Skip to content

Docker

Docker #33

name: Docker
on:
workflow_dispatch:
inputs:
set_latest_tag:
description: 'Set to true to tag the image with `latest`'
required: true
default: false
type: boolean
build_version:
description: 'The version of pushpin to build and push (ex: 1.40.1)'
required: true
type: string
build_tag:
description: 'The tag to use for the docker image (ex: 1.40.1) (ex: 1.40.1-2)'
required: true
type: string
env:
REGISTRY: docker.io
IMAGE_NAME: fanout/pushpin
SET_LATEST: ${{ github.event.inputs.set_latest_tag }}
BUILD_VERSION: ${{ github.event.inputs.build_version }}
BUILD_TAG: ${{ github.event.inputs.build_tag }}
jobs:
build:
# We use a matrix to run each docker container build for a specific platform on it's own native runner.
# This avoids using virtualization and massively speeds up builds.
strategy:
matrix:
platform: [linux/amd64, linux/arm64]
include:
- platform: linux/amd64
runner: ubuntu-latest
- platform: linux/arm64
runner: ubuntu-24.04-arm
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
steps:
- name: Code checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
latest=${{ env.SET_LATEST }}
tags: |
type=ref,event=branch,pattern={{branch}}
type=semver,pattern={{version}},value=${{ env.BUILD_TAG }}
- name: Derive arch-suffixed tags as output
id: archtags
run: |
set -euo pipefail
ARCH="$(echo '${{ matrix.platform }}' | cut -d/ -f2)"
T="$(printf '%s\n' "${{ steps.meta.outputs.tags }}" | sed "s/$/-${ARCH}/")"
{
echo 'tags<<EOF'
echo "$T"
echo 'EOF'
echo "arch=$ARCH"
} >> "$GITHUB_OUTPUT"
- name: Login to ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build & push ${{ matrix.platform }}
uses: docker/build-push-action@v6
with:
context: .
platforms: ${{ matrix.platform }}
push: ${{ github.event_name != 'pull_request' }}
build-args: |
VERSION=${{ env.BUILD_VERSION }}
tags: ${{ steps.archtags.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# In order to have a single tag that covers both archtectures we run one more job to create a multi-arch manifest
# under a single tag.
manifest:
name: Create multi-arch manifest
runs-on: ubuntu-latest
needs: build
steps:
- name: Code checkout
uses: actions/checkout@v4
- name: Docker meta (same base tags)
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
flavor: |
latest=${{ env.SET_LATEST }}
tags: |
type=ref,event=branch,pattern={{branch}}
type=semver,pattern={{version}},value=${{ env.BUILD_TAG }}
- name: Login
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Create manifest for each base tag
if: github.event_name != 'pull_request'
run: |
set -euo pipefail
while IFS= read -r BASE; do
echo "Preparing manifest for $BASE"
AMD="${BASE}-amd64"
ARM="${BASE}-arm64"
# Skip if one arch is missing
docker buildx imagetools inspect "$AMD"
docker buildx imagetools inspect "$ARM"
docker buildx imagetools create \
--tag "$BASE" \
"$AMD" \
"$ARM"
echo "OK: $BASE now points to $AMD + $ARM"
done <<'EOF'
${{ steps.meta.outputs.tags }}
EOF