mirror of
https://github.com/dani-garcia/vaultwarden
synced 2024-11-05 15:18:57 +01:00
ca0fd7a31b
- Split Debian and Alpine into different build matrix This starts building both Debian and Alpine based images at the same time - Make use of Docker BuildKit, which improves speed also. - Use BuildKit caching for Rust Cargo across docker images. This prevents downloading the same crates multiple times. - Use Github Actions Services to start a docker registry, starting it via the build script sometimes caused issues. - Updated the Build workflow to use Ubuntu 20.04 which is more close to the Bullseye Debian release regarding package versions.
149 lines
5.4 KiB
Bash
Executable file
149 lines
5.4 KiB
Bash
Executable file
#!/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 when needed..."
|
|
|
|
# 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.
|
|
#
|
|
# First check if there already is a registry container running, else skip it.
|
|
# This will only happen either locally or running it via Github Actions
|
|
#
|
|
if ! timeout 5 bash -c 'cat < /dev/null > /dev/tcp/localhost/5000'; then
|
|
# defaults to port 5000
|
|
docker run -d --name registry --network host registry:2
|
|
fi
|
|
|
|
# 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
|
|
#
|
|
# Check if there already is a builder running, else skip this and use the existing.
|
|
# This will only happen either locally or running it via Github Actions
|
|
#
|
|
if ! docker buildx inspect builder > /dev/null 2>&1 ; then
|
|
docker buildx create --name builder --use --driver-opt network=host
|
|
fi
|
|
|
|
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 vaultwarden 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
|