My previous blog posts talks about built-in container support in the .NET SDK. It allows you to create and publish Docker images for your .NET applications without writing any Dockerfile. I also showed how to use the Chiseled Ubuntu base images optimized for .NET and containers. We saw how to publish your Docker images using the .NET SDK to GitHub Packages / Container Registry.
Today, I want to show you how to publish your Docker images using the .NET SDK to GitHub Container Registry using GitHub Actions. It brings us to the next level of automation.
Introduction
GitHub Container Registry is a package hosting service that allows you to host your Docker images and other container images in one place. It integrates with GitHub and GitHub Actions. You can use GitHub Actions to build and publish your Docker images to GitHub Container Registry. You can also use GitHub Actions to build and publish your Docker images to other container registries such as Docker Hub, Azure Container Registry, and Amazon Elastic Container Registry.
Combining GitHub Actions and the .NET SDK makes the whole experience easy and more consistent.
GitHub Packages / Container Registry publish profile
We configure the .NET SDK container building tools using a profile.
It can specify the base image and the target tags. The profile file is a XML file named after the publish profile. Later, you select the publish profile using the PublishProfile property in the GitHub Action.
As we want to publish our Docker images to GitHub Container Registry, we specify the ContainerRegistry property to ghcr.io. We also set the ContainerRepository property to the name of the image we want to publish. The ContainerRepository is configured as a path using your GitHub username, laurentkempe, then / and the image’s name.
1 | <Project> |
Publishing images using GitHub Actions
To be able to publish your Docker images to GitHub Container Registry, you need to create a GitHub Actions workflow. A GitHub Actions workflow is a set of instructions executed when a specific event occurs. For example, you can create a workflow executed when a new tag getting pushed to the repository. You can also create a workflow executed when a pull request get created or triggered manually.
Here is an example of a GitHub action using the .NET SDK container building tools to publish a .NET project to GitHub Container Registry using a .NET publish profile:
1 | name: Publish to GitHub Container Registry |
The publish job is triggered when a git push is made on the main branch matching a path or can be triggered manually. It sets the permissions granted to the GITHUB_TOKEN for the actions in this job. It uses the checkout action to checkout the repository, the setup-dotnet action to install the .NET 7 SDK, the docker/login-action action to login to GitHub Container Registry, and the run action to publish the project using the .NET SDK pushing the container image to GitHub Container Registry.
Failing
Following those steps and running the GitHub Action, you will get the following errors error CONTAINER1013 and CONTAINER1001:
1 | Error: /home/runner/.dotnet/sdk/7.0.403/Containers/build/Microsoft.NET.Build.Containers.targets(201,5): error CONTAINER1013: Failed to push to the output registry: CONTAINER1001: Failed to upload blob using POST https://ghcr.io/v2/laurentkempe/containerplayground/blobs/uploads/; received status code 'Forbidden'. [/home/runner/work/containerPlayground/containerPlayground/PublishGitHubAction/PublishGitHubAction.csproj] |
GitHub Packages supports the GITHUB_TOKEN for easy and secure authentication in your workflows.
Using the
GITHUB_TOKEN
, instead of a personal access token (classic) with the repo scope, increases the security of your repository as you don’t need to use a long-lived personal access token that offers unnecessary access to the repository where your workflow is run.
To be able to publish from a GitHub Action to GitHub Container Registry using GITHUB_TOKEN
, you need to ensure your package has access to your workflow. You must add the repository where the workflow is stored to your package. Then, use the Role drop-down menu to select the write role.
Follow the following four steps from this page to fix the issue.
Success
You can now manually trigger the GitHub Action and see it succeed.
And the package is published to GitHub Container Registry.
Testing the image
The GitHub Action combined with the publishing profile will create a Docker image named ghcr.io/laurentkempe/containerplayground:1.0.1
.
First login to the GitHub Container Registry using the following command using a Personal Access Token with the read:packages
scope:
1 | docker login ghcr.io -u USERNAME |
You will then be able to pull it using the following command:
1 | docker pull ghcr.io/laurentkempe/containerplayground:1.0.1 |
or run it
1 | docker run -it --rm -p 8080:80 ghcr.io/laurentkempe/containerplayground:1.0.1 |
Finally, browse to http://localhost:8080/ to see the “Hello World!” message.
Conclusion
In this blog post, we saw how to publish Docker images to GitHub Container Registry using GitHub Actions and the .NET SDK. We saw how to create a GitHub Actions workflow triggered when a git push is made on the main branch matching a path or can be triggered manually.
I hope this helps. If you have any questions, please leave a comment.
References
My older blog posts on the subject
- .NET 7 SDK built-in container support and Ubuntu Chiseled
- .NET 7 SDK built-in container improvements
- Simplify your .NET Docker image publishing workflow with the .NET SDK
Others
- .NET SDK Containers CI Pipeline Example
- Discover .NET 7 SDK Containers - Support for Authentication and Cross …
- Containerize a .NET app with dotnet publish
- GitHub Actions and .NET | Microsoft Learn
Get the source code on GitHub laurentkempe/containerPlayground/PublishGitHubAction.