github-actions
GitHub Actions Build and Push Docker Image
GitHub Actions workflow to build, tag, and push Docker images to container registries with multi-platform and caching support.
Overview
A GitHub Actions workflow that builds Docker images and pushes them to GitHub Container Registry (GHCR). Supports multi-platform builds, layer caching, semantic version tagging, and security scanning.
Configuration
# .github/workflows/docker.yml
name: Build and Push Docker Image
on:
push:
branches: [main]
tags: ["v*"] # Trigger on version tags
pull_request:
branches: [main] # Build (no push) on PRs
concurrency:
group: docker-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }} # e.g., org/repo
jobs:
build:
name: Build & Push
runs-on: ubuntu-latest
permissions:
contents: read
packages: write # Push to GHCR
attestations: write # Sign images
id-token: write # OIDC for signing
steps:
- name: Checkout code
uses: actions/checkout@v4
# Set up QEMU for multi-platform builds
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
# Set up Docker Buildx for advanced build features
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# Log in to container registry
- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Generate image tags and labels from Git metadata
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
# Tag with branch name
type=ref,event=branch
# Tag with PR number
type=ref,event=pr
# Tag with semver from Git tag (v1.2.3 -> 1.2.3, 1.2, 1)
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
# Tag with Git SHA (short)
type=sha,prefix=
# Tag latest for default branch
type=raw,value=latest,enable={{is_default_branch}}
# Build and push the image
- name: Build and push
id: build
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64 # Multi-platform
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha # GitHub Actions cache
cache-to: type=gha,mode=max
# Scan for vulnerabilities
- name: Run Trivy vulnerability scanner
if: github.event_name != 'pull_request'
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
format: sarif
output: trivy-results.sarif
severity: CRITICAL,HIGH
- name: Upload Trivy scan results
if: github.event_name != 'pull_request'
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: trivy-results.sarif
Key Options Explained
docker/metadata-action— Automatically generates proper OCI image tags from Git refs. Av1.2.3tag produces1.2.3,1.2,1, andlatestimage tags.docker/build-push-action— Uses Buildx for advanced features like multi-platform builds, build caching, and inline cache metadata.platforms: linux/amd64,linux/arm64— Builds for both x86 and ARM architectures in a single workflow, producing a multi-arch manifest.cache-from/cache-to: type=gha— Uses GitHub Actions cache backend to store and restore Docker layer cache, dramatically speeding up rebuilds.push: ${{ github.event_name != 'pull_request' }}— Only pushes images for non-PR events. PRs still build the image (validating the Dockerfile) but don’t publish.- Trivy scanner — Scans the built image for known CVEs. Results appear in GitHub’s Security tab as SARIF alerts.
Common Modifications
- AWS ECR: Replace GHCR login with
aws-actions/amazon-ecr-login@v2and setREGISTRYto your ECR URL. - Docker Hub: Use
docker/login-actionwithusername: ${{ secrets.DOCKERHUB_USERNAME }}andpassword: ${{ secrets.DOCKERHUB_TOKEN }}. - Build args: Add
build-args: |withNODE_ENV=productionorVERSION=${{ github.ref_name }}to the build step. - Single platform: Remove the QEMU step and
platformsline to build only forlinux/amd64(faster builds). - Deploy after push: Add a
deployjob withneeds: buildthat updates your Kubernetes deployment or ECS service with the new image tag.