|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# This script wraps Docker and Docker BuildX to build multiarch Zulip images. |
| 4 | +# Make sure a recent Docker and BuildX are installed on your system - Docker |
| 5 | +# Desktop users (on any OS) should be good to go, those using Linux |
| 6 | +# distribution's builds of Docker will need to find the correct packages. |
| 7 | +# |
| 8 | +# To use locally, override the environment variables REGISTRY, REGISTRY_TAG |
| 9 | +# (perhaps to 'local'), and optionally BUILDX_PLATFORMS. Additionally, |
| 10 | +# PUSH_LATEST_TAG can be set to 1 to additonally tag :latest when pushing to |
| 11 | +# the registry. Then, run the script without arguments. For example: |
| 12 | +# |
| 13 | +# REGISTRY=docker.example.com/myorg/zulip REGISTRY_TAG=local PUSH_LATEST_TAG=1 |
| 14 | +# ./build_and_push_image.sh |
| 15 | +# |
| 16 | +# Note: EXTERNAL_QEMU=1 is required when it's unsafe or undesired to manage |
| 17 | +# binfmt helpers, for example within CI systems like GitHub Actions (use |
| 18 | +# docker/setup-buildx-action@v1 instead). |
| 19 | +# |
| 20 | +# By default, REGISTRY:REGISTRY_TAG will be built for linux/amd64 and |
| 21 | +# linux/arm64. Adding other platforms to this list is unsupported and will |
| 22 | +# almost certainly not work, but the list can be shrunk. REGISTRY must be set |
| 23 | +# to something the builder has push access to, because BuildX images and |
| 24 | +# manifests are not loaded into the host's Docker registry (an upstream |
| 25 | +# limitation). |
| 26 | +# |
| 27 | +# If building for architectures other than that the host runs on, ne can expect |
| 28 | +# this step to take many multiples of the time it takes to build the Zulip |
| 29 | +# image for just the native architecture. If it takes 10 minutes to build the |
| 30 | +# amd64 image by itself, expect cross-compiling the arm64 image to take 30-60 |
| 31 | +# minutes on most currently-common hardware. Currently, distributing the image |
| 32 | +# builds to multiple machines (perhaps to allow the arm64 image to build on a |
| 33 | +# native arm64 host for efficiency) is unsupported. |
| 34 | +# |
| 35 | +# Assuming all goes well, REGISTRY:REGISTRY_TAG will point to a multiarch |
| 36 | +# manifest referring to an image for each of BUILDX_PLATFORMS, which can then |
| 37 | +# be rolled out to your infrastructure, used in Docker Compose, etc. |
| 38 | +# |
| 39 | +# Please report bugs with this script or anything it runs, or with running |
| 40 | +# Zulip on arm64 in general, at https://github.com/zulip/docker-zulip and/or at |
| 41 | +# https://chat.zulip.org |
| 42 | + |
| 43 | +set -ex |
| 44 | + |
| 45 | +REGISTRY="${REGISTRY:-ghcr.io/zulip/zulip}" |
| 46 | +REGISTRY_TAG="${REGISTRY_TAG:-$(tail -n 1 < "$(git rev-parse --show-toplevel)/IMAGE_TAG")}" |
| 47 | +PRIMARY_IMAGE="${REGISTRY}:${REGISTRY_TAG}" |
| 48 | + |
| 49 | +if [ "${SKIP_PULL_CHECK}" != "1" ]; then |
| 50 | + if docker pull "${PRIMARY_IMAGE}"; then |
| 51 | + echo "Image ${PRIMARY_IMAGE} already exists, refusing to overwrite!" > /dev/stderr |
| 52 | + exit 1 |
| 53 | + fi |
| 54 | +fi |
| 55 | + |
| 56 | +PUSH_LATEST_TAG="${PUSH_LATEST_TAG:-0}" |
| 57 | + |
| 58 | +if [ "${PUSH_LATEST_TAG}" = "1" ]; then |
| 59 | + PUSH_LATEST_TAG_ARG=("-t" "${REGISTRY}:latest") |
| 60 | +fi |
| 61 | + |
| 62 | +# Default to creating our own buildx context, as "default", using the native |
| 63 | +# "docker" driver, can result in errors like the following when using Linux |
| 64 | +# distros' Docker and not Docker Desktop: |
| 65 | +# |
| 66 | +# ERROR: multiple platforms feature is currently not supported for docker |
| 67 | +# driver. Please switch to a different driver (eg. "docker buildx create |
| 68 | +# --use") |
| 69 | +BUILDX_BUILDER="${BUILDX_BUILDER:-zulip}" |
| 70 | +BUILDX_PLATFORMS="${BUILDX_PLATFORMS:-linux/amd64,linux/arm64}" |
| 71 | + |
| 72 | +if [ "${EXTERNAL_QEMU}" != "1" ]; then |
| 73 | + # --credential yes is required to run sudo within qemu, without it the |
| 74 | + # effective UID after a call to sudo will not be 0 and sudo in cross-built |
| 75 | + # containers (eg. the arm64 build if running on an amd64 host) will fail. |
| 76 | + # See also: https://github.com/crazy-max/ghaction-docker-buildx/issues/213. |
| 77 | + # |
| 78 | + # We're allowing failures here (|| true) for two main reasons: |
| 79 | + # |
| 80 | + # - BUILDX_PLATFORMS can be overridden to a single, native platform |
| 81 | + # (meaning this QEMU reset won't be necessary anyway) |
| 82 | + # - On ZFS<2.2 root filesystems, this incantation can fail due to |
| 83 | + # Docker-side dataset teardown issues as documented in |
| 84 | + # https://github.com/moby/moby/issues/40132. The QEMU reset may have |
| 85 | + # succeeded despite the Docker daemon errors, so we'll try to power |
| 86 | + # through. |
| 87 | + docker run \ |
| 88 | + --rm \ |
| 89 | + --privileged \ |
| 90 | + multiarch/qemu-user-static \ |
| 91 | + --reset \ |
| 92 | + -p yes \ |
| 93 | + --credential yes \ |
| 94 | + || true |
| 95 | +fi |
| 96 | + |
| 97 | +(docker buildx ls | grep "${BUILDX_BUILDER}" >/dev/null 2>&1) || { |
| 98 | + docker buildx create \ |
| 99 | + --name "${BUILDX_BUILDER}" \ |
| 100 | + --platform "${BUILDX_PLATFORMS}" \ |
| 101 | + --bootstrap \ |
| 102 | + --use |
| 103 | +} |
| 104 | + |
| 105 | +docker buildx build \ |
| 106 | + --platform "${BUILDX_PLATFORMS}" \ |
| 107 | + -t "${PRIMARY_IMAGE}" \ |
| 108 | + "${PUSH_LATEST_TAG_ARG[@]}" \ |
| 109 | + --push \ |
| 110 | + . |
0 commit comments