Docker cookbook · Intermediate

Build, cache and push images in GitHub Actions

Build images in CI with layer caching and push them with immutable tags.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Use the official actions: set up Buildx, log in, compute tags with metadata-action (commit SHA and semver), and build-push with the GitHub Actions cache.

Solution

name: image
on: {push: {branches: [main], tags: ["v*"]}}
permissions: {contents: read, packages: write}
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with: {registry: ghcr.io, username: "${{ github.actor }}", password: "${{ secrets.GITHUB_TOKEN }}"}
      - id: meta
        uses: docker/metadata-action@v5
        with:
          images: ghcr.io/${{ github.repository }}
          tags: |
            type=sha
            type=semver,pattern={{version}}
      - uses: docker/build-push-action@v6
        with:
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Pitfalls

  • Pushing only latest, so deployments can't pin a build.
  • Building without cache on every run.
  • Long-lived registry passwords instead of the job token or OIDC.

Variations

  • Add platforms: linux/amd64,linux/arm64 for multi-platform images.
  • Add provenance and SBOM attestations (provenance: true, sbom: true).

Further reading: Docker build GitHub Actions

Reference: https://docs.docker.com/build/ci/github-actions/

More Docker recipes

Was this page helpful?