Working with Docker Workflows
1. Building Docker Images
| Option | Values | Notes |
|---|---|---|
| uses | docker/build-push-action@v5 |
GitHub Action for building and pushing Docker images |
| context | . |
Path to the Dockerfile and build context |
| tags | my-image:latest |
Tags to apply to the built image |
| push | true |
Whether to push the image to a registry |
Example: Building and pushing a Docker image
name: Build and Push Docker Image
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: my-image:latest
Note: Ensure Dockerfile is in the root of your repository or adjust the
context accordingly.
2. Tagging Docker Images
| Tag Format | Description | Examples |
|---|---|---|
| latest | Default tag for the most recent image | ghcr.io/myuser/myapp:latest |
| version | Tag with semantic versioning (e.g., v1.0.0) | ghcr.io/myuser/myapp:v1.2.3 |
| commit-sha | Tag with full commit SHA (e.g., 7d8b3c4) | ghcr.io/myuser/myapp:7d8b3c4 |
| branch | Tag with branch name (e.g., main) | ghcr.io/myuser/myapp:main |
Example: Using GitHub Actions to tag Docker images with version
name: Build and Push Docker Image
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/myuser/myapp:${{ github.ref_name }}
3. Pushing to Docker Hub
| Option | Values | Notes |
|---|---|---|
| uses | docker://ghcr.io/owner/repo:tag |
Image reference for Docker Hub |
| with.image | myapp:latest |
Name of the Docker image to push |
| with.tags | latest, v1.0 |
Comma-separated list of tags to push |
| with.username | $GITHUB_ACTOR |
Username for Docker Hub authentication |
| with.password | ${{ secrets.DOCKER_HUB_TOKEN }} |
Personal Access Token for Docker Hub |
Example: Pushing Docker Image to Docker Hub
name: Push Docker Image to Docker Hub
on:
push:
branches: [ main ]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: myapp:latest,myapp:v1.0
4. Pushing to GHCR
| Option | Values | Description |
|---|---|---|
| uses | docker://ghcr.io/owner/repo:tag |
Reference to the GHCR image |
| with.image | ghcr.io/owner/repo:tag |
Name of the image to push |
| with.tags | latest, v1.0 |
Comma-separated list of tags to push |
Example: Pushing Docker Image to GHCR
name: Push Docker Image to GHCR
on:
push:
branches: [ main ]
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ghcr.io/${{ github.actor }}/my-app:latest
Note: Ensure the
GITHUB_TOKEN has write:packages permissions to push images.
Warning: Avoid pushing sensitive data or secrets in Docker images. Use build args or environment variables for configuration.
5. Using Docker Buildx
| Option | Values | Description |
|---|---|---|
| uses | docker/setup-buildx-action@v3 |
Sets up Docker Buildx for use in workflows |
| args | --driver docker-container |
Specifies the driver to use for Buildx |
| version | v0.12.0 |
Version of Buildx to use (latest stable as of 2026) |
Example: Setting up Buildx
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker-container
version: v0.12.0
| Option | Values | Description |
|---|---|---|
| platform | linux/amd64,linux/arm64 |
Target platforms for the build (comma-separated) |
| outputs | type=registry,registry=ghcr.io,repository=myapp |
Output configuration for the build (e.g., registry or local) |
| cache-from | type=gha |
Cache sources for build cache (e.g., GitHub Actions cache) |
| cache-to | type=gha,mode=max |
Cache destinations for build cache (e.g., GitHub Actions cache) |
Example: Building and pushing multi-platform image
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/myuser/myapp:latest
cache-from: type=gha
cache-to: type=gha,mode=max
Note: Buildx requires Docker daemon to be running on the runner. Ensure that
dockerd is enabled in your workflow if using self-hosted runners.
Warning: When using
docker/build-push-action, make sure to set push: true if you want to push the image to a registry. Otherwise, it will only build locally.
6. Using Multi-Stage Builds
| Stage | Description | Use Case | Example |
|---|---|---|---|
| FROM node:18 as builder | Initial stage for building application dependencies | Install Node.js dependencies and build frontend assets | |
| FROM node:18-alpine as runtime | Final stage with minimal runtime environment | Run the application in a lightweight container | |
Example: Multi-stage Docker Build in GitHub Actions
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: false
tags: my-app:latest
Note: Multi-stage builds reduce image size and improve security by minimizing the attack surface in production containers.
7. Caching Docker Layers
Example: Using cache action for Docker layers
name: Build and push Docker image
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Cache Docker layers
uses: actions/cache@v3
id: cache
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
-
name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: false
tags: my-image:latest
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache
| Option | Description | Values |
|---|---|---|
| actions/cache@v3 | Cache action to store Docker layers | true |
| path | Directory to cache | /tmp/.buildx-cache |
| key | Cache key to use for storing and retrieving cache | ${{ runner.os }}-buildx-${{ github.sha }} |
Note: The cache key should include a unique identifier like
github.sha to ensure cache invalidation on code changes.
Warning: Ensure the cache directory is not included in your Docker image to avoid layer caching issues.
8. Using Docker Compose
| Option | Values | Description |
|---|---|---|
| services | object |
Defines the services that make up your app's containers |
| volumes | array |
Defines volumes to be mounted in the containers |
| networks | object |
Defines custom networks for services to communicate |
Example: Basic docker-compose.yml
version: '3.8'
services:
web:
build: .
ports:
- "3000:3000"
depends_on:
- db
db:
image: postgres:13
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
Example: GitHub Actions workflow using Docker Compose
name: Build and Test with Docker Compose
on:
push:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Compose
run: |
docker-compose up -d
sleep 10
- name: Run tests
run: |
docker-compose exec web npm test
Note: Ensure that your
docker-compose.yml file is in the root of your repository for GitHub Actions to find it.
Warning: Using
docker-compose up in a CI environment might not be ideal for all use cases. Consider using docker-compose run or docker-compose exec for more controlled execution.
9. Running Docker Containers
| Option | Values | Notes |
|---|---|---|
| uses | docker://image:tag |
Runs a Docker image as a step |
| with.args | arg1 arg2 |
Arguments to pass to the container |
| with.entrypoint | /bin/sh |
Override the default entrypoint |
| with.working-directory | /app |
Working directory inside the container |
Example: Running a Docker Container
steps:
- name: Run Docker Container
uses: docker://alpine:latest
with:
args: echo "Hello from Alpine"
Example: Using Custom Image with Arguments
steps:
- name: Run Custom Image
uses: docker://myapp:latest
with:
args: "--verbose --output=/tmp/result.txt"
Note: When using
docker://, the image must be available in a registry (e.g., Docker Hub, GitHub Container Registry).
10. Scanning Images for Vulnerabilities
Example: Using Trivy to Scan Docker Images
name: Scan Docker Image
on:
push:
branches: [ main ]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Scan image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-name: 'myapp:latest'
format: 'sarif'
output: 'trivy-results.sarif'
| Option | Values | Description |
|---|---|---|
| image-name | myapp:latest |
Name of the Docker image to scan |
| format | sarif |
Output format (e.g., sarif, json) |
| output | trivy-results.sarif |
File to save scan results |
Note: Trivy is a popular open-source vulnerability scanner for container images and filesystems.
Warning: Ensure that the image is pulled or built before scanning to avoid errors.
11. Using Build Arguments
| Argument | Description | Usage |
|---|---|---|
| build-arg | Build argument to pass to the Docker build command | build-arg NAME=value |
| build-arg-file | Path to a file containing build arguments | build-arg-file path/to/args.txt |
Example: Setting Build Arguments in Workflow
jobs:
build:
runs-on: ubuntu-latest
steps:
-
name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
build-arg:
VERSION: 1.0.0
ENV: production
Note: Build arguments are only available during the build process and are not persisted in the final image.
12. Publishing to Multiple Registries
| Registry | URL | Authentication | Notes |
|---|---|---|---|
| Docker Hub | https://index.docker.io/v1/ |
Username + Password or Token | Default registry for most Docker images |
| GitHub Container Registry (GHCR) | https://ghcr.io |
GitHub Personal Access Token (PAT) or GitHub App Token | Integrated with GitHub, supports fine-grained permissions |
| Amazon ECR | 123456789012.dkr.ecr.region.amazonaws.com |
AWS Access Key ID + Secret Access Key or IAM Role | Requires AWS CLI or AWS credentials to be configured |
| Google Container Registry (GCR) | gcr.io |
Service Account Key or gcloud auth application-default login | Requires Google Cloud SDK to be installed and authenticated |
Example: Publishing to Docker Hub and GHCR
name: Publish Docker Image
on:
push:
branches:
- main
jobs:
publish:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v4
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
my-dockerhub-username/my-image:latest
ghcr.io/my-github-username/my-image:latest
Note: When pushing to multiple registries, ensure that each registry's authentication is correctly configured in your GitHub repository secrets.