GitHub logo.

GitHub has a feature called GitHub Actions that run automatic builds, tests, and other scripts whenever you make changes to a repository. One handy use case of this is automatically building and pushing Docker containers to a container registry.

GitHub’s New Container Registry

GitHub’s new container registry, called GitHub Container Registry, is a bit different than most registries like the Docker Hub. It functions as an extension of GitHub Packages, a package storage system that associates packages with their source code repositories. Packages can be built and pushed from the repository, often automatically with the help of a GitHub Actions pipeline.

GitHub Container Registry.

GitHub Container Registry is simply adding Docker-specific compatibility to GitHub Packages, making it function like a container registry for purposes of running docker pull and other CLI commands.

You don’t need to publish to GitHub’s container registry—you can still publish to the Docker Hub from an action with some configuration. The prebuilt actions work with GHCR out of the box though, so it’s a lot simpler to set up.

How to Set Up Automatic Builds to GitHub Packages

To start, you’ll need a repository. Even if you are only publishing packages, you’ll still need a repo, because the format for GHCR is:

Set up a repo, then click on “Actions” to create a new action. Under “More Continuous Integration Workflows,” click “Publish Docker Container.”

Set up your repo.

This generates a starter template, which needs a few changes to work. First, the IMAGE_NAME variable needs to be changed to your image name.

Then, on line 39, you’ll find where it logs into GHCR.

run: echo "${{ secrets.CR_PAT }}" | docker login -u ${{ }} --password-stdin

Currently, the only supported authentication scheme is Personal Access Tokens (PATs), which isn’t great for security because they grant account-wide access. GitHub knows this, and is working on a better fix for the future, but in the meantime if you want to use GHCR from a GitHub Actions workflow, you’ll need to store a PAT in the Secrets for your repository, because obviously just pasting it in here would be horrendous.

First, you’ll need to head over to Settings > Developer Settings > Personal Access Tokens and create a new token. This token needs write:packages and delete:packages settings. Note that for some reason, selecting write packages automatically selects “Full Control Of Repositories,” which you have to uncheck.

Create a new token with write:packages and delete:packages settings.

Then, head over to the repository’s settings, and create a new secret called CR_PAT, to match the action.

Head back to the action, and click “Start Commit” to push it to the repository.

Once it’s committed, it will trigger a workflow to run and build the package. You can monitor the status of all running workflows under the “Actions” tab. Here, it failed because the default actions expects there to be tests to run, which this image didn’t have.

Monitor the status of all running workflows under the "Actions" tab.

Once it’s successful, you should see the container in the registry, under “Packages” on the repository’s main page, or under the packages on your profile.

A successful package build.

Profile Photo for Anthony Heddings Anthony Heddings
Anthony Heddings is the resident cloud engineer for LifeSavvy Media, a technical writer, programmer, and an expert at Amazon's AWS platform. He's written hundreds of articles for How-To Geek and CloudSavvy IT that have been read millions of times.
Read Full Bio »