| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- #!/bin/bash
- source ./hooks/arches.sh
- export DOCKER_CLI_EXPERIMENTAL=enabled
- # Join a list of args with a single char.
- # Ref: https://stackoverflow.com/a/17841619
- join() { local IFS="$1"; shift; echo "$*"; }
- set -ex
- echo ">>> Starting local Docker registry..."
- # Docker Buildx's `docker-container` driver is needed for multi-platform
- # builds, but it can't access existing images on the Docker host (like the
- # cross-compiled ones we just built). Those images first need to be pushed to
- # a registry -- Docker Hub could be used, but since it's not trivial to clean
- # up those intermediate images on Docker Hub, it's easier to just run a local
- # Docker registry, which gets cleaned up automatically once the build job ends.
- #
- # https://docs.docker.com/registry/deploying/
- # https://hub.docker.com/_/registry
- #
- # Use host networking so the buildx container can access the registry via
- # localhost.
- #
- docker run -d --name registry --network host registry:2 # defaults to port 5000
- # Docker Hub sets a `DOCKER_REPO` env var with the format `index.docker.io/user/repo`.
- # Strip the registry portion to construct a local repo path for use in `Dockerfile.buildx`.
- LOCAL_REGISTRY="localhost:5000"
- REPO="${DOCKER_REPO#*/}"
- LOCAL_REPO="${LOCAL_REGISTRY}/${REPO}"
- echo ">>> Pushing images to local registry..."
- for arch in ${arches[@]}; do
- docker_image="${DOCKER_REPO}:${DOCKER_TAG}-${arch}"
- local_image="${LOCAL_REPO}:${DOCKER_TAG}-${arch}"
- docker tag "${docker_image}" "${local_image}"
- docker push "${local_image}"
- done
- echo ">>> Setting up Docker Buildx..."
- # Same as earlier, use host networking so the buildx container can access the
- # registry via localhost.
- #
- # Ref: https://github.com/docker/buildx/issues/94#issuecomment-534367714
- #
- docker buildx create --name builder --use --driver-opt network=host
- echo ">>> Running Docker Buildx..."
- tags=("${DOCKER_REPO}:${DOCKER_TAG}")
- # If the Docker tag starts with a version number, assume the latest release
- # is being pushed. Add an extra tag (`latest` or `alpine`, as appropriate)
- # to make it easier for users to track the latest release.
- if [[ "${DOCKER_TAG}" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
- if [[ "${DOCKER_TAG}" == *alpine ]]; then
- tags+=(${DOCKER_REPO}:alpine)
- else
- tags+=(${DOCKER_REPO}:latest)
- fi
- fi
- tag_args=()
- for tag in "${tags[@]}"; do
- tag_args+=(--tag "${tag}")
- done
- # Docker Buildx takes a list of target platforms (OS/arch/variant), so map
- # the arch list to a platform list (assuming the OS is always `linux`).
- declare -A arch_to_platform=(
- [amd64]="linux/amd64"
- [armv6]="linux/arm/v6"
- [armv7]="linux/arm/v7"
- [arm64]="linux/arm64"
- )
- platforms=()
- for arch in ${arches[@]}; do
- platforms+=("${arch_to_platform[$arch]}")
- done
- platforms="$(join "," "${platforms[@]}")"
- # Run the build, pushing the resulting images and multi-arch manifest list to
- # Docker Hub. The Dockerfile is read from stdin to avoid sending any build
- # context, which isn't needed here since the actual cross-compiled images
- # have already been built.
- docker buildx build \
- --network host \
- --build-arg LOCAL_REPO="${LOCAL_REPO}" \
- --build-arg DOCKER_TAG="${DOCKER_TAG}" \
- --platform "${platforms}" \
- "${tag_args[@]}" \
- --push \
- - < ./docker/Dockerfile.buildx
- # Add an extra arch-specific tag for `arm32v6`; Docker can't seem to properly
- # auto-select that image on ARMv6 platforms like Raspberry Pi 1 and Zero
- # (https://github.com/moby/moby/issues/41017).
- #
- # Note that we use `arm32v6` instead of `armv6` to be consistent with the
- # existing bitwarden_rs tags, which adhere to the naming conventions of the
- # Docker per-architecture repos (e.g., https://hub.docker.com/u/arm32v6).
- # Unfortunately, these per-arch repo names aren't always consistent with the
- # corresponding platform (OS/arch/variant) IDs, particularly in the case of
- # 32-bit ARM arches (e.g., `linux/arm/v6` is used, not `linux/arm32/v6`).
- #
- # TODO: It looks like this issue should be fixed starting in Docker 20.10.0,
- # so this step can be removed once fixed versions are in wider distribution.
- #
- # Tags:
- #
- # testing => testing-arm32v6
- # testing-alpine => <ignored>
- # x.y.z => x.y.z-arm32v6, latest-arm32v6
- # x.y.z-alpine => <ignored>
- #
- if [[ "${DOCKER_TAG}" != *alpine ]]; then
- image="${DOCKER_REPO}":"${DOCKER_TAG}"
- # Fetch the multi-arch manifest list and find the digest of the armv6 image.
- filter='.manifests|.[]|select(.platform.architecture=="arm" and .platform.variant=="v6")|.digest'
- digest="$(docker manifest inspect "${image}" | jq -r "${filter}")"
- # Pull the armv6 image by digest, retag it, and repush it.
- docker pull "${DOCKER_REPO}"@"${digest}"
- docker tag "${DOCKER_REPO}"@"${digest}" "${image}"-arm32v6
- docker push "${image}"-arm32v6
- if [[ "${DOCKER_TAG}" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
- docker tag "${image}"-arm32v6 "${DOCKER_REPO}:latest"-arm32v6
- docker push "${DOCKER_REPO}:latest"-arm32v6
- fi
- fi
|