Building Docker Images in GitHub Actions
A few lines of YAML turn every push into a freshly built, tested Docker image.
GitHub Actions has first-class Docker support through the official docker/* actions. In this lesson you will set up Buildx, build an image from your Dockerfile, tag it meaningfully, and pass build arguments. We build without pushing first, so you can validate the workflow before adding a registry.
A minimal Dockerfile
Start with a small, explicit Dockerfile. Pin the base image tag so builds are reproducible.
FROM node:20-bookworm-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/server.js"]Set up Buildx and build the image
Use docker/setup-buildx-action to enable BuildKit, then docker/build-push-action to build. Keep push: false until the registry step is in place.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/build-push-action@v6
with:
context: .
push: false
tags: myapp:${{ github.sha }}Tag images so you can trace them
- Tag with the commit SHA (
myapp:${{ github.sha }}) for an immutable, traceable reference. - Add a moving tag like
latestor the branch name for convenience, never as the deploy reference. - Use
docker/metadata-actionto generate tags and OCI labels automatically from git context.
Passing build arguments
Use build-args for non-secret build-time values such as a version string. Never pass secrets this way, since build args are visible in image history; use BuildKit secret mounts instead.
- uses: docker/build-push-action@v6
with:
context: .
push: false
build-args: |
APP_VERSION=${{ github.ref_name }}
tags: myapp:${{ github.sha }}Key takeaways
- Use
docker/setup-buildx-actionplusdocker/build-push-actionfor a clean, cacheable build. - Tag images with the commit SHA for an immutable, traceable artifact reference.
- Build args are for non-secret values only; they persist in image history.