GitHub Actions workflow to build and publish a Docker image to GHCR
A workflow that builds your repository's Docker image and publishes it to GitHub Container Registry (ghcr.io) when you push to main or create a v* tag. It needs no secrets: it uses the GITHUB_TOKEN. This is the exact YAML the application generates.
When to use it
- Your repository has a Dockerfile at the root.
- You want to publish the image to ghcr.io without creating secrets.
- You want pull requests to only build the image, without publishing it.
The complete workflow
name: Docker
on:
push:
branches:
- main
tags:
- v*
pull_request:
branches:
- main
workflow_dispatch:
permissions:
contents: read
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
image:
name: Build and publish the image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
timeout-minutes: 30
steps:
- name: Check out the code (actions/checkout v7.0.1)
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Set up Buildx (docker/setup-buildx-action v4.4.1)
uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069
- name: Log in to GHCR (docker/login-action v4.6.0)
if: github.event_name != 'pull_request'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- id: meta
name: Compute tags and metadata (docker/metadata-action v6.2.0)
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=tag
type=sha
- name: Build and publish (docker/build-push-action v7.4.0)
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc
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
It is a starting point: you can open it in the editor, change events, jobs and steps, and the application validates it again before generating the file.
Before you use it
- Needs a Dockerfile at the root of the repository.
- Publishes to ghcr.io/<your-user>/<repository> with the GITHUB_TOKEN; no secret is needed.
- On pull requests it only builds (it does not publish).
- If the repository belongs to an organization, check that workflows can write packages (Settings → Actions).
What each part does
- EventsIt runs on pushes to main, when you create a tag starting with v, on pull requests targeting main and manually from the Actions tab.
- Publish only when it shouldLogging in to GHCR and publishing only happen outside pull requests; in a pull request the image is built but not published.
- Minimal, scoped permissionsThe workflow asks only for read access to the contents; the only write permission (packages: write) is inside the job that publishes, not on the whole workflow.
- Tags and metadataThe image tags are computed from the branch, the Git tag and the commit.
- Layer cacheThe GitHub Actions cache is used for Docker layers, which speeds up repeated builds.
- Security and maximum timeThird-party actions are pinned to a specific commit SHA (with the readable version in the step name), not to a movable tag. Every job has a maximum run time (timeout-minutes) so a hang cannot burn minutes forever.
How to use it in your repository
- Save the file in the .github/workflows/ folder of your repository.
- Push it (commit and push). GitHub detects the workflow and runs it according to its events.
- Check the result in the Actions tab of the repository.
Frequently asked questions
Do I need to create any secret?
No. The login uses the GITHUB_TOKEN that GitHub generates on every run, with the packages: write permission only in the job that publishes.
What should I check if my repository belongs to an organization and publishing fails?
In the organization's Actions settings, check that workflows can write packages (Settings → Actions).
Where is the image published?
At ghcr.io/<your-user>/<repository>, with the tags computed by the workflow. The package visibility is managed in GitHub.
Other templates
- GitHub Actions workflow for Python (pytest)Installs dependencies and runs pytest on several Python versions with pip caching.
- GitHub Actions workflow for Node.js (lint, tests and build)Installs with npm ci and runs lint, tests and build on several Node versions with npm caching.
Try it for free
The editor is available with a free account, with usage limits. Nothing runs in your repository or your installation: you decide which file to use.