diff --git a/Dockerfile b/Dockerfile index ea04baf..7958795 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ ARG DIST=nginx:1.19.6 FROM $DIST -ARG ARCH=amd64 + +# Set by `docker buildx build` +ARG TARGETPLATFORM # Delete sym links from nginx image, install logrotate RUN rm /var/log/nginx/access.log && \ @@ -8,23 +10,25 @@ RUN rm /var/log/nginx/access.log && \ WORKDIR /root +RUN apt-get update && \ + apt-get install -y python ruby cron iproute2 apache2-utils logrotate wget && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +# Need this already now, but cannot copy remainder of fs_overlay yet +COPY ./fs_overlay/bin/archname /bin/ + ENV S6_OVERLAY_VERSION v1.22.1.0 ENV DOCKER_GEN_VERSION 0.7.4 ENV ACME_TINY_VERSION 4.1.0 -ADD https://github.com/just-containers/s6-overlay/releases/download/$S6_OVERLAY_VERSION/s6-overlay-$ARCH.tar.gz /tmp/ -ADD https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-$ARCH-$DOCKER_GEN_VERSION.tar.gz /tmp/ -ADD https://raw.githubusercontent.com/diafygi/acme-tiny/$ACME_TINY_VERSION/acme_tiny.py /bin/acme_tiny - -RUN tar xzf /tmp/s6-overlay-$ARCH.tar.gz -C / &&\ - tar -C /bin -xzf /tmp/docker-gen-linux-${ARCH}-$DOCKER_GEN_VERSION.tar.gz && \ - rm /tmp/docker-gen-linux-$ARCH-$DOCKER_GEN_VERSION.tar.gz && \ - rm /tmp/s6-overlay-$ARCH.tar.gz && \ - rm /etc/nginx/conf.d/default.conf && \ - apt-get update && \ - apt-get install -y python ruby cron iproute2 apache2-utils logrotate && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* +RUN sh -c "wget -q https://github.com/just-containers/s6-overlay/releases/download/$S6_OVERLAY_VERSION/s6-overlay-`archname s6-overlay`.tar.gz -O -" | \ + tar xzC / +RUN sh -c "wget -q https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-`archname docker-gen`-$DOCKER_GEN_VERSION.tar.gz -O -" | \ + tar xzC /bin +RUN wget -q https://raw.githubusercontent.com/diafygi/acme-tiny/$ACME_TINY_VERSION/acme_tiny.py -O /bin/acme_tiny + +RUN rm /etc/nginx/conf.d/default.conf COPY ./fs_overlay / diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..546f3ad --- /dev/null +++ b/Makefile @@ -0,0 +1,56 @@ +# Create multi-platform docker image. If you have native systems around, using +# them will be much more efficient at build time. See e.g. +# https://netfuture.ch/2020/05/multi-arch-docker-image-easy/ +BUILDXDETECT = ${HOME}/.docker/cli-plugins/docker-buildx + +# Just one of the many files created +QEMUDETECT = /proc/sys/fs/binfmt_misc/qemu-m68k + +# Override this, if you want to use your own registry +REGISTRY = steveltn +# For version x.y.z, output "-t …:x.yz -t …:x.y -t …:x"; +# for anything else, output nothing +BASETAG = ${REGISTRY}/https-portal +VERSIONTAGS = $(shell git describe --tags | \ + sed -n -e 's,^\(\(\([0-9]*\).[0-9]*\).[0-9]*\).*,-t ${BASETAG}:\1 -t ${BASETAG}:\2 -t ${BASETAG}:\3,p') + +# For platform compatibility/naming matrix, see `./fs_overlay/bin/archname` +# +# Not building for linux/arm/v5, as building the docker image fails with: +# Error while loading /usr/sbin/dpkg-split: No such file or directory +# Error while loading /usr/sbin/dpkg-deb: No such file or directory + +PLATFORMS = linux/386,linux/amd64,linux/arm/v7,linux/arm64/v8 + +docker-multiarch: qemu buildx docker-multiarch-builder + docker login + docker buildx build --builder docker-multiarch --pull --push \ + --platform ${PLATFORMS} \ + ${VERSIONTAGS} -t ${BASETAG}:latest . + +qemu: ${QEMUDETECT} +${QEMUDETECT}: + docker pull multiarch/qemu-user-static + docker run --privileged multiarch/qemu-user-static --reset -p yes + docker ps -a | sed -n 's, *multiarch/qemu-user-static.*,,p' \ + | (xargs docker rm 2>&1 || \ + echo "Cannot remove docker container on ZFS; retry after next reboot") \ + | grep -v 'dataset is busy' + +buildx: ${BUILDXDETECT} +${BUILDXDETECT}: + @echo +# Output of `uname -m` is too different + @echo '*** `docker buildx` missing. Install binary for this machine architecture' + @echo '*** from `https://github.com/docker/buildx/releases/latest`' + @echo '*** to `~/.docker/cli-plugins/docker-buildx` and `chmod +x` it.' + @echo + @exit 1 + +docker-multiarch-builder: qemu buildx + if ! docker buildx ls | grep -w docker-multiarch > /dev/null; then \ + docker buildx create --name docker-multiarch && \ + docker buildx inspect --builder docker-multiarch --bootstrap; \ + fi + +.PHONY: qemu buildx docker-multiarch docker-multiarch-builder diff --git a/Readme.armhf b/Readme.armhf index 3b9e602..b6e5ee2 100644 --- a/Readme.armhf +++ b/Readme.armhf @@ -1,5 +1,23 @@ -#to build armhf image from amd64 machine: -#Install qemu, see https://github.com/multiarch/qemu-user-static -docker run --rm --privileged multiarch/qemu-user-static --reset -p yes -#Pass relevant args to the docker build cmd -docker build --build-arg DIST=arm32v7/nginx:1.17.3 --build-arg ARCH=armhf -t https-portal:armhf-master . +# Cross-platform/multi-platform docker images +Docker images for different and/or multiple architectures may be built using +`sudo make docker-multiarch`. + +# Single-platform image for the current platform (compatibility) +As usual: `docker build .` + +# Basic multi-platform build +Publish to your private docker registry, using the default set of platforms: + +`sudo make docker-multiarch REGISTRY=docker.example.com` + +# Specify your list of platforms +`sudo make docker-multiarch REGISTRY=docker.example.com PLATFORMS=linux/arm/v7` + +For details on the supported platforms, see `./fs_overlay/bin/archname`. + +# Set-up +In order to support cross-platform building, you need to install +`docker-buildx`. It can be downloaded from +https://github.com/docker/buildx/releases/latest and needs to be installed +as `~/.docker/cli-plugins/docker-buildx` and `chmod +x`ed. See +https://github.com/docker/buildx for more information. diff --git a/fs_overlay/bin/archname b/fs_overlay/bin/archname new file mode 100755 index 0000000..b93f296 --- /dev/null +++ b/fs_overlay/bin/archname @@ -0,0 +1,80 @@ +#/bin/sh +# Usage: archname.sh +# +# Outputs the correct architecture string for the named package, translating +# between the different platform strings. The nice things about standards… +# PACKAGE is one of "s6-overlay" or "docker-gen" +# +# Reads the docker architecture from $TARGETPLATFORM (set by `docker buildx +# build`) and outputs the appropriate per-package architecture name. If +# $TARGETPLATFORM is unset (using legacy `docker build`), it is determined from +# the output for `arch`, which is unreliable in case it is run in an emulator. +# If you really plan to build inside an emulator with the legacy build process, +# you are on your own. + + +# Platform compatibility/naming matrix as of 2020-01-17: +# - Nginx: https://hub.docker.com/_/nginx?tab=tags +# - S6 Overlay: https://github.com/just-containers/s6-overlay/releases +# - Docker-Gen: https://github.com/jwilder/docker-gen/releases +# - ACME-Tiny: No architecture/platform dependencies +# - Stars elsewhere are not part of the output, but indicate special values +# +# Nginx (Docker) | `arch` output | S6 Overlay | Docker-Gen | ACME-Tiny +# ---------------+---------------+------------+------------+---------- +# linux/386 | x86_64* | x86 | i386 | * +# linux/amd64 | x86_64 | amd64 | amd64 | * +# linux/arm/v5 | armv7l* | arm | armel | * +# linux/arm/v6* | armv7l* | arm | armel | * +# linux/arm/v7 | armv7l | armhf | armhf | * +# linux/arm64/v8 | aarch64 | aarch64 | armhf* | * +# linux/mips64le | mips64 | --- | --- | * +# linux/ppc64le | ppc6le | ppc64le | --- | * +# linux/s390x | s390x | --- | --- | * +# +# Notes: +# - nginx:1.19.6 does not support linux/arm/v6 +# - `arch` output as reported potentially inside the emulater with +# `docker buildx build --builder docker-multiarch --platform ...` +# - Assuming linux/arm/v5 and linux/arm/v6 are user-level compatible (for +# S6 Overlay and Docker-Gen) +# - Assuming Docker-Gen armhf is user-level compatible with linux/arm64/v8 + +# This is only used for `docker build`, so we should not run inside the +# emulator: +if [ "x$TARGETPLATFORM" = "x" ]; then + case `arch` in + # Extend this list as necessary + x86_64) TARGETPLATFORM=linux/amd64;; + armv7l) TARGETPLATFORM=linux/arm/v7;; + aarch64) TARGETPLATFORM=linux/arm64/v8;; + *) echo "$0: Empty TARGETPLATFORM, unsupported ARCH: `arch`">&2; exit 1;; + esac +fi + +case "$1" in + s6-overlay) + case "$TARGETPLATFORM" in + linux/386) echo x86;; + linux/amd64) echo amd64;; + linux/arm/v5) echo arm;; + linux/arm/v6) echo arm;; + linux/arm/v7) echo armhf;; + linux/arm64/v8) echo aarch64;; + *) echo "$0: Unsupported TARGETPLATFORM: $TARGETPLATFORM" >&2; exit 1;; + esac + ;; + docker-gen) + case "$TARGETPLATFORM" in + linux/386) echo i386;; + linux/amd64) echo amd64;; + linux/arm/v5) echo armel;; + linux/arm/v6) echo armel;; + linux/arm/v7) echo armhf;; + linux/arm64/v8) echo armhf;; + *) echo "$0: Unsupported TARGETPLATFORM: $TARGETPLATFORM" >&2; exit 1;; + esac + ;; + *) + echo "$0: Unsupported package: $1" >&2; exit 1;; +esac