Home/Engineer/Git / CI·CD/Automating Docker Image Buil…
Git / CI·CDIntermediateUbuntugithub-actionsdockerci-cd

Automating Docker Image Builds and Registry Deployment with GitHub Actions

Set up a CI/CD pipeline that builds Docker images with a GitHub Actions workflow and pushes them to GHCR or Docker Hub.

Contents
  1. Overall Flow
  2. Deploying to GHCR (GitHub Container Registry)
  3. Automatic Server Deployment After Build
  4. Configuring Secrets
  5. Multi-architecture Builds (ARM Support)
  6. Speeding Up Builds with Caching

Overall Flow

CODE
git push → GitHub Actions trigger
→ Checkout code
→ Build Docker image
→ Push to registry (GHCR / Docker Hub)
→ docker pull + restart on the server

Deploying to GHCR (GitHub Container Registry)

YAML
# .github/workflows/docker-build.yml

name: Docker Build & Push

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - 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 }}
          tags: |
            type=ref,event=branch
            type=sha,prefix=sha-
            type=semver,pattern={{version}}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: .
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

Automatic Server Deployment After Build

YAML
      - name: Deploy to server
        if: github.ref == 'refs/heads/main'
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            docker pull ghcr.io/${{ github.repository }}:main
            docker compose -f /opt/app/docker-compose.yml up -d app
            docker image prune -f

Configuring Secrets

GitHub repository → Settings → Secrets and variables → Actions:

Secret nameValue
SERVER_HOSTServer IP or domain
SERVER_USERSSH username
SSH_PRIVATE_KEYSSH private key (-----BEGIN OPENSSH PRIVATE KEY----- ...)

GITHUB_TOKEN is provided automatically by Actions.


Multi-architecture Builds (ARM Support)

YAML
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Build and push (multi-arch)
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}

Use this when you need to support ARM servers (AWS Graviton, Raspberry Pi) and x86 servers at the same time.


Speeding Up Builds with Caching

GitHub Actions cache is used with just the cache-from: type=gha / cache-to: type=gha,mode=max settings. Unchanged layers are not rebuilt, which significantly reduces build time.

#github-actions#docker#ci-cd#ghcr
Editorial note

AI tools may assist drafting. Check the evidence in each guide for whether commands were run and which environment was used. Confirm the current docs for your version before applying instructions, and email us about errors. email us

Topic-related official docs (auto-linked · not per-claim sources)Docker documentation ↗Git documentation ↗

Questions & answers

Ask a question about this guide. We'll review and reply.