How to Publish a Docker Container Image
In this article, I'm going to show you how to publish a Docker container image to the GitHub Container Registry using GitHub Actions.
In this article, I'm going to show you how to publish a Docker container image to the GitHub Container Registry using GitHub Actions.
The instructions were written for a Mac, but can be easily ported to other operating systems.
Step 1. Setup
To use these steps you first need a Docker project on GitHub. If you don't have one, see my previous article:
Step 2. Create a GitHub workflows folder
GitHub looks for Action scripts in a particular workflow folder. To create that folder, go to the root of your Docker project and make the directory and subdirectory:
mkdir -p .github/workflows
Step 3. Create a workflow
GitHub Actions will run any workflow file that it finds in the folder that you just created.
Create a file to publish to a docker registry:
touch .github/workflows/publish.yml
Open that file, copy the text below into it, and save it:
The code above does the following:
- Triggers when you push a tag that begins with a v (like v1.2.3)
- Logs in to the GitHub Container Registry (ghcr.io)
- Creates a tag variable that removes the v from the front of the GitHub tag (v1.2.3 becomes just 1.2.3)
- Creates an image path variable starting with ghcr.io/ - the root of the GitHub Container Registry - and ending with the name of the repo (which includes the GitHub username in the path)
- Builds, tags, and publishes your container image to the GitHub Container Registry
You may notice that it pushes two tags:
- one based on the tag (minus the v at the front)
- another is called latest - so that people won't need to know the exact version number and just get the latest
Once the file is saved, commit and push the code to your GitHub repo.
The latest tag
There is some debate about whether using the latest tag is a good thing or if it can lead to problems. If you don't want to use that tag you can edit the workflow to only use the version tag. To do that remove -t ${image}:latest
from the docker build command.
Note that if you do not include the latest tag, commands like docker pull will require a version tag. If the user doesn't include a tag then it will default to the latest tag and then fail.
This is not necessarily a bad thing. It's inconvenient. But it does have the advantage of making the user of your container image define exactly which version they want to use. That will protect them against sudden failures if the latest version changes functionality.
Step 4: Generate a token
To access the GitHub Container Registry you are going to need to generate a token and log in with it. You can do that by doing the following:
- In GitHub open your Profile Settings
- Scroll to the bottom of the left menu and click on Developer settings
- On the left menu select Personal access tokens / Tokens (classic)
- Click Generate new token / Generate new token (classic)
- For Note, you can say something like "Container Registry"
- For Expiration, some say you should never choose the No experiation option - it's up to you
- Check repo
- Check write:packages
- Click Generate token
- Copy the result to the clipboard (never save the result in a repo or doc!)
- Open up terminal window and paste the token into this command (paste over YOUR_TOKEN here):
export CR_PAT=YOUR_TOKEN
- Login using the credential:
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
Step 5. Set the Action permission
If you try to run the workflow as is, you will get an error like this from the build step:
denied: installation not allowed to Write organization package
To make sure that your action has permission to create a package, do the following:
- in your repo, click on Settings
- on the left, expand Actions
- under Actions, select General (not to be confused with General at the top of the menu)
- In the main window scroll down to the Workflow permissions section
- Select Read and write permissions
- Click Save
Step 6. Trigger the build
The workflow is triggered when you push a tag or create a release. To trigger a build using a tag, do the following:
git checkout main
git tag v1.0.0
git push origin --tags
Now go to your GitHub repo and click on the Actions tab.
If the run comes up green, then you should have successfully published the repo.
Remember that every time you issue a tag command you should increment the number (v1.0.0, v1.0.1, v1.0.2, ...).
If you prefer to use the GitHub site to generate a release, I'll include a link to their instructions at the end of this article.
Step 7. Test the published image
When an image is stored on GitHub it is considered a "package". There are a few ways to find packages on GitHub:
- On the Home Page of your GitHub Profile, click the Packages tab
- In your repo, you should see a Packages section in the right column
If your repo was private, then the package visibility will default to private. Otherwise, it will be public.
When you click on a container image package you will see a generated docker pull command that you can copy to the clipboard.
- Copy the docker pull command to the clipboard
- Open up a terminal window, paste in the pull command, and run it
If the pull command succeeded then congratulations! You've published a container image to the GitHub Container Registry!
Note that if this is your first time - and you are using a latest tag - the docker pull command that is generated will use latest as the tag. But if you tag a new version and have multiple versions of your package listed, it will use the version tag instead of latest in the generated command.
Conclusion
In this article you learned how to:
- Create a GitHub Actions workflow
- How to write a workflow to publish a docker container image
- How to find the published package and test it