Claude Code Plugins

Community-maintained marketplace

Feedback

github-actions-container-build

@pigfoot/claude-code-hubs
1
0

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

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name github-actions-container-build
description 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

GitHub Actions Container Build

Build multi-architecture container images in GitHub Actions using Podman and native ARM64 runners.

Core Principles

Choose Your Workflow

CRITICAL: Ask these questions before generating any workflow.

Question 1: Is your GitHub repository public?

  • Yes → Use github-actions-workflow-matrix-build.yml (free standard ARM64 runners, 10-50x faster)
  • No → Go to Question 2

Question 2: Do you have GitHub Team/Enterprise + willing to pay for ARM64 builds?

  • Yes → Use ARM64 larger runners (custom setup required, paid per minute)
  • No → Use github-actions-workflow-qemu.yml (free QEMU emulation, slower but works on free tier)

1. Push-by-Digest (2025 Best Practice - Default)

Matrix builds use push-by-digest pattern:

  • Images pushed by digest without intermediate :amd64/:arm64 tags
  • Only tiny digest files (~70 bytes) transfer as artifacts
  • Registry stays clean (no tag clutter)
  • Same debug experience with --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

2. Matrix Builds (Public Repos)

For public repositories - use GitHub-hosted standard ARM64 runners:

  • 10-50x faster builds (native vs. emulation)
  • Better reliability and accuracy
  • Lower CI costs
  • Completely free for public repos
  • Not available for private repos
strategy:
  matrix:
    include:
      - arch: amd64
        runner: ubuntu-24.04
      - arch: arm64
        runner: ubuntu-24.04-arm  # Standard ARM64 runner (public repos only)

3. QEMU Builds (Private Repos - Free Tier)

For private repositories on free tier - use QEMU emulation:

  • Works on GitHub Free plan
  • Slower (10-50x) than native ARM64 runners
  • Uses docker/setup-qemu-action for ARM64 emulation
  • Single-job pattern with --platform linux/amd64,linux/arm64
runs-on: ubuntu-latest
steps:
  - uses: docker/setup-qemu-action@v3
  - run: podman build --platform linux/amd64,linux/arm64 --manifest ...

4. Podman Over Docker

Use Podman for container builds:

  • Rootless by default (better security)
  • No daemon required
  • Native multi-arch manifest support
  • OCI compliant
  • Must use podman manifest push --all (not podman push)
  • Format: Use OCI (default) for modern registries; use --format v2s2 only for Quay.io or cross-registry (see references for details)
  • Network: Use --network=host flag for builds to avoid container networking SSL issues on GitHub Actions ubuntu-24.04 (see Troubleshooting section)

5. podman-static for Heredoc Support

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.

Quick Start

For Public Repos (Matrix Build)

  1. Copy workflow template:

    cp assets/github-actions-workflow-matrix-build.yml .github/workflows/build.yml
    
  2. Customize Containerfile path:

    -f ./Containerfile.python-uv  # or your Containerfile
    
  3. Add your Containerfile (see secure-container-build plugin for templates)

For Private Repos (QEMU)

  1. Copy workflow template:

    cp assets/github-actions-workflow-qemu.yml .github/workflows/build.yml
    
  2. Follow steps 2-3 from above.

Workflow Structure

Matrix Build Workflow (Push-by-Digest)

  1. Build job (matrix): Build and push images by digest on native runners
  2. Merge job: Download digests, create and push multi-arch manifest

QEMU Workflow

  1. Single job: Build multi-arch manifest directly with --platform flag

Multi-arch Build Approaches

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.

ARM64 Larger Runners (Private Repos with Team/Enterprise)

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:

  1. Go to Organization Settings → Actions → Runners → New runner
  2. Select "Larger runners"
  3. Choose "Ubuntu 24.04 by Arm Limited" partner image
  4. Name your runner (e.g., my-org-arm64-runner)
  5. Configure size (e.g., 4-core, 16GB RAM)

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:

  • Billed per minute (not included in free minutes)
  • ~37% cheaper than x64 larger runners
  • Ref: Actions runner pricing

Registry Configuration

GitHub Container Registry (GHCR) - Default

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

Docker Hub (Optional)

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

Debugging Multi-arch Images

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

Reference Documentation

For detailed information, see references/github-actions-best-practices.md.

Containerfile Templates

For Containerfile templates and security best practices, see the secure-container-build plugin which provides:

  • Production-ready templates for Python/uv, Bun, Node.js/pnpm, Golang, and Rust
  • Wolfi runtime images with non-root users
  • Multi-stage build patterns
  • Allocator optimization for Rust

Troubleshooting

Common Issues

Container networking SSL errors (ubuntu-24.04 runners):

  • Symptom: UNKNOWN_CERTIFICATE_VERIFICATION_ERROR or SSL certificate verification failures during bun install, npm install, pip install, etc. inside containers
  • Cause: GitHub Actions ubuntu-24.04 runner image 20251208.163.1+ has container networking configuration changes that break SSL/TLS connections from inside containers
  • Solution: Add --network=host flag to podman build:
    podman build \
      --network=host \
      --format docker \
      --platform linux/${{ matrix.arch }} \
      -f ./Containerfile \
      .
    
  • Verification: Test repository at https://github.com/pigfoot/test-bun-ssl-issue
  • GitHub Issue: https://github.com/actions/runner-images/issues/13422
  • Note: This is a known issue with ubuntu-24.04 runners. The --network=host workaround reduces network isolation during build but is acceptable for CI/CD use cases.

Authentication failed:

  • Ensure GITHUB_TOKEN has package write permission
  • Check registry URL and credentials

Manifest add failed:

  • Verify architecture-specific images exist in registry
  • Check digest format is correct (sha256:...)

ARM64 runner not available:

  • Standard ARM64 runners only work for public repos
  • For private repos, use QEMU or larger runners

podman-static installation fails:

  • Verify correct architecture detection
  • Check GitHub releases for podman-static availability

AppArmor issues:

  • Install binaries to /usr/bin/ not /usr/local/bin/
  • Run podman system migrate after installation

Wrong architecture pulled:

  • Always use --platform flag when pulling
  • Use --format docker when building for compatibility