# ===============================================================
# Multiplatform Docker Build Workflow
# ===============================================================
#
# This workflow builds container images for multiple architectures:
# - linux/amd64 (native on ubuntu-latest)
# - linux/arm64 (native on ubuntu-24.04-arm)
# - linux/ppc64le (QEMU emulation on ubuntu-latest)
#
# Pipeline:
# 1. Build platform images in parallel
# 2. Create multiplatform manifest
#
# Trigger: Only on version tags (v*)
#
# ===============================================================
name: Multiplatform Docker Build
on:
push:
tags:
- 'v*'
workflow_dispatch:
permissions:
contents: read
packages: write
actions: read
id-token: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# ---------------------------------------------------------------
# Build each platform in parallel
# ---------------------------------------------------------------
build:
name: Build ${{ matrix.suffix }}
environment: Release
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
suffix: amd64
cache_mode: max
- platform: linux/arm64
runner: ubuntu-24.04-arm
suffix: arm64
cache_mode: max
- platform: linux/ppc64le
runner: ubuntu-latest
suffix: ppc64le
qemu: true
cache_mode: min
runs-on: ${{ matrix.runner }}
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Extract tag name
id: tag
run: |
TAG=${GITHUB_REF#refs/tags/}
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Set image name lowercase
run: |
IMAGE_NAME_LC=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')
echo "IMAGE_NAME_LC=${IMAGE_NAME_LC}" >> $GITHUB_ENV
- name: Set up QEMU
if: matrix.qemu
uses: docker/setup-qemu-action@v3
with:
platforms: ${{ matrix.platform }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}
tags: |
type=raw,value=${{ matrix.suffix }}-${{ steps.tag.outputs.tag }}
- name: Build and push
id: build
uses: docker/build-push-action@v6
with:
context: ./server
file: ./server/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=build-${{ matrix.suffix }}
cache-to: type=gha,mode=${{ matrix.cache_mode }},scope=build-${{ matrix.suffix }}
provenance: false
# ---------------------------------------------------------------
# Create multiplatform manifest
# ---------------------------------------------------------------
manifest:
name: Create Manifest
environment: Release
needs: build
runs-on: ubuntu-latest
steps:
- name: Extract tag name
id: tag
run: |
TAG=${GITHUB_REF#refs/tags/}
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Set image name lowercase
run: |
IMAGE_NAME_LC=$(echo "${{ env.IMAGE_NAME }}" | tr '[:upper:]' '[:lower:]')
echo "IMAGE_NAME_LC=${IMAGE_NAME_LC}" >> $GITHUB_ENV
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push manifest
run: |
TAG=${{ steps.tag.outputs.tag }}
IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}
echo "Creating multiplatform manifest for tag: $TAG"
# Platform-specific images
IMAGES="${IMAGE}:amd64-${TAG} ${IMAGE}:arm64-${TAG} ${IMAGE}:ppc64le-${TAG}"
docker buildx imagetools create \
--tag "${IMAGE}:${TAG}" \
--tag "${IMAGE}:latest" \
$IMAGES
echo "Manifest created successfully"
- name: Inspect manifest
run: |
TAG=${{ steps.tag.outputs.tag }}
IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME_LC }}
echo "Inspecting multiplatform manifest for tag: $TAG"
docker buildx imagetools inspect "${IMAGE}:${TAG}"
echo "Inspecting latest tag..."
docker buildx imagetools inspect "${IMAGE}:latest"