I wanted to use the GitHub Container Registry to host an image for me and had some issues setting things up. To save me some time the next time I need this, and hopefully for someone else as well, I wanted to document how this process works.
Photo by Evgeni Tcherkasski on Unsplash
Beta period
During the beta, the container registry will be free to use. Open-source and public repositories are always entirely free to use, but private repositories will fall under the standard billing rates for GitHub Packages after the beta is over. The free tier of that includes 500 MB of storage and 1 GB of transfer every month.
Enable GitHub Container Registry
Currently, the registry is in Beta, so you’ll need to enable the beta feature on your profile or on the organization level you want to use it on. To do so, go to your profile (or organization) and go to Feature preview
where you can toggle the feature. You’ll notice a new ‘Packages’ tab on you profile page as well.
Preparing to push image to the registry
Currently the only way to authenticate with GitHub Container Registry is to use a GitHub Personal Access Token (PAT). GitHub already knows this is an issue because the PAT can be used in the entire account it is created and will change that later. For now the advisory is to create a specific PAT with only rights to the registry and use that.
These are the scopes you need to enable for the PAT:
- read:packages scope to download container images and read their metadata.
- write:packages scope to download and upload container images and read and write their metadata.
If you want to delete the packages, also use this scope:
- delete:packages scope to delete container images.
Using a GitHub workflow to build and push an image
To push a new image from a workflow, use the complete example below.
The steps used are as follows:
- Get the source code with the docker file and anything you need to build the image. “` yaml
- uses: actions/checkout@v1 “`
- Build the image “` yaml
- name: Build the Docker image run: docker build -t ghcr.io/«ACCOUNT NAME»/«IMAGE NAME»:«VERSION» . “`
- The normal
docker build
step where I am tagging the image with the tag I want to push to the registry “` yaml- name: Build the Docker image run: docker build -t ghcr.io/«ACCOUNT NAME»/«IMAGE NAME»:«VERSION» . “`
- Authenticate with the GitHub Container Registry Using the recommended setup from GitHub) for safety “` yaml
- name: Setup GitHub Container Registry run: echo “${{ secrets.GH_PAT }}” | docker login https://ghcr.io -u ${{ github.actor }} –password-stdin
5. The normal <code>docker push
step to push the container
``` yaml
- name: push to GitHub Container Registry
run: docker push ghcr.io/<<ACCOUNT NAME>>/<<IMAGE NAME>>:<<VERSION>>
Full workflow example
<span class="na">name</span><span class="pi">:</span> <span class="s">Build and Push Docker container</span>
<span class="na">on</span><span class="pi">:</span>
<span class="na">push</span><span class="pi">:</span>
<span class="na">branches</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">main</span>
<span class="na">jobs</span><span class="pi">:</span>
<span class="na">build-and-push</span><span class="pi">:</span>
<span class="na">runs-on</span><span class="pi">:</span> <span class="s">ubuntu-latest</span>
<span class="na">steps</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v1</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Build the Docker image</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">docker build -t ghcr.io/<<ACCOUNT NAME>>/<<IMAGE NAME>>:<<VERSION>> .</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Setup GitHub Container Registry</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">echo "$" | docker login https://ghcr.io -u $ --password-stdin</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">push to GitHub Container Registry</span>
<span class="na">run</span><span class="pi">:</span> <span class="s">docker push ghcr.io/<<ACCOUNT NAME>>/<<IMAGE NAME>>:<<VERSION>></span>
Secret names
Do note that I am using secrets.GH_PAT
to inject the PAT token I’m using into the workflow. You cannot use GITHUB
as a prefix for the secret name, so you need to change that. The secrets user interface doesn’t tell you about that in a great way, which I have sent GitHub feedback on through the GitHub Community.
Consuming the new image
By default the images are kept behind a login, so if you want to make the image publicly available you need to do that for each package.
Keep the image behind a login
To use the image behind the login, you’ll need to authenticate with the registry first:
<span class="n">echo</span><span class="w"> </span><span class="s2">"</span><span class="nv">$</span><span class="nn">env</span><span class="p">:</span><span class="nv">GH_PAT</span><span class="s2">"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">docker</span><span class="w"> </span><span class="nx">login</span><span class="w"> </span><span class="nx">https://ghcr.io</span><span class="w"> </span><span class="nt">-u</span><span class="w"> </span><span class="nx">USERNAME</span><span class="w"> </span><span class="nt">--password-stdin</span><span class="w">
</span>
Enable the public registry
Note: this is a one way trip: it cannot be made private after making it publicly available
To change this setting: go to the package and to its settings:
And make the image publicly available: