GitHub Actions
Continuous Integration with GitHub Actions
Workflow Login and Push to GHCR
Automating Docker image builds and pushes to multiple registries—Docker Hub and GitHub Container Registry (GHCR)—is straightforward with GitHub Actions. This guide walks you through defining environment variables, authenticating to GHCR, updating your workflow, and handling permissions.
Step 1: Define Environment Variables
Keep secret credentials out of your code by declaring environment variables at the top of your workflow:
env:
MONGO_URI: mongodb+srv://supercluster.d8jj.mongodb.net/superdata
MONGO_USERNAME: ${{ vars.MONGO_USERNAME }}
MONGO_PASSWORD: ${{ secrets.MONGO_PASSWORD }}
jobs:
unit-testing: …
code-coverage: …
docker: …
Note
Use vars
for non-sensitive values and secrets
for confidential data.
Step 2: View Recent Workflow Runs
After committing your .github/workflows/ci.yml
, check the Actions tab to see your workflow executions:
Understanding GitHub Container Registry
GHCR lets you publish, store, and share Docker and OCI images under the ghcr.io
namespace.
Explore GHCR in GitHub Docs
Visit the GitHub Packages documentation and select Container Registry:
GHCR Namespace Details
All images live under ghcr.io/<OWNER>/<IMAGE>
:
Step 3: Authenticate to GHCR
Authenticating uses a GitHub token with write permissions to packages
. The registry is ghcr.io
, username is your GitHub account, and the password is a Personal Access Token (PAT) or $GITHUB_TOKEN
.
export CR_PAT=YOUR_TOKEN
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
docker push ghcr.io/NAMESPACE/IMAGE_NAME:latest
docker push ghcr.io/NAMESPACE/IMAGE_NAME:2.5
Warning
By default, GITHUB_TOKEN
only has read access to packages. You must grant write permissions (shown later) to push images.
Step 4: Update Your GitHub Actions Workflow
Under the docker
job, add login, build, test, and push steps.
Login Actions
Registry | Action | Inputs |
---|---|---|
Docker Hub | docker/[email protected] | username: ${{ vars.DOCKERHUB_USERNAME }} , password: ${{ secrets.DOCKERHUB_PASSWORD }} |
GitHub Container Registry | docker/[email protected] | registry: ghcr.io , username: ${{ github.repository_owner }} , password: ${{ secrets.GITHUB_TOKEN }} |
jobs:
docker:
name: Containerization
needs: [unit-testing, code-coverage]
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Docker Hub Login
uses: docker/[email protected]
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: GHCR Login
uses: docker/[email protected]
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
Build Image for Testing
Use docker/build-push-action
with push: false
to build without pushing:
- name: Build image for testing
uses: docker/build-push-action@v4
with:
context: .
push: false
tags: ${{ vars.DOCKERHUB_USERNAME }}/solar-system:${{ github.sha }}
Run Container Tests
Start your container and verify health endpoints:
- name: Test Docker image
run: |
docker images
docker run --name solar-system-app -d \
-p 3000:3000 \
-e MONGO_URI=$MONGO_URI \
-e MONGO_USERNAME=$MONGO_USERNAME \
-e MONGO_PASSWORD=$MONGO_PASSWORD \
${{ vars.DOCKERHUB_USERNAME }}/solar-system:${{ github.sha }}
export IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' solar-system-app)
echo "App IP: $IP"
echo "Testing endpoint"
wget -q -O - 127.0.0.1:3000/live | grep live
Push to Both Registries
Finally, enable push: true
and tag for both Docker Hub and GHCR:
- name: Push to registries
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
${{ vars.DOCKERHUB_USERNAME }}/solar-system:${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/solar-system:${{ github.sha }}
Commit (e.g., chore: add GHCR authentication and push steps
) and monitor:
Handling Push Errors
If you encounter:
denied: installation not allowed to Create organization package
you’ll see a failed Containerization job:
And logs may display:
Step 5: Grant Write Permissions to Packages
Add package write permissions to the docker
job:
jobs:
docker:
permissions:
packages: write
…
Refer to the GitHub Token permissions table:
Re-run the workflow. The Containerization job should now succeed:
Step 6: View All Workflow Runs
Check all runs under your workflow:
If you need to reference a failed run, it appears like this:
Step 7: Pull and Use Your GHCR Image
Now that your image lives on GHCR, you can pull and reuse it:
docker pull ghcr.io/${{ github.repository_owner }}/solar-system:${{ github.sha }}
Use it as a base in other Dockerfiles:
FROM ghcr.io/${{ github.repository_owner }}/solar-system:${{ github.sha }}
Visit your Packages tab to explore your new container package:
Links and References
- GitHub Actions Documentation
- GitHub Container Registry
- Docker Build and Push Action
- Permissions for the GITHUB_TOKEN
Watch Video
Watch video content