Build multi-architecture container images in GitHub Actions. Matrix builds (public repos with native ARM64), QEMU emulation (private repos), or ARM64 larger runners (Team/Enterprise). Uses Podman rootless builds with push-by-digest pattern
Builds multi-architecture container images in GitHub Actions using Podman. Automatically chooses matrix builds for public repos (native ARM64), QEMU emulation for private repos on free tier, or ARM64 larger runners for Team/Enterprise plans.
/plugin marketplace add pigfoot/claude-code-hubs/plugin install github-actions-container-build@pigfoot-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
assets/github-actions-workflow-matrix-build.ymlassets/github-actions-workflow-qemu.ymlreferences/github-actions-best-practices.mdBuild multi-architecture container images in GitHub Actions using Podman and native ARM64 runners.
CRITICAL: Ask these questions before generating any workflow.
Question 1: Is your GitHub repository public?
github-actions-workflow-matrix-build.yml (free standard ARM64 runners, 10-50x faster)Question 2: Do you have GitHub Team/Enterprise + willing to pay for ARM64 builds?
github-actions-workflow-qemu.yml (free QEMU emulation, slower but works on free tier)Matrix builds use push-by-digest pattern:
:amd64/:arm64 tags--platform flag# Build job
- name: Push by digest
run: |
podman push \
--digestfile /tmp/digest \
localhost/build:${{ matrix.arch }} \
docker://${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Merge job
- name: Create manifest from digests
run: |
podman manifest create "$IMAGE:latest"
podman manifest add "$IMAGE:latest" "docker://$IMAGE@${AMD64_DIGEST}"
podman manifest add "$IMAGE:latest" "docker://$IMAGE@${ARM64_DIGEST}"
podman manifest push --all "$IMAGE:latest" "docker://$IMAGE:latest"
Debug specific architecture:
podman pull --platform linux/arm64 ghcr.io/OWNER/REPO:latest
For public repositories - use GitHub-hosted standard ARM64 runners:
strategy:
matrix:
include:
- arch: amd64
runner: ubuntu-24.04
- arch: arm64
runner: ubuntu-24.04-arm # Standard ARM64 runner (public repos only)
For private repositories on free tier - use QEMU emulation:
docker/setup-qemu-action for ARM64 emulation--platform linux/amd64,linux/arm64runs-on: ubuntu-latest
steps:
- uses: docker/setup-qemu-action@v3
- run: podman build --platform linux/amd64,linux/arm64 --manifest ...
Use Podman for container builds:
podman manifest push --all (not podman push)--format v2s2 only for Quay.io or cross-registry (see references for details)--network=host flag for builds to avoid container networking SSL issues on GitHub Actions ubuntu-24.04 (see Troubleshooting section)Ubuntu 24.04's bundled podman (4.9.3) uses buildah 1.33.7 which doesn't support heredoc syntax. Install podman-static for full BuildKit compatibility:
- name: Install podman-static
run: |
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
PODMAN_ARCH="amd64"
else
PODMAN_ARCH="arm64"
fi
curl -fsSL -o /tmp/podman-linux-${PODMAN_ARCH}.tar.gz \
https://github.com/mgoltzsche/podman-static/releases/latest/download/podman-linux-${PODMAN_ARCH}.tar.gz
cd /tmp && tar -xzf podman-linux-${PODMAN_ARCH}.tar.gz
sudo cp -f podman-linux-${PODMAN_ARCH}/usr/local/bin/* /usr/bin/
podman system migrate
Important: Install to /usr/bin/ (not /usr/local/bin/) to avoid AppArmor issues.
Copy workflow template:
cp assets/github-actions-workflow-matrix-build.yml .github/workflows/build.yml
Customize Containerfile path:
-f ./Containerfile.python-uv # or your Containerfile
Add your Containerfile (see secure-container-build plugin for templates)
Copy workflow template:
cp assets/github-actions-workflow-qemu.yml .github/workflows/build.yml
Follow steps 2-3 from above.
--platform flag| Approach | Artifact Size | Registry Overhead | Best For |
|---|---|---|---|
| Push-by-digest (default) | ~70 bytes | 1x | Production |
| Architecture tags | None | 2x (tags + manifest) | Debugging |
| OCI artifacts | Full images | 3x | Maximum privacy |
See references/github-actions-best-practices.md for detailed comparison.
For private repositories with GitHub Team or Enterprise Cloud plans:
Standard ARM64 runners (ubuntu-24.04-arm) don't work in private repos. Instead, create ARM64 larger runners:
Setup steps:
my-org-arm64-runner)Update workflow to use custom runner:
strategy:
matrix:
include:
- arch: amd64
runner: ubuntu-24.04
- arch: arm64
runner: my-org-arm64-runner # Your custom ARM64 larger runner name
Cost:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
- name: Login to GHCR
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | podman login "${{ env.REGISTRY }}" \
-u "${{ github.actor }}" \
--password-stdin
- name: Login to Docker Hub
run: |
echo "${{ secrets.DOCKERHUB_TOKEN }}" | podman login docker.io \
-u "${{ secrets.DOCKERHUB_USERNAME }}" \
--password-stdin
# Push to Docker Hub
podman manifest push --all "$IMAGE:latest" \
"docker://docker.io/${{ secrets.DOCKERHUB_USERNAME }}/app:latest"
# Pull specific architecture
podman pull --platform linux/arm64 ghcr.io/OWNER/REPO:latest
# Inspect manifest
podman manifest inspect ghcr.io/OWNER/REPO:latest
# Verify architectures
podman manifest inspect ghcr.io/OWNER/REPO:latest | jq '.manifests[].platform'
For detailed information, see references/github-actions-best-practices.md.
For Containerfile templates and security best practices, see the secure-container-build plugin which provides:
Container networking SSL errors (ubuntu-24.04 runners):
UNKNOWN_CERTIFICATE_VERIFICATION_ERROR or SSL certificate verification failures during bun install, npm install, pip install, etc. inside containers--network=host flag to podman build:
podman build \
--network=host \
--format docker \
--platform linux/${{ matrix.arch }} \
-f ./Containerfile \
.
--network=host workaround reduces network isolation during build but is acceptable for CI/CD use cases.Authentication failed:
Manifest add failed:
sha256:...)ARM64 runner not available:
podman-static installation fails:
AppArmor issues:
/usr/bin/ not /usr/local/bin/podman system migrate after installationWrong architecture pulled:
--platform flag when pulling--format docker when building for compatibility