Skip to content

Commit

Permalink
DDEV ARM64 Docker images (#2454)
Browse files Browse the repository at this point in the history
  • Loading branch information
dennisameling committed Sep 25, 2020
1 parent 15ece72 commit 93743aa
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 95 deletions.
8 changes: 7 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -262,19 +262,25 @@ jobs:
- run:
command: ./.circleci/linux_circle_vm_setup.sh
name: Circle VM setup - tools, docker, golang
- run:
command: ./.circleci/linux_docker_buildx_setup.sh
name: Docker buildx setup for multi-arch builds

- run:
command: |
. ~/.bashrc
for dir in containers/*
for dir in containers/*/
do pushd $dir
echo "--- Build container $dir"
time make container DOCKER_ARGS=--no-cache EXTRA_PATH=/home/linuxbrew/.linuxbrew/bin
echo "--- Test container $dir"
time make test EXTRA_PATH=/home/linuxbrew/.linuxbrew/bin
echo "--- Cross-compile container $dir"
time make multi-arch EXTRA_PATH=/home/linuxbrew/.linuxbrew/bin
popd
done
name: linux container test

- save_cache:
key: linux-v13
paths:
Expand Down
16 changes: 16 additions & 0 deletions .circleci/linux_docker_buildx_setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
sudo apt-get install docker-ce-cli binfmt-support qemu-user-static

BUILDX_BINARY_URL="https://github.com/docker/buildx/releases/download/v0.4.2/buildx-v0.4.2.linux-amd64"

curl --output docker-buildx \
--silent --show-error --location --fail --retry 3 \
"$BUILDX_BINARY_URL"

mkdir -p ~/.docker/cli-plugins
mv docker-buildx ~/.docker/cli-plugins
chmod a+x ~/.docker/cli-plugins/docker-buildx

# We need this to get arm64 qemu to work https://github.com/docker/buildx/issues/138#issuecomment-569240559
docker run --privileged --rm docker/binfmt:a7996909642ee92942dcd6cff44b9b95f08dad64
if ! docker buildx inspect ddev-builder-multi --bootstrap >/dev/null; then docker buildx create --name ddev-builder-multi; fi
docker buildx use ddev-builder-multi
25 changes: 25 additions & 0 deletions containers/containers_shared.mak
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# In CI environments, use the plain Docker build progress to not overload the CI logs
PROGRESS := $(if $(CI),plain,auto)

SANITIZED_DOCKER_REPO = $(subst /,_,$(DOCKER_REPO))

DOTFILE_IMAGE = $(subst /,_,$(IMAGE))-$(VERSION)

container: .container-$(DOTFILE_IMAGE) container-name

.container-$(DOTFILE_IMAGE): $(wildcard Dockerfile Dockerfile.in) container-name
# UPSTREAM_REPO in the Dockerfile.in will be changed to the value from Makefile; this is deprecated.
# There's no reason not to just use Dockerfile now.
@if [ -f Dockerfile.in ]; then sed -e 's|UPSTREAM_REPO|$(UPSTREAM_REPO)|g' Dockerfile.in > .dockerfile; else cp Dockerfile .dockerfile; fi
# Add information about the commit into .docker_image, to be added to the build.
@echo "$(DOCKER_REPO):$(VERSION) commit=$(shell git describe --tags --always)" >.docker_image
# Add the .docker_image into the build so it's easy to figure out where a docker image came from.
@echo "ADD .docker_image /$(SANITIZED_DOCKER_REPO)_VERSION_INFO.txt" >>.dockerfile
docker buildx build --platform linux/amd64 --progress=$(PROGRESS) -o type=docker -t $(DOCKER_REPO):$(VERSION) $(DOCKER_ARGS) -f .dockerfile .
@docker images -q $(DOCKER_REPO):$(VERSION) >$@

container-name:
@echo "container: $(DOCKER_REPO):$(VERSION)"

push:
docker buildx build --push --platform $(BUILD_ARCHS) --progress=$(PROGRESS) -t $(DOCKER_REPO):$(VERSION) $(DOCKER_ARGS) -f .dockerfile .
55 changes: 31 additions & 24 deletions containers/ddev-dbserver/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,57 +31,65 @@ VERSION := $(shell git describe --tags --always --dirty)
# This version-strategy uses a manual value to set the version string
#VERSION := 1.2.3

# Each section of the Makefile is included from standard components below.
# If you need to override one, import its contents below and comment out the
# include. That way the base components can easily be updated as our general needs
# change.
#include ../../../build-tools/makefile_components/base_build_go.mak
#include ../../build-tools/makefile_components/base_build_python-docker.mak
#include ../../build-tools/makefile_components/base_container.mak
#include ../../build-tools/makefile_components/base_push.mak
#include build-tools/makefile_components/base_test_go.mak
#include ../../build-tools/makefile_components/base_test_python.mak

build: container

# The format here is majorversion:pinnedimageversion
# This allows to pin the version (as currently required with 8.0.19
MARIADB_VERSIONS=5.5:5.5 10.0:10.0 10.1:10.1 10.2:10.2 10.3:10.3 10.4:10.4 10.5:10.5
MYSQL_VERSIONS=5.5:5.5 5.6:5.6 5.7:5.7 8.0:8.0.19
MARIADB_VERSIONS_amd64=5.5:5.5 10.0:10.0 10.1:10.1 10.2:10.2 10.3:10.3 10.4:10.4 10.5:10.5
MYSQL_VERSIONS_amd64=5.5:5.5 5.6:5.6 5.7:5.7 8.0:8.0.19
MARIADB_VERSIONS_arm64=10.2:10.2 10.3:10.3 10.4:10.4 10.5:10.5
# MySQL images on Docker Hub currently are amd64 only
MYSQL_VERSIONS_arm64=

# In CI environments, use the plain Docker build progress to not overload the CI logs
PROGRESS := $(if $(CI),plain,auto)

container: mariadb_containers mysql_containers

mariadb_containers:
for item in $(MARIADB_VERSIONS); do \
for item in $(MARIADB_VERSIONS_amd64); do \
set -euo pipefail ; \
export baseversion=$$(echo $$item | awk -F ':' '{print $$1}'); \
export fullversion=$$(echo $$item | awk -F ':' '{print $$2}'); \
printf "\n\n========== Building MariaDB $${baseversion} with image $${fullversion} ==========\n"; \
docker build $(DOCKER_ARGS) --build-arg="DBVERSION=$${baseversion}" --build-arg="PARENTIMAGEVERSION=$$fullversion" --build-arg="DBTYPE=mariadb" -t "drud/ddev-dbserver-mariadb-$${baseversion}:$(VERSION)" . ; \
docker buildx build -o type=docker $(DOCKER_ARGS) --progress=$(PROGRESS) --build-arg="DBVERSION=$${baseversion}" --build-arg="PARENTIMAGEVERSION=$$fullversion" --build-arg="DBTYPE=mariadb" -t "drud/ddev-dbserver-mariadb-$${baseversion}:$(VERSION)" . ; \
done

mysql_containers:
for item in $(MYSQL_VERSIONS) ; do \
for item in $(MYSQL_VERSIONS_amd64) ; do \
set -euo pipefail ; \
export baseversion=$$(echo $$item | awk -F ':' '{print $$1}'); \
export fullversion=$$(echo $$item | awk -F ':' '{print $$2}'); \
printf "\n\n========== Building MySQL $${baseversion} with image $${fullversion} ==========\n", ${baseversion}, ${fullversion}; \
docker build $(DOCKER_ARGS) --build-arg="DBVERSION=$$baseversion" --build-arg="PARENTIMAGEVERSION=$$fullversion" --build-arg="DBTYPE=mysql" -t "drud/ddev-dbserver-mysql-$${baseversion%%%.*}:$(VERSION)" . ; \
docker buildx build -o type=docker $(DOCKER_ARGS) --progress=$(PROGRESS) --build-arg="DBVERSION=$$baseversion" --build-arg="PARENTIMAGEVERSION=$$fullversion" --build-arg="DBTYPE=mysql" -t "drud/ddev-dbserver-mysql-$${baseversion%%%.*}:$(VERSION)" . ; \
done

push: container
for item in $(MARIADB_VERSIONS); do \
# Below has mariadb_containers and mysql_containers as a prerequisite because those build the amd64 images.
# So, the multi-arch approach here is a bit different from the ones in the other Makefiles.
multi-arch: mariadb_containers mysql_containers
for item in $(MARIADB_VERSIONS_arm64); do \
set -euo pipefail ; \
export baseversion=$$(echo $$item | awk -F ':' '{print $$1}'); \
export fullversion=$$(echo $$item | awk -F ':' '{print $$2}'); \
printf "\n\n========== Building MariaDB $${baseversion} with image $${fullversion} ==========\n"; \
docker buildx build --platform=linux/arm64 $(DOCKER_ARGS) --progress=$(PROGRESS) --build-arg="DBVERSION=$${baseversion}" --build-arg="PARENTIMAGEVERSION=$$fullversion" --build-arg="DBTYPE=mariadb" -t "drud/ddev-dbserver-mariadb-$${baseversion}:$(VERSION)" . ; \
done

push:
for item in $(MARIADB_VERSIONS_amd64); do \
set -euo pipefail ;\
export baseversion=$$(echo $$item | awk -F ':' '{print $$1}'); \
docker push "drud/ddev-dbserver-mariadb-$${baseversion%%%.*}:$(VERSION)"; \
export fullversion=$$(echo $$item | awk -F ':' '{print $$2}'); \
export archs=$$(if [[ "$(MARIADB_VERSIONS_arm64)" == *"$$item"* ]]; then echo "linux/amd64,linux/arm64"; else echo "linux/amd64"; fi);\
docker buildx build --push --platform $${archs} $(DOCKER_ARGS) --progress=$(PROGRESS) --build-arg="DBVERSION=$${baseversion}" --build-arg="PARENTIMAGEVERSION=$$fullversion" --build-arg="DBTYPE=mariadb" -t "drud/ddev-dbserver-mariadb-$${baseversion}:$(VERSION)" .; \
done
for item in $(MYSQL_VERSIONS) ; do \
for item in $(MYSQL_VERSIONS_amd64) ; do \
set -euo pipefail ;\
export baseversion=$$(echo $$item | awk -F ':' '{print $$1}'); \
docker push "drud/ddev-dbserver-mysql-$${baseversion%%%.*}:$(VERSION)"; \
export fullversion=$$(echo $$item | awk -F ':' '{print $$2}'); \
docker buildx build --push --platform linux/amd64 $(DOCKER_ARGS) --progress=$(PROGRESS) --build-arg="DBVERSION=$$baseversion" --build-arg="PARENTIMAGEVERSION=$$fullversion" --build-arg="DBTYPE=mysql" -t "drud/ddev-dbserver-mysql-$${baseversion%%%.*}:$(VERSION)" .; \
done


test: container
bash ./test/test_dbserver.sh $(VERSION) # bash execution just for windows make

Expand All @@ -93,4 +101,3 @@ clean:
if docker image inspect $(DOCKER_REPO)-mysql-${item}:$(VERSION) >/dev/null 2>&1; then docker rmi -f $(DOCKER_REPO)-mysql-$${item}:$(VERSION); fi; \
done
@rm -rf .container-* .dockerfile* .push-* linux darwin windows container VERSION.txt .docker_image

53 changes: 44 additions & 9 deletions containers/ddev-router/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,62 @@
FROM nginx:1.18

ENV MKCERT_VERSION=v1.4.1
ENV MKCERT_VERSION=v1.4.4

ENV DEBIAN_FRONTEND noninteractive
ENV DOCKER_GEN_VERSION 0.7.4
ENV DOCKER_GEN_VERSION 0.7.7
ENV DOCKER_HOST unix:///tmp/docker.sock

# TARGETPLATFORM is Docker buildx's target platform (e.g. linux/arm64), while
# BUILDPLATFORM is the platform of the build host (e.g. linux/amd64)
ARG TARGETPLATFORM
ARG BUILDPLATFORM

SHELL ["/bin/bash", "-c"]

RUN mkdir /tmp/ddev && \
if [[ $TARGETPLATFORM == "linux/arm64" ]]; then \
printf '# jwilder/forego doesnt have an arm64 download so we resort to the original forego repo \n\
FORGO_IS_TGZ="true" \n\
FORGO_FILENAME="forego-stable-linux-arm64.tgz" \n\
FORGO_URL="https://bin.equinox.io/c/ekMN3bCZFUn/forego-stable-linux-arm64.tgz" \n\
DOCKER_GEN_ARCH="linux-arm64" \n\
MKCERT_ARCH="linux-arm64"' > /tmp/ddev/vars; \

else \
printf 'FORGO_IS_TGZ="false" \n\
FORGO_URL="https://github.com/jwilder/forego/releases/download/v0.16.1/forego" \n\
DOCKER_GEN_ARCH="linux-amd64" \n\
MKCERT_ARCH="linux-amd64"' > /tmp/ddev/vars; \
fi

RUN apt-get -qq update && \
apt-get -qq install --no-install-recommends --no-install-suggests -y \
ca-certificates certbot curl iputils-ping less python-certbot-nginx procps telnet vim wget && \
apt-get autoremove -y && \
apt-get clean -y && \
rm -rf /var/lib/apt/lists/*

ADD https://github.com/jwilder/forego/releases/download/v0.16.1/forego /usr/local/bin/forego
RUN source /tmp/ddev/vars && \
if [[ $FORGO_IS_TGZ == "true" ]]; then \
wget -q $FORGO_URL && \
tar -C /usr/local/bin -xvzf $FORGO_FILENAME && \
rm /$FORGO_FILENAME && \
chmod ugo+x /usr/local/bin/forego; \
else \
curl -sSL $FORGO_URL -o /usr/local/bin/forego && \
chmod ugo+x /usr/local/bin/forego; \
fi

RUN wget -q https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz && \
tar -C /usr/local/bin -xvzf docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz && \
rm /docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz && \
chmod ugo+x /usr/local/bin/forego && \
mkdir -p /etc/nginx/certs /mnt/ddev-global-cache/mkcert
RUN source /tmp/ddev/vars && \
DOCKER_GEN_FILE="docker-gen-${DOCKER_GEN_ARCH}-${DOCKER_GEN_VERSION}.tar.gz" && \
wget -q https://github.com/drud/docker-gen/releases/download/${DOCKER_GEN_VERSION}/${DOCKER_GEN_FILE} && \
tar -C /usr/local/bin -xvzf $DOCKER_GEN_FILE && \
rm /$DOCKER_GEN_FILE

RUN mkdir -p /etc/nginx/certs /mnt/ddev-global-cache/mkcert

RUN curl -sSL https://github.com/FiloSottile/mkcert/releases/download/$MKCERT_VERSION/mkcert-$MKCERT_VERSION-linux-amd64 -o /usr/local/bin/mkcert && chmod +x /usr/local/bin/mkcert && mkdir -p /root/.local/share && ln -s /mnt/ddev-global-cache/mkcert /root/.local/share/mkcert && mkcert -install
RUN source /tmp/ddev/vars && \
curl -sSL https://github.com/drud/mkcert/releases/download/${MKCERT_VERSION}/mkcert-${MKCERT_VERSION}-${MKCERT_ARCH} -o /usr/local/bin/mkcert && chmod +x /usr/local/bin/mkcert && mkdir -p /root/.local/share && ln -s /mnt/ddev-global-cache/mkcert /root/.local/share/mkcert && mkcert -install

# Configure Nginx and apply fix for very long server names
RUN echo "daemon off;" >> /etc/nginx/nginx.conf \
Expand Down
22 changes: 12 additions & 10 deletions containers/ddev-router/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,18 @@ VERSION := $(shell git describe --tags --always --dirty)
# This version-strategy uses a manual value to set the version string
#VERSION := 1.2.3

# Each section of the Makefile is included from standard components below.
# If you need to override one, import its contents below and comment out the
# include. That way the base components can easily be updated as our general needs
# change.
#include build-tools/makefile_components/base_build_go.mak
include ../../build-tools/makefile_components/base_build_python-docker.mak
include ../../build-tools/makefile_components/base_container.mak
include ../../build-tools/makefile_components/base_push.mak
#include build-tools/makefile_components/base_test_go.mak
include ../../build-tools/makefile_components/base_test_python.mak
# In CI environments, use the plain Docker build progress to not overload the CI logs
PROGRESS := $(if $(CI),plain,auto)

# Tests always run against amd64 (build host). Once tests have passed, a multi-arch build
# will be generated and pushed (the amd64 build will be cached automatically to prevent it from building twice).
BUILD_ARCHS=linux/amd64,linux/arm64

include ../containers_shared.mak

test: container
bash -c test/containertest.sh

multi-arch:
docker buildx build --platform $(BUILD_ARCHS) --progress=$(PROGRESS) -t $(DOCKER_REPO):$(VERSION) $(DOCKER_ARGS) .; \
echo "created multi-arch builds $(BUILD_ARCHS) for $(DOCKER_REPO)";
2 changes: 1 addition & 1 deletion containers/ddev-ssh-agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM bitnami/minideb:buster
FROM debian:buster-slim

RUN apt-get update && apt-get install -y bash expect file openssh-client socat sudo psmisc && sudo apt autoclean

Expand Down
24 changes: 13 additions & 11 deletions containers/ddev-ssh-agent/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ VERSION := $(shell git describe --tags --always --dirty)
# This version-strategy uses a manual value to set the version string
#VERSION := 1.2.3

# Each section of the Makefile is included from standard components below.
# If you need to override one, import its contents below and comment out the
# include. That way the base components can easily be updated as our general needs
# change.
#include ../build-tools/makefile_components/base_build_go.mak
#include ../../build-tools/makefile_components/base_build_python-docker.mak
include ../../build-tools/makefile_components/base_container.mak
include ../../build-tools/makefile_components/base_push.mak
#include build-tools/makefile_components/base_test_go.mak
#include build-tools/makefile_components/base_test_python.mak
# In CI environments, use the plain Docker build progress to not overload the CI logs
PROGRESS := $(if $(CI),plain,auto)

# Tests always run against amd64 (build host). Once tests have passed, a multi-arch build
# will be generated and pushed (the amd64 build will be cached automatically to prevent it from building twice).
BUILD_ARCHS=linux/amd64,linux/arm64

include ../containers_shared.mak

multi-arch:
docker buildx build --platform $(BUILD_ARCHS) --progress=$(PROGRESS) -t $(DOCKER_REPO):$(VERSION) $(DOCKER_ARGS) .; \
echo "created multi-arch builds $(BUILD_ARCHS) for $(DOCKER_REPO)";

test:
true >/dev/null
true >/dev/null

0 comments on commit 93743aa

Please sign in to comment.