How to Push Image to Registry

How to Push Image to Registry Pushing a container image to a registry is a foundational step in modern software development and DevOps workflows. Whether you're deploying applications using Docker, Kubernetes, or cloud-native platforms, the ability to build, tag, and push container images to a centralized registry ensures consistency, scalability, and reproducibility across environments. This tuto

Nov 10, 2025 - 11:35
Nov 10, 2025 - 11:35
 0

How to Push Image to Registry

Pushing a container image to a registry is a foundational step in modern software development and DevOps workflows. Whether you're deploying applications using Docker, Kubernetes, or cloud-native platforms, the ability to build, tag, and push container images to a centralized registry ensures consistency, scalability, and reproducibility across environments. This tutorial provides a comprehensive, step-by-step guide on how to push an image to a registrycovering public and private registries such as Docker Hub, GitHub Container Registry (GHCR), Google Container Registry (GCR), Amazon Elastic Container Registry (ECR), and Azure Container Registry (ACR). Well also explore best practices, essential tools, real-world examples, and answers to frequently asked questions to help you master this critical skill.

Understanding how to push images to a registry is not just about executing a commandits about establishing secure, automated, and reliable pipelines that support continuous integration and continuous deployment (CI/CD). Without proper image management, teams risk deploying outdated, unverified, or insecure containers, leading to system instability, security breaches, or compliance failures. By the end of this guide, youll have the knowledge to confidently push images to any major registry, optimize your workflows, and align with industry standards.

Step-by-Step Guide

Prerequisites

Before pushing an image to a registry, ensure you have the following:

  • Docker installed on your local machine or CI/CD environment. Verify installation by running docker --version.
  • A container image built locally. If you dont have one, create a simple Dockerfile and build it using docker build -t your-image-name:tag ..
  • Access to a container registry. This could be Docker Hub, GitHub, Google Cloud, AWS, Azure, or a private registry like Harbor or Nexus.
  • Authentication credentials for the registry. Most registries require login via username/password, personal access tokens (PATs), or service account keys.

Step 1: Build Your Container Image

Before pushing, you must have a valid container image. Start by creating a simple Dockerfile. For example:

FROM nginx:alpine

COPY index.html /usr/share/nginx/html/

EXPOSE 80

Place an index.html file in the same directory, then build the image:

docker build -t my-nginx-app:v1 .

The -t flag assigns a tag to your image. The format is repository-name:tag. The tag helps identify versions and is required when pushing to a registry.

Step 2: Log In to Your Registry

Each registry requires authentication before you can push images. Use the appropriate login command:

Docker Hub

docker login

Youll be prompted to enter your Docker Hub username and password or personal access token (recommended for security).

GitHub Container Registry (GHCR)

echo $PAT | docker login ghcr.io -u USERNAME --password-stdin

Replace $PAT with your GitHub Personal Access Token and USERNAME with your GitHub username.

Amazon ECR

First, authenticate using the AWS CLI:

aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ACCOUNT.dkr.ecr.us-east-1.amazonaws.com

Ensure the AWS CLI is configured with valid credentials and the correct region.

Google Container Registry (GCR)

gcloud auth configure-docker

This command configures Docker to use your Google Cloud credentials. Alternatively, use:

docker login https://gcr.io

Azure Container Registry (ACR)

az acr login --name your-registry-name

Ensure youre logged into the Azure CLI with the correct subscription.

Step 3: Tag Your Image with the Registrys Repository Path

After logging in, you must tag your local image with the full registry path. This tells Docker where to push the image.

For Docker Hub:

docker tag my-nginx-app:v1 your-dockerhub-username/my-nginx-app:v1

For GitHub Container Registry:

docker tag my-nginx-app:v1 ghcr.io/your-github-username/my-nginx-app:v1

For Amazon ECR:

docker tag my-nginx-app:v1 ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-nginx-app:v1

For Google Container Registry:

docker tag my-nginx-app:v1 gcr.io/your-project-id/my-nginx-app:v1

For Azure Container Registry:

docker tag my-nginx-app:v1 your-registry-name.azurecr.io/my-nginx-app:v1

Always verify the tag was applied correctly:

docker images

You should see both the original and tagged versions listed.

Step 4: Push the Image to the Registry

Now that your image is properly tagged, push it using:

docker push your-registry-path/my-nginx-app:v1

Example for Docker Hub:

docker push your-dockerhub-username/my-nginx-app:v1

Example for AWS ECR:

docker push ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-nginx-app:v1

Youll see output indicating the upload progresslayers being pushed, checksums verified, and final success confirmation.

Step 5: Verify the Push

After pushing, verify the image exists in the registry:

  • Docker Hub: Visit https://hub.docker.com/repositories and navigate to your repository.
  • GitHub Container Registry: Go to GitHub Packages and select Container Registry.
  • Amazon ECR: Open the AWS Console ? ECR ? Repositories ? Select your repository.
  • Google Container Registry: Visit GCR Console and select your project.
  • Azure Container Registry: Go to Azure Portal ? Container Registries ? Select your registry ? Repositories.

You should see your image listed with the tag you pushed. Click on it to view metadata, layers, and digest.

Step 6: Push Multiple Tags (Optional)

Its common to tag the same image with multiple identifiersfor example, v1, latest, and 2024-06-15. This supports versioning and deployment strategies.

docker tag my-nginx-app:v1 your-dockerhub-username/my-nginx-app:latest

docker tag my-nginx-app:v1 your-dockerhub-username/my-nginx-app:2024-06-15

docker push your-dockerhub-username/my-nginx-app:latest

docker push your-dockerhub-username/my-nginx-app:2024-06-15

Be cautious with the latest tag. While convenient, it can lead to ambiguity in production environments. Use it sparingly and only in development or staging.

Best Practices

Use Semantic Versioning

Always use meaningful tags based on semantic versioning (e.g., v1.2.3) instead of arbitrary names like build123. This improves traceability, rollback capabilities, and integration with CI/CD tools. Avoid using latest in production pipelines unless absolutely necessary.

Minimize Image Size

Smaller images reduce push/pull times, improve security surface, and lower storage costs. Use multi-stage builds to eliminate unnecessary dependencies. For example:

FROM golang:alpine AS builder

WORKDIR /app

COPY . .

RUN go build -o myapp .

FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

COPY --from=builder /app/myapp .

CMD ["./myapp"]

This results in a final image under 10MB instead of hundreds of MBs.

Sign Images with Cosign or Notary

Image signing ensures integrity and authenticity. Use tools like Cosign (from Sigstore) to cryptographically sign your images:

cosign sign --key cosign.key your-registry-path/my-nginx-app:v1

Verify signatures during deployment to prevent tampering:

cosign verify --key cosign.pub your-registry-path/my-nginx-app:v1

Scan Images for Vulnerabilities

Before pushing, scan your images using tools like Trivy, Clair, or Docker Scout:

trivy image your-registry-path/my-nginx-app:v1

Integrate scanning into your CI pipeline to block pushes if critical vulnerabilities are detected.

Use Registry-Specific Naming Conventions

Each registry may have naming rules. For example:

  • Docker Hub: username/repo:tag
  • GitHub: ghcr.io/username/repo:tag
  • ECR: account.dkr.ecr.region.amazonaws.com/repo:tag
  • GCR: gcr.io/project-id/repo:tag
  • ACR: registry-name.azurecr.io/repo:tag

Always follow the registrys naming guidelines to avoid push failures.

Automate with CI/CD

Manually pushing images is error-prone and unscalable. Automate the process using GitHub Actions, GitLab CI, Jenkins, or CircleCI. Example GitHub Actions workflow:

name: Build and Push Image

on:

push:

branches: [ main ]

jobs:

build-and-push:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- name: Set up Docker Buildx

uses: docker/setup-buildx-action@v3

- 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: .

file: ./Dockerfile

push: true

tags: your-dockerhub-username/my-app:latest

This ensures every commit to main triggers a secure, automated build and push.

Rotate Credentials and Use Service Accounts

Never hardcode personal credentials in CI/CD pipelines. Instead, use short-lived tokens or service accounts with minimal permissions. For example, create a dedicated GitHub service account for CI or an AWS IAM role for ECR access.

Enable Immutable Tags (Where Supported)

Some registries (like GitHub Container Registry and Azure Container Registry) support immutable tags. Once pushed, a tag cannot be overwritten. This prevents accidental or malicious updates to production images. Enable this feature in your registry settings.

Tools and Resources

Essential Tools

  • Docker CLI The standard tool for building, tagging, and pushing images.
  • Docker Buildx Enables multi-platform builds and improved caching. Essential for cross-architecture deployments.
  • Trivy Open-source vulnerability scanner for containers and infrastructure.
  • Cosign Container signing and verification tool from the Sigstore project.
  • Skopeo Utility for copying, inspecting, and managing container images without requiring Docker daemon.
  • Regclient Command-line tool for interacting with container registries using the OCI Distribution Specification.

Registry Comparison

Below is a comparison of major container registries:

Registry Provider Authentication Immutable Tags Image Scanning Cost
Docker Hub Docker Username/Password, PAT No Basic (Automated on paid plans) Free (Limited pulls), Paid for teams
GitHub Container Registry GitHub Personal Access Token Yes Yes (via Code Scanning) Free for public repos, Paid for private
Amazon ECR AWS AWS IAM, Access Keys Yes Yes (via Amazon Inspector) Paid (per GB stored, per GB pulled)
Google Container Registry Google Cloud gcloud auth, Service Accounts Yes Yes (via Container Analysis) Paid (per GB stored)
Azure Container Registry Microsoft Azure Azure AD, Service Principals Yes Yes (via Azure Defender for Cloud) Paid (per tier: Basic, Standard, Premium)
Harbor VMware (Open Source) LDAP, OIDC, Username/Password Yes Yes (via Trivy integration) Free (self-hosted)

Documentation and Learning Resources

Real Examples

Example 1: Deploying a Node.js App to Docker Hub via CI/CD

Project: A simple Express.js application hosted on GitHub.

Dockerfile:

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install --only=production

COPY . .

EXPOSE 3000

CMD ["node", "server.js"]

GitHub Actions Workflow:

name: Deploy Node.js App

on:

push:

tags:

- 'v*'

jobs:

publish:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

- name: Extract version

id: version run: echo "VERSION=${GITHUB_REF

refs/tags/}" >> $GITHUB_ENV

- name: Set up Docker Buildx

uses: docker/setup-buildx-action@v3

- 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: .

file: ./Dockerfile

push: true

tags: ${{ secrets.DOCKER_USERNAME }}/my-node-app:${{ env.VERSION }}

When a tag like v1.0.0 is pushed, the workflow automatically builds the image and pushes it to Docker Hub as your-username/my-node-app:v1.0.0.

Example 2: Pushing to AWS ECR with Terraform

Infrastructure as Code (IaC) setup using Terraform to create an ECR repository and push an image:

main.tf:

provider "aws" {

region = "us-east-1"

}

resource "aws_ecr_repository" "my_app" {

name = "my-node-app"

}

data "aws_ecr_authorization_token" "token" {}

output "repository_url" {

value = aws_ecr_repository.my_app.repository_url

}

After applying with terraform apply, use the output URL to tag and push:

docker tag my-node-app:v1.0.0 ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-node-app:v1.0.0

docker push ACCOUNT.dkr.ecr.us-east-1.amazonaws.com/my-node-app:v1.0.0

Example 3: Private Registry with Harbor

Company X runs a private Harbor registry for internal applications. Developers must authenticate via LDAP and use project-specific namespaces.

Steps:

  1. Log in: docker login harbor.company.com
  2. Tag image: docker tag my-service:v1 harbor.company.com/dev-team/my-service:v1
  3. Push: docker push harbor.company.com/dev-team/my-service:v1

Harbors UI shows image scanning results, vulnerability reports, and access logsensuring compliance with internal security policies.

FAQs

What happens if I push an image with a tag that already exists?

By default, most registries allow overwriting tags. This can be dangerous in production. Always use immutable tags or enable the immutable tags feature if your registry supports it. Overwriting latest is common in development but should be avoided in production.

Can I push images without Docker installed?

Yes. Tools like Skopeo and Buildah allow you to push images without a Docker daemon. Skopeo can copy images directly between registries or from local image files.

Why is my push failing with unauthorized: authentication required?

This error means your Docker client is not authenticated. Ensure you ran docker login with the correct credentials for the target registry. Also, verify that your token hasnt expired and that youre using the right registry URL.

How do I delete an image from a registry?

Most registries allow deletion via their web UI or CLI. For example, in ECR:

aws ecr delete-image --repository-name my-repo --image-imageTag v1

In GitHub Container Registry, use the GitHub Packages UI. Always confirm deletion with your teamdeleting images can break deployments.

Can I push images to multiple registries at once?

Yes. Tag the same image with multiple registry paths and push each one:

docker tag my-app:v1 docker.io/username/my-app:v1

docker tag my-app:v1 ghcr.io/username/my-app:v1

docker push docker.io/username/my-app:v1

docker push ghcr.io/username/my-app:v1

This is useful for multi-cloud strategies or redundancy.

How do I check the size of an image before pushing?

Use docker images to see local image sizes. For remote registry details, use:

docker manifest inspect your-registry-path/my-app:v1

Or use skopeo inspect docker://your-registry-path/my-app:v1 for registry-level inspection.

Is it safe to push images from a CI runner?

Yes, if you follow security best practices: use short-lived tokens, restrict permissions, scan for vulnerabilities, sign images, and avoid storing secrets in logs. Never use personal credentialsalways use service accounts.

Whats the difference between a registry and a repository?

A registry is the service or server that stores container images (e.g., Docker Hub, ECR). A repository is a collection of related images under a namespace within a registry (e.g., docker.io/library/nginx is a repository in Docker Hub).

Can I push images to a registry without a Dockerfile?

No. You must first build an image using a Dockerfile (or another build tool like Buildah or Podman). The registry only accepts pre-built images. You cannot push raw files or directories.

Conclusion

Pushing an image to a registry is more than a technical stepits a critical component of modern software delivery. Mastering this process enables teams to build reliable, secure, and scalable containerized applications. Whether youre working with Docker Hub for open-source projects, AWS ECR for enterprise applications, or Harbor for private infrastructure, the principles remain the same: build, tag, authenticate, push, and verify.

By following the best practices outlined in this guideusing semantic versioning, scanning for vulnerabilities, signing images, automating with CI/CD, and leveraging secure credentialsyou not only ensure operational efficiency but also strengthen your organizations security posture. As container adoption continues to grow, the ability to manage images effectively will become increasingly vital for developers, DevOps engineers, and platform teams alike.

Start small: build one image, push it to Docker Hub, and observe the workflow. Then scale upintegrate scanning, signing, and automation. The journey from local development to production-grade container deployment begins with a single push command. Make it count.