Skip to content
Go back

How to grant GitHub Container Registry permissions to GitHub Actions

| Last edited: 3 days ago

I ran into an annoying issue while deploying my Astro blog using GitHub Actions. The Docker image built fine locally and the docker push to GitHub Container Registry worked from my terminal. But when I tried to automate this through GitHub Actions, I hit this error:

denied: permission_denied: write_package
Error: Process completed with exit code 1.

The strange part was that I had nearly identical workflow steps working in another project. Same image tag format, same use of GITHUB_TOKEN, and the same secret permissions in the workflow file.

The problem

It turns out the GitHub Container Registry enforces package-level permissions that are not automatically granted, even when your GitHub Action has packages: write permissions.

By default, new packages are private and unlinked to any repository. That means your GitHub Action doesn’t have the rights it needs to push updated images.

The fix

You need to go into the Package settings for the container on GitHub and explicitly grant access to the repository that owns the Action.

  1. Navigate to your container package (e.g. https://github.com/users/ahoog42/packages/container/andrewhoog-astro).
  2. Click Package settings.
  3. Under Manage Actions access, click Add Repository.
  4. Select the repository where your GitHub Action is defined.
  5. Make sure the role is set to Write.

Screenshots below walk through the steps:

Initial state, no repository access granted

No repository linked

Granting access to the repo

Grant repo access

Choosing the Write role

Set write permission

Optionally, connect the repo via Dockerfile

You can also link the repo by adding this line to your Dockerfile:

LABEL org.opencontainers.image.source=https://github.com/ahoog42/andrewhoog-astro

This isn’t required for permissions, but helps with GitHub UI integration and metadata.


Once access was granted and the role set to Write, the GitHub Action completed without error.

Hope this saves you time debugging.


Share this post on:

Previous Post
Uncovering Audio Source with macOS Control Center
Next Post
How I debugged a Let's Encrypt TLS cert renewal error with ChatGPT