Lesson 2.5: Tagging and Pushing Images
Welcome to the final lesson of Phase 2! You've built custom images and optimized them with multi-stage builds. Now it's time to share your work. In this lesson, you'll learn how to tag images meaningfully, push them to a registry like Docker Hub, and pull them anywhere. By the end, you'll be able to distribute your containerized applications to the world (or your team).
Learning Objectives
TIP
By the end of this lesson, you will be able to:
- Understand Docker image naming conventions (repository, tag, digest).
- Tag local images with
docker tag. - Log in to a container registry (Docker Hub) using
docker login. - Push images to a registry with
docker push. - Pull images from a registry using
docker pull. - Choose a versioning strategy for tags (e.g.,
latest, semantic versioning). - Briefly describe private registries and their use cases.
- Avoid common security pitfalls when pushing images.
1. Docker Image Naming
Before pushing, you need to understand how Docker images are named and identified.
1.1. Repository and Tag
A full image name has the format:
[registry/][namespace/]repository[:tag]- registry: The hostname of the registry (defaults to Docker Hub if omitted).
- namespace: Often a username or organization (e.g.,
libraryfor official images on Docker Hub). On Docker Hub, if you omit namespace, it implieslibrary(official images). For your own images, you typically use your Docker Hub username. - repository: The name of the image (e.g.,
ubuntu,myapp). - tag: A label identifying a specific version or variant (e.g.,
latest,1.0,slim). If omitted, defaults tolatest.
Examples:
ubuntu→ Docker Hub, library/ubuntu, tag latest.yourusername/myapp:v1.0→ Docker Hub, yourusername/myapp, tag v1.0.quay.io/prometheus/node-exporter:latest→ Quay.io registry, prometheus/node-exporter, tag latest.
1.2. Digest
Every image also has a unique digest (a SHA256 hash) that identifies its exact content. You can refer to an image by digest to ensure you always get the same image, even if the tag changes.
yourusername/myapp@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2Use docker images --digests to see digests of local images.
2. Tagging Images Locally
The docker tag command creates a new tag (reference) for an existing local image. It does not create a new image; it just adds another name.
Syntax:
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]Examples:
- Tag an existing
myappimage asyourusername/myapp:1.0:bashdocker tag myapp:latest yourusername/myapp:1.0 - Tag an image by ID:bash
docker tag a1b2c3d4 yourusername/myapp:1.0 - Add the
latesttag to a specific version:bashdocker tag yourusername/myapp:1.0 yourusername/myapp:latest
Now docker images will show multiple tags pointing to the same image ID.
3. Docker Hub and Other Registries
3.1. Docker Hub
Docker Hub is the default public registry. It hosts official images and millions of community images. To push your own images, you need a Docker Hub account.
- Free account: unlimited public repositories, one private repository.
- Paid plans: more private repos.
3.2. Other Registries
You can also use other registries:
INFO
- GitHub Container Registry (ghcr.io) – integrated with GitHub.
- Google Container Registry (gcr.io) – for Google Cloud.
- Amazon Elastic Container Registry (ECR) – for AWS.
- Azure Container Registry (ACR) – for Azure.
- Quay.io – from Red Hat.
- Private self-hosted registry (e.g., using the
registry:2image).
Pushing to these is similar but requires different login credentials.
4. Logging In to a Registry
Before pushing, you must authenticate with the registry. Use docker login.
Syntax:
docker login [OPTIONS] [SERVER]- If SERVER is omitted, defaults to Docker Hub.
Example for Docker Hub:
docker loginYou'll be prompted for username and password (or personal access token). For security, consider using a personal access token instead of your password (Docker Hub supports tokens).
Example for another registry:
docker login ghcr.ioLogout:
docker logout5. Pushing Images
Once you're logged in and your image is tagged appropriately, use docker push.
Syntax:
docker push NAME[:TAG]Example:
docker push yourusername/myapp:1.0Docker uploads the image layers to the registry. If the layers already exist (e.g., you pushed a different tag of the same image), only the manifest is updated.
6. Pulling Images
After pushing, you (or anyone) can pull the image from any machine with Docker installed.
docker pull yourusername/myapp:1.0If the tag is omitted, :latest is assumed.
You can also run directly without an explicit pull:
docker run yourusername/myapp:1.0If the image is not local, Docker automatically pulls it.
7. Versioning Strategies
Tagging consistently is crucial for maintainability. Common strategies:
TIP
latesttag: Always points to the most recent stable version. Useful for development, but can be ambiguous.- Semantic versioning (e.g.,
1.2.3):1– major version tag (points to latest 1.x.x).1.2– minor version tag (points to latest 1.2.x).1.2.3– exact patch.
- Environment tags (e.g.,
staging,production) – but careful, these can be misleading if not immutable. - Git commit hash (e.g.,
git-abc1234) – for traceability.
Best practice: Tag with both a version and latest, e.g., push 1.0 and also update latest to point to the same image.
8. Private Registries
For proprietary code, use a private registry. You can:
- Use Docker Hub's private repositories (one free private repo).
- Use cloud provider registries (ECR, GCR, ACR) which are private by default.
- Run your own registry with the official
registryimage.
Running a local registry for testing:
docker run -d -p 5000:5000 --name registry registry:2Then tag and push to localhost:5000/myapp:1.0.
9. Security Considerations
DANGER
Never push secrets (API keys, passwords) in your images. Even if you delete them in a later layer, they remain in the layer history. Use environment variables at runtime or secret management.
- Use personal access tokens instead of your password for
docker login. - Regularly scan your images for vulnerabilities (Docker Hub can do this automatically for private repos).
- Sign your images with Docker Content Trust (advanced) to ensure integrity.
Hands-On Tasks
Task 1: Create a Docker Hub Account (if needed)
- Go to hub.docker.com and sign up for a free account.
- Verify your email.
Task 2: Create a Personal Access Token (optional but recommended)
- In Docker Hub, go to Account Settings → Security → New Access Token.
- Give it a name (e.g., "CLI access") and generate.
- Copy the token (you won't see it again).
Task 3: Login to Docker Hub
docker loginUse your username and the token (or password).
Task 4: Tag an Existing Image
- If you don't have a custom image, build a simple one (e.g., the Go app from the previous lesson).
- Tag it with your Docker Hub username and a version:bash
docker tag myapp:latest yourusername/myapp:1.0 docker tag myapp:latest yourusername/myapp:latest - Verify with
docker images.
Task 5: Push the Image
docker push yourusername/myapp:1.0
docker push yourusername/myapp:latestWatch the layers upload. If you push the same image again, it will be instant (cached).
Task 6: Verify on Docker Hub
- Go to your Docker Hub repositories page. You should see
myappwith tags1.0andlatest.
Task 7: Pull and Run from Another Machine (or Simulate)
If you have another machine with Docker, pull and run:
docker run yourusername/myapp:1.0If not, you can simulate by removing the local image first:
docker rmi yourusername/myapp:1.0
docker pull yourusername/myapp:1.0
docker run yourusername/myapp:1.0Task 8: Explore an Image's Digest
docker images --digests yourusername/myappNote the digest. Try pulling by digest:
docker pull yourusername/myapp@sha256:<digest>Task 9: Push to a Different Tag
Tag and push a new version, e.g., 1.1.
docker tag yourusername/myapp:1.0 yourusername/myapp:1.1
docker push yourusername/myapp:1.1Task 10: (Optional) Run a Local Registry
- Start a local registry container:bash
docker run -d -p 5000:5000 --name registry registry:2 - Tag your image for localhost:bash
docker tag yourusername/myapp:1.0 localhost:5000/myapp:1.0 - Push to local registry:bash
docker push localhost:5000/myapp:1.0 - Remove local image and pull from local registry to test.
Summary
Key Takeaways
- Images are named with
[registry/][namespace/]repository[:tag]. Tag defaults tolatest. docker tagcreates additional references to an existing local image.- Registries store and distribute images; Docker Hub is the default.
- Use
docker loginto authenticate, thendocker pushto upload. docker pulldownloads images (often done automatically bydocker run).- Choose a versioning strategy (semantic versioning +
latestis common). - Private registries keep images secure; you can run your own.
- Never embed secrets in images; use tokens for authentication.
Check Your Understanding
- What is the full format of a Docker image name? Give an example with a custom registry, namespace, and tag.
- How do you create a new tag
myapp:prodfor an existing imagemyapp:2.0? - What command do you use to authenticate with a registry?
- After tagging an image with your Docker Hub username, what command pushes it?
- Why should you avoid using your Docker Hub password directly in
docker login? - What is an image digest, and why might you use it instead of a tag?
- How would you set up a private registry on your local machine for testing?
Click to see answers
[registry/][namespace/]repository[:tag]. Example:gcr.io/myproject/myapp:v1.0(gcr.io is the registry, myproject is the namespace/project, myapp is the repository, v1.0 is the tag).docker tag myapp:2.0 myapp:proddocker login(for Docker Hub) ordocker login <registry-hostname>for other registries.docker push yourusername/myapp:tagname- Because your password grants full account access. A personal access token can be scoped to specific permissions and revoked without affecting your account password.
- A digest is a SHA256 hash that uniquely identifies the exact image content. Using a digest ensures you always pull the exact same image, even if someone has retagged
latestto point to a different version. - Run
docker run -d -p 5000:5000 --name registry registry:2. Then tag images aslocalhost:5000/myapp:tagand push tolocalhost:5000.
Additional Resources
- Docker tag reference
- Docker push reference
- Docker login reference
- Docker Hub Quickstart
- Deploy a registry server
- Best practices for tagging
Next Up
This concludes Phase 2: Building Custom Images. You are now equipped to create, optimize, and share your own images. In Phase 3, we'll dive into Data Persistence & Storage – a critical topic for stateful applications. See you there!