Container Registry Integration: Pushing Images in CI/CD
Learn to authenticate with a container registry like Docker Hub or GHCR and automate pushing your Docker images using GitHub Actions for seamless deployments.

Previously in this course, we covered Building Images in CI. Now that your pipeline can successfully construct a container image from your source code, the next logical step is moving those artifacts off the ephemeral build runner and into a permanent home where your production servers can find them: the container registry.
Why Registry Integration Matters
A container registry acts as a versioned storage system for your images. Without a registry, your build artifacts exist only for the duration of the CI job. By pushing your images to a registry like Docker Hub or GitHub Container Registry (GHCR), you create a "source of truth" that your deployment targets can pull from later.
Think of it as the difference between a local draft of a document and a published version on a shared drive; until it's in the registry, it isn't ready for the real world.
Authenticating with a Registry
To push images, your CI pipeline needs permission to write to your account. You should never hardcode credentials in your YAML files. Instead, use Managing Secrets to store your DOCKER_USERNAME and DOCKER_PASSWORD (or Personal Access Token).
When using GitHub Actions, the most common and robust way to authenticate is the docker/login-action. It handles the handshake with the registry securely.
Worked Example: Pushing to Docker Hub
Let’s update your existing pipeline to include an authentication step and a push step. We assume you have already built your image and tagged it appropriately.
YAMLjobs: build-and-push: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ secrets.DOCKER_USERNAME }}/my-app:latest
In this example, the docker/build-push-action performs the heavy lifting. By setting push: true, the action automatically pushes the resulting image to the repository specified in the tags parameter after the build completes.
Hands-on Exercise
- Log in to your Docker Hub account and create a new repository (e.g.,
my-awesome-app). - Add your
DOCKER_USERNAMEandDOCKER_PASSWORDas repository secrets in your GitHub repository settings. - Update your workflow YAML file to include the
docker/login-actionanddocker/build-push-actionsteps shown above. - Push your changes and observe the "Actions" tab in GitHub; verify that the image appears in your Docker Hub dashboard after the job succeeds.
Common Pitfalls
- Permissions Errors: If your build fails with a 403 or "denied" error, ensure your secret contains a Personal Access Token (PAT) with "write" permissions, not just your account password.
- Tagging Mismatches: Always ensure the tag you push matches the naming convention of your registry repository. If you push to
my-user/my-app, ensure your tag follows that exact format. - Public vs. Private: By default, new Docker Hub repositories are public. Ensure you verify the visibility settings of your registry, especially if your application code or environment contains sensitive logic.
Frequently Asked Questions
Which registry should I choose? If you are already using GitHub, GHCR (GitHub Container Registry) is highly recommended as it integrates natively with GitHub permissions. Docker Hub is a great, industry-standard alternative for cross-platform projects.
Should I use 'latest' tags for production?
Avoid using latest in production environments. It is better practice to use the Git commit SHA or a semantic version (e.g., v1.0.2) as a tag to ensure you know exactly what code is running.
Does this increase my build time? Yes, adding a push step adds network latency to your pipeline. However, as discussed in Advanced Pipeline Caching, you can mitigate this by utilizing build layers effectively.
Recap
We have moved from building local artifacts to automating the distribution of those artifacts. By integrating registry authentication and pushing images, you've established a reliable link between your code and your future deployment environments. You now have a persistent, versioned record of every successful build.
Up next: Pulling Images in Production, where we will configure your target server to pull these images and refresh your application.
Work with me

CI/CD Pipeline & Docker Containerization
Ship with confidence: automated CI/CD pipelines and Docker setups so every push is tested and deployed — no more manual, error-prone releases.

AI Chatbot & LLM Integration for Your App or Website
Add a smart AI chatbot or LLM feature to your product — trained on your content, integrated into your stack, and shipped by an AI-native engineer.

