Publish docker images to GitHub Container Registry (ghcr)

November 24, 2022 by Anuraj

Docker GitHub Container

This post is about how to publish docker images to GitHub Container Registry. GitHub offers a container registry where we can publish docker images as public and private.

To publish a docker image to GitHub Container registry, first we need to create a Personal Access Token, then login to the Container registry with your username and PAT. And finally push the image to GitHub Container Registry.

First we need to create Personal Access Token. Navigate to then generate new token - classic. In the screen, we need to give the name, expiration time and required scopes. For publishing images we require following permissions - write:packages, read:packages and delete:packages.

Generate Github PAT

Personal Access Token aka PAT is same as Password. Once generated, we need to copy the PAT and keep it in a secure location. We need this token to login to the container registry. We won’t be able to view it again. If required we can re generate.

Generated Github PAT

Next we need to create the container image. I am using a Minimal Web API project with Microsoft.NET.Build.Containers nuget package so that I can build the docker image without any Dockerfile. More details checkout this blog post - Creating Containers in .NET 7 with the .NET CLI. We can build the docker image with the command - dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer

Next we need to login to Github Container Registry. First we need to create environment variable, I am using Powershell. I am setting the GitHub PAT to an environment variable. Then we need to login using docker login.

$env:CR_PAT = 'ghp_89M4r14PsdoPAB7azAwPP7MPIKPPjZ1zAdpA'
Write-Output $env:CR_PAT | docker login -u anuraj --password-stdin

Once we execute this, we will get a Login succeeded message. Next we can publish the container image with docker push command. Please note we need to make the container name like<GITHUB USERNAME>/<IMAGE NAME>:<IMAGE TAG>. We can either do it using docker tag command like this - docker tag minimalapi or we can the container image customization tags in the project file like this. I am using the second one.


Now publish the project with dotnet publish command, which will generate a container image with the name in your local machine. Then execute the command docker push which will publish the image to Github container registry.

Docker Push command

And we will be able to see the container image in the packages section - - Replace the my github username with yours.

We can publish the container image from GitHub Action as well. It is recommended to use GitHub Token to publish the image instead of the Personal Access Token. GitHub already provides documentation around this.

Here is the action with dotnet publish and publishing the image to GitHub Container registry.

name: CI
    branches: [main]
      - ""
    branches: [main]
      - ""

    runs-on: ubuntu-latest

      - uses: actions/checkout@v2

      - name: Set up .NET Core
        uses: actions/setup-dotnet@v1
          dotnet-version: "7.0.x"
          include-prerelease: true

      - name: Build with dotnet
        run: dotnet build --configuration Release

      - name: Publishing the image to local container registry
        run: dotnet publish --os linux --arch x64 -p:PublishProfile=DefaultContainer

      - name: Login with Github Container registry
        uses: docker/login-action@v2
          username: ${{ }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Publish to Github Container registry
        run: docker push

And here the execution details.

GitHub Action Execution

This way we can create and publish a container image to GitHub Container Registry. And We also explored how to automate it with using GitHub actions.

Happy Programming.

Copyright © 2024 Anuraj. Blog content licensed under the Creative Commons CC BY 2.5 | Unless otherwise stated or granted, code samples licensed under the MIT license. This is a personal blog. The opinions expressed here represent my own and not those of my employer. Powered by Jekyll. Hosted with ❤ by GitHub