Blog

GitHub Container Registry

06 Jan, 2021
Xebia Background Header Wave

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.

Image of a lighthouse at night

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.

Location to find the preview settings

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.

Personal Access Token Creation

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:

  1. Get the source code with the docker file and anything you need to build the image. “` yaml
    • uses: actions/checkout@v1 “`
  2. Build the image “` yaml
    • name: Build the Docker image run: docker build -t ghcr.io/«ACCOUNT NAME»/«IMAGE NAME»:«VERSION» . “`
  3. 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» . “`
  4. 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: Package settings

And make the image publicly available: Make the image public

Rob Bos
Rob has a strong focus on ALM and DevOps, automating manual tasks and helping teams deliver value to the end-user faster, using DevOps techniques. This is applied on anything Rob comes across, whether it’s an application, infrastructure, serverless or training environments. Additionally, Rob focuses on the management of production environments, including dashboarding, usage statistics for product owners and stakeholders, but also as part of the feedback loop to the developers. A lot of focus goes to GitHub and GitHub Actions, improving the security of applications and DevOps pipelines. Rob is a Trainer (Azure + GitHub), a Microsoft MVP and a LinkedIn Learning Instructor.
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts