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
 | |
| 
 |