GitHub Actions workflows in combination with GitHub Container Registry Package Visibility
4 min read
965 words
Last week my task was to set up a container image that we wanted to use to test the GitHub Container Registry (GHCR). We wanted to see if we could lower our building times for one of our CI jobs when using GitHub’s registry to pull from. The following is a description of an error we encountered and how we got rid of it. Additionally, I will talk about the different visibility types of container images or packages how they are called at GitHub which were a hurdle we had to take with the registry.
The workflow.yaml
file we used looked something like the following:
name: CI
on:
- pull_request
jobs:
continous-integration:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Log in to the Container registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Pull Image from ghcr.io
run: docker pull ghcr.io/USERNAME/MY_PRIVATE_IMAGE
...
First, we check out the repository and log into the GitHub Container Registry
afterwards with our github.actor
as the username and the GITHUB_TOKEN
as the
password. After a successful login, we’ll pull our container image from the
registry. The steps coming afterwards are not subject to the error we
encountered so these are left out in this article.
The Error
After triggering the workflow with a Pull Request the workflow quickly answered
with an Error response from daemon: unauthorized
when getting into the
docker pull ghcr.io/USERNAME/MY_PRIVATE_IMAGE
step. After searching for an
answer in the GitHub docs and the internet we found out that our problem lays
inside of the visibility type of the container image. I will go into further
detail in the sections below.
Package Settings and Visibility
The problem happened with an image built and saved in a GitHub organization
account. For regular packages in GHCR, there are two types available – public
and private
. There is also a third visibility type of internal
available in
the GitHub Enterprise Cloud plan. After creating and pushing a container image
to GitHub Packages the default visibility type after creation is always set to
private. This can be changed in the package settings. In the following the 3
options will be described and how they influence the ability to work with these
packages in GitHub Actions.
Public
Changing the package’s visibility to public
is the easiest option of these 3
to work with. After making the package public it is visible to anyone and it can
be pulled anonymously via ghcr.io. This is good for public images of
applications like web apps or web servers like nginx. While working with GitHub
Actions this is also the easiest option of visibility since we don’t need to
login to the registry first. So using a public repository is as straightforward
as it gets. However, this was not a viable option for us.
Caution: When making a package public it cannot be made private again
Private
The visibility option of private
is the default one when a container image is
created in the first place. Accessibility is restricted only to people who have
been given the rights from the package owner in the package’s settings. When
given access it is possible to pull or with advanced rights write/update or
delete the package entirely. To pull or change the image via CLI or API one has
to authenticate with the container registry first. Authentication to pull,
update or delete the container image happens via a Personal Access Token (PAT).
How to do that is described in the GitHub documentation. [1] Without
authenticating first one will see the error response unauthorized
from the
beginning of this post. For GitHub Actions workflows GitHub recommends using the
GITHUB_TOKEN
instead which is available in the workflow.
Anyway using a private package in a GitHub Action workflow did not work even
when the account that triggered the workflow and was used to authenticate with
the container registry. The login to the registry even succeeded but the
following pull step failed due to the unauthorized
error shown above. Even
after giving the repository’s GitHub Actions workflow access to the package
[2], it was not possible to pull the image.
Internal
The solution came from a GitHub community answer [3]. The internal
visibility
type is the answer to our problem here. With this setting, the container image
is visible within the whole organization or all the organizations in the
enterprise. Every member will have at least read/pull access to the package.
Write and Delete rights are then given via the package’s settings. The GitHub
Actions documentation is pretty vague about what the internal visibility does
differently than giving the user account permissions who triggers the workflow
in the first place.
Conclusion
After setting the package’s visibility to internal
it was possible for our
workflow to successfully run. Anyway, we found out that the GitHub repository is
not yet a better option to migrate to with our CI runs. Having the possibility
to cache the container image would make a huge difference in speed. But since
this is not (yet?) possible we will stay with our current setup.
Thank you for reading,
Niklas