Tag and push images to Docker Hub
Tag and push images to Docker Hub, the official registry. Learn the docker tag and docker push commands to share your images with the world or your team. This lesson covers tagging conventions, pushing to repositories, and the workflow for publishing Docker images.
Focus: tag and push images to docker hub
You've built a Docker image locally. It runs perfectly on your machine. But the moment you need to deploy it to a server, share it with a teammate, or use it in a CI/CD pipeline, that image is trapped — only on your laptop. The solution is a container registry, and the most common one is Docker Hub. In this lesson, you'll learn how to tag your image with a meaningful identifier and push it to Docker Hub so anyone (or any system) with access can pull and run it.
The problem this lesson solves
Without a remote registry, your Docker images are isolated. You cannot: - Deploy to a cloud server or Kubernetes cluster. - Share a reproducible build with colleagues. - Use the image in automated pipelines (GitHub Actions, GitLab CI, etc.).
A local image lives in your docker images list, but that list is private to your machine. You need a standard way to distribute images. Docker Hub acts as the central hub for container images — just like GitHub for source code. By the end of this lesson, you'll be able to tag your local image with a registry path and push it so it's available anywhere.
Core concept / mental model
Think of Docker images like application binaries. You build the binary (docker build), but then you need a repository to store it, version it, and distribute it. Docker Hub is that repository. The process has two steps:
- Tag – Give your local image a name that includes the registry (hub) and a version/label.
- Push – Upload the tagged image to the registry.
Key insight: A Docker tag is not a Git tag. It's a label that points to a specific version of your image. The full tag format is:
[registry]/[username]/[image-name]:[tag]. For Docker Hub, the registry is implicit (default isdocker.io).
Definitions
- Image name: The base name of your project (e.g.,
my-app). - Tag: A label for a specific version or variant (e.g.,
v1.0.0,latest,production). - Repository: The collection of all tags for a given image name under your Docker Hub account.
- Registry: The server hosting the repositories (Docker Hub, AWS ECR, GitHub Container Registry, etc.).
The naming convention
A fully qualified image reference looks like:
docker.io/your-dockerhub-username/my-app:v1.0.0
But you can omit docker.io/ — Docker assumes Docker Hub if no other registry is specified.
How it works step by step
- Authenticate to Docker Hub – You need to be logged in to push images. Use
docker loginwith your Docker Hub credentials (or an access token). - Build (or have) an image – You need a local image. Can be one you just built or one pulled from another source.
- Tag the image – Use
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]. The target image must include your Docker Hub username. - Push the tagged image – Use
docker push TARGET_IMAGE[:TAG]. This uploads the image layers to the registry. - Verify on Docker Hub – Check your repository on the Docker Hub website to confirm the image is there.
Hands-on walkthrough
1. Log in to Docker Hub
First, ensure you have a Docker Hub account. Then log in from your terminal:
docker login
You'll be prompted for your username and password (or an access token). For security, consider creating an access token from the Docker Hub website under Account Settings > Security.
Pro tip: Use a personal access token instead of your password. It's more secure and can be scoped to specific permissions.
2. Build a sample image
Create a simple Dockerfile:
# Dockerfile
FROM alpine:latest
CMD ["echo", "Hello from Docker Hub!"]
Build it with:
docker build -t my-hello-world .
Verify the image exists:
docker images
You should see my-hello-world with tag latest (default).
3. Tag the image with your Docker Hub username
Now tag it so it can be pushed to your Docker Hub account. Replace your-username with your actual Docker Hub username:
docker tag my-hello-world:latest your-username/my-hello-world:v1.0
Check that both tags point to the same image ID:
docker images
Example output:
REPOSITORY TAG IMAGE ID CREATED SIZE
my-hello-world latest abc123def456 2 minutes ago 7.05MB
your-username/my-hello-world v1.0 abc123def456 2 minutes ago 7.05MB
The same image ID confirms they are identical — the tag is just a pointer.
4. Push the image to Docker Hub
docker push your-username/my-hello-world:v1.0
You'll see progress output as layers are uploaded:
The push refers to repository [docker.io/your-username/my-hello-world]
9f5e6b0a6b0a: Layer already exists
...
v1.0: digest: sha256:abc123... size: 528
If layers already exist on the registry (e.g., from a previous push), Docker reuses them — saving time and bandwidth.
5. Verify on Docker Hub
Go to hub.docker.com, log in, and navigate to your repository your-username/my-hello-world. You should see the tag v1.0. Anyone with access can now pull it:
docker pull your-username/my-hello-world:v1.0
Compare options / when to choose what
| Action | Command | Use case |
|---|---|---|
| Local tag only | docker tag |
Re‑label an image for local use or before pushing |
| Push to Docker Hub | docker push |
Publish images publicly or to a private repo on Docker Hub |
| Push to another registry | docker push registry.example.com/... |
Use with AWS ECR, GitHub Container Registry, or self-hosted registries |
| Pull from a registry | docker pull |
Download images from any registry you have access to |
When to choose what:
- Use Docker Hub for public open‑source images or simple personal projects.
- Use a private registry (Docker Hub private repos or AWS ECR) for proprietary code.
- Use
latesttag carefully — it should point to the most recent stable version, not a work in progress.
Troubleshooting & edge cases
"Access denied" or "unauthorized"
- Cause: You are not logged in to Docker Hub or your token lacks push permissions.
- Fix: Run
docker loginagain. Use an access token withread-writeorread-write-deletescope.
"Repository does not exist or you may not have access"
- Cause: The repository name in the tag does not match your Docker Hub username, or the repository is private and you're not a collaborator.
- Fix: Ensure the tag is formatted as
your-username/repository-name:tag. If the repo doesn't exist, Docker Hub creates it on the first push (for public repos). For private repos, create it manually first.
Push hangs or is very slow
- Cause: Large image size or slow internet connection. Docker compresses layers before upload.
- Fix: Optimize your image with multi‑stage builds or use a smaller base image (e.g.,
alpine). You can also check Docker Hub status at status.docker.com.
Mistagging: forgetting the username
- Problem: Pushing an image tagged as
my-app:v1.0(no username). Docker interprets this aslibrary/my-app:v1.0(official images), and you get a "denied" error. - Fix: Always include your Docker Hub username:
your-username/my-app:v1.0.
Overwriting latest unintentionally
- Problem: Multiple pushes to
latestwithout version tags can lead to confusion. - Fix: Always tag with a semantic version (e.g.,
v1.0.0) and updatelatestexplicitly only when you're sure.
What you learned & what's next
You now understand how to tag a local Docker image with a reference that includes your Docker Hub username and a version label, and push it to Docker Hub. This allows you to distribute your images, collaborate with teammates, and deploy to any environment.
You learned:
- The structure of a fully qualified image name: [username]/[repo]:[tag].
- How docker login authenticates you to push.
- How docker tag creates a new alias for the same image.
- How docker push uploads image layers to the registry.
- Common pitfalls like missing the username or permission errors.
Next up: In the next lesson, you'll learn how to use Docker Hub images to deploy containers remotely — including pulling images on a server and running them as services. This is the foundation for continuous deployment and container orchestration.
Practice recap
Mini exercise: Build a new Docker image (e.g., a simple Python script that prints 'Hello, Registry!'), tag it with your Docker Hub username and a version of your choice, then push it to Docker Hub. After pushing, delete your local image with docker rmi and pull it back to confirm it works. This solidifies the tag-push-pull cycle.
Common mistakes
- Forgetting to include your Docker Hub username in the tag before pushing — results in 'repository does not exist' error.
- Using your password instead of an access token for docker login — less secure and can lead to token revocation issues.
- Pushing an image with the 'latest' tag only, without version tags — makes it impossible to roll back or reproduce specific builds.
- Not running
docker loginbefore push — leads to 'unauthorized: access denied' error.
Variations
- You can push to a private Docker Hub repository by creating the repo first on hub.docker.com as private, then pushing normally — only authorized users can pull.
- For other registries like AWS ECR, you need to authenticate with the registry's own CLI (e.g.,
aws ecr get-login-password) and include the full registry URL in the tag. - Use
docker push --all-tagsto push all tags of a repository at once, saving time when you have multiple version tags.
Real-world use cases
- Publishing a public base image (e.g.,
nginx-custom) for the community to use viadocker pull your-username/nginx-custom. - Sharing a team's application image among developers and CI/CD systems — tag with commit hash for traceability.
- Storing a golden image of your production environment (e.g.,
python-3.10-slim-buster:1.2.3) to ensure consistent deployments.
Key takeaways
- A Docker tag is a label pointing to a specific version of your image — always include your Docker Hub username and a version tag.
- Use
docker loginwith an access token for secure authentication to Docker Hub. docker tagcreates a new alias for an existing image; it does not duplicate the image data.docker pushuploads only the layers not already present on the registry, optimizing for speed.- Always use semantic versioning (e.g.,
v1.0.0) alongsidelatestto enable rollback and reproducibility. - Verify your push by checking the repository on Docker Hub or using
docker pullfrom another machine.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.