DEV Community

Garrin Costa, Jr.
Garrin Costa, Jr.

Posted on

6 checks before you push a Docker image to ghcr.io from GitHub Actions

Pushing an image to ghcr.io can be a ten-line workflow. The trouble is that a few settings are outside the workflow file, and the error messages often don't mention them. Here are six checks that cover the most common surprises, so you spend your time on the image and not on the log.

This guide is for maintainers who publish Docker images from a GitHub repository to ghcr.io.

1. The job doesn't have permission to write packages

If the push fails with permission_denied: write_package, the job probably lacks permission. Depending on your repository or organization settings, the default token permissions may be read-only.

Check: Give the publish job its own permissions block:

permissions:
  contents: read
  packages: write
Enter fullscreen mode Exit fullscreen mode

Then log in with the built-in GITHUB_TOKEN. For a package in the same repository, you don't need a personal access token.

2. The image name has uppercase letters

Registry names must be lowercase. Your GitHub owner name may not be.

Check: Write the full image name in lowercase, or lowercase it in the workflow before you use it.

3. An old package is linked to something else

If a package with the same name already exists, it can be linked to another repository or owner. The login step then succeeds, but GitHub still denies the push.

Check: Open the package settings. See which repository it is linked to. Link it to the right one, or use a new name.

4. Your organization limits package creation

Organizations can control who may create packages. In that case, a member's push can fail even when the workflow file is correct.

Check: If the owner is an organization, ask an admin about the package settings before you debug the workflow.

5. You only push latest

Each time you push, the latest tag is reassigned to the new image. If a release breaks something, a user who pulled latest can't tell which build they have or get back to the one that worked.

Check: Push a version tag for every release, like 1.4.0, next to latest. Tell users to pin the version tag. docker/metadata-action can make both tags from your Git tag, so pushing v1.4.0 gives you 1.4.0 and latest without typing either one.

6. Users can't pull because the package is private

A new package can be private by default. Pulls without a login then fail with unauthorized, which looks like a bug in your image.

Check: Open the package page and look at the visibility. Decide on purpose. Then test from a clean shell with no login:

docker pull ghcr.io/your-owner/your-image:1.4.0
Enter fullscreen mode Exit fullscreen mode

The short version

  1. Add packages: write to the publish job.
  2. Use a lowercase image name.
  3. Check which repository the package is linked to.
  4. Check the organization package settings.
  5. Push a version tag, not only latest.
  6. Check the visibility and test a pull with no login.

The full checklist

I made a longer version of this as a paid kit: GHCR Publish Checklist ($7). It has three parts:

  • A 7-step checklist that you can copy into a release issue
  • A CSV of the build, test, tag, and pull commands
  • A GitHub Actions workflow template for ghcr.io

It is for maintainers who publish Docker images from GitHub to ghcr.io. It is not for teams that use another registry or a managed release platform.

GHCR Publish Checklist

A step-by-step checklist, command list, and workflow template to publish a Docker image to ghcr.io from GitHub Actions. What you get A 7-step publish...

favicon costar6.gumroad.com

The free checks above cover the errors that come up most often in public threads. The official GitHub documentation is the source of truth, and the settings and actions can change, so check them if a step doesn't match what you see.

Top comments (0)