You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							110 lines
						
					
					
						
							3.7 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							110 lines
						
					
					
						
							3.7 KiB
						
					
					
				
								#!/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
							 | 
						|
								
							 |