After this lesson, you will be able to: Push and pull images from Docker Hub, GitHub Container Registry (GHCR), and private registries. Tag images correctly.
Built images live somewhere. Registries are how teams share them and how deploys reach them. This lesson covers the most common ones.
Docker Hub (hub.docker.com): the default. Public images are free; private images require a paid plan. Pull rate limits on anonymous pulls. GitHub Container Registry (ghcr.io): integrated with GitHub. Free for public + private (within GitHub Actions). Common for OSS and modern teams. Cloud registries: AWS ECR, Google Artifact Registry, Azure ACR. Used when deploying to the same cloud (lower latency, IAM integration). Self-hosted: Harbor, Distribution Registry (the official one). For air-gapped or strict-compliance shops.
After signing up at hub.docker.com.
# Log indocker login# Username: your-hub-username# Password: <use a personal access token, not your real password># Tag and pushdocker tag myapp:1.0 your-hub-username/myapp:1.0docker push your-hub-username/myapp:1.0# Tag for 'latest' if you wantdocker tag myapp:1.0 your-hub-username/myapp:latestdocker push your-hub-username/myapp:latest# Now anyone can:docker pull your-hub-username/myapp:1.0
Tightly integrated with GitHub repos.
# Create a Personal Access Token (PAT) at github.com/settings/tokens# Permissions needed: read:packages, write:packages, delete:packagesecho $GHCR_PAT | docker login ghcr.io -u your-github-username --password-stdin# Tag and push (note the format: ghcr.io/<owner>/<image>:<tag>)docker tag myapp:1.0 ghcr.io/your-github-username/myapp:1.0docker push ghcr.io/your-github-username/myapp:1.0# In GitHub Actions (free tier):# - uses: docker/login-action@v3# with:# registry: ghcr.io# username: ${{ github.actor }}# password: ${{ secrets.GITHUB_TOKEN }}
NEVER use `:latest` in production. Reproducibility lost. Use semantic versions: `myapp:1.4.2`. Use git SHAs: `myapp:a1b2c3d`. CI tags every image with the build SHA; deploy that SHA. Use environment labels carefully: `myapp:staging` is fine as a moving pointer, but the underlying SHA is what truly identifies the build. Combo: tag both `myapp:a1b2c3d` AND `myapp:staging` when deploying to staging.
Pushing images with hardcoded secrets (env vars set at build time leak through layer inspection). Use runtime env vars. Forgetting `docker login` then debugging 'unauthorized' for an hour. Pushing 5GB images. Multi-stage builds + alpine bases keep them small. Storing PATs in plaintext. Use git-credential-helper or pass via stdin (as above). Anonymous Docker Hub pulls in CI/CD. The rate limit catches you mid-deploy.
Pick the safest approach.
Sign in and purchase access to unlock this lesson.