Managing Images
Learn to tag, remove, save, load, and push Docker images, keeping your local environment clean and your registry organized.
Tagging Images
A tag is just a label that points to an image. The same image can have multiple tags, which is useful for marking the same build as v1.0, latest, and production all at once without duplicating any data.
# Add a new tag to an existing image
docker tag myapp:v1.0 myapp:latest
# Tag the same image for different environments
docker tag myapp:v1.0 myapp:production
docker tag myapp:v1.0 myapp:staging
# Tag it for a private registry before pushing
docker tag myapp:v1.0 registry.company.com/myteam/myapp:v1.0
# Tag with the Git commit SHA for full traceability
docker tag myapp:v1.0 myapp:sha-$(git rev-parse --short HEAD)
Tagging never copies data, every tag pointing to the same image ID shares the exact same layers on disk. It's just an alias.
Removing Images
When you're done with an image, docker rmi removes it:
# Remove by name and tag
docker rmi nginx:latest
# Remove by image ID (you only need enough characters to make it unique)
docker rmi 605c77
# Remove multiple images in one go
docker rmi nginx:1.24 nginx:1.25 postgres:15
# Force removal even if a stopped container still references it
docker rmi -f myapp:old
# Remove all images (use with caution)
docker rmi $(docker images -q)
Note: Docker won't remove an image if any container is stopped. You'll need to remove the container first with docker rm <container-id>, or use the -f flag to force it.
Cleaning Up Unused Images
As you rebuild images over time, old versions lose their tags but the layers stick around on disk. These tagless leftovers are called dangling images and they serve no purpose, they're just taking up space.
# Remove only dangling (untagged) images
docker image prune
# Remove all images not currently used by any container
docker image prune -a
# Skip the confirmation prompt
docker image prune -f
# Remove images that haven't been used in the last 24 hours
docker image prune -a --filter "until=24h"
Pushing Images to a Registry
Once your image is ready, you push it to a registry so other machines like your server, your teammates, your CI pipeline, can pull it down.
Docker Hub:
# Log in with your Docker Hub account
docker login
# Tag the image with your Docker Hub username
docker tag myapp:v1.0 yourusername/myapp:v1.0
# Push it
docker push yourusername/myapp:v1.0
A Private Registry:
# Log in to your company's registry
docker login registry.company.com
# Tag the image for that registry
docker tag myapp:v1.0 registry.company.com/team/myapp:v1.0
# Push it
docker push registry.company.com/team/myapp:v1.0
The process is the same everywhere: log in, tag the image with the registry address, push. The registry address at the front of the tag is how Docker knows where to send it.
Saving Images as Files
Sometimes you need to move an image without using a registry across a network with no internet access, as a backup, or to share directly with someone.
Save an image to a file:
# Export to a tar archive
docker save nginx:latest > nginx.tar
# Save compressed to reduce file size
docker save nginx:latest | gzip > nginx.tar.gz
# Save multiple images into one archive
docker save nginx:latest postgres:16 alpine:3.18 > images.tar
Load it back on another machine:
# Load from a tar file
docker load < nginx.tar
# Load a compressed archive
gunzip -c nginx.tar.gz | docker load
# Alternative syntax if piping feels awkward
docker load --input nginx.tar
After loading, the image shows up in docker images with its original name and tag, no re-tagging needed.
Hands-On Practice: Tag, Save, and Remove
# Step 1: Tag the nginx image as webserver:backup
docker tag nginx webserver:backup
# Step 2: Save it to a tar file
docker save webserver:backup > webserver.tar
# Step 3: Remove the original nginx image
docker rmi nginx:latest
# Step 4: Confirm nginx is gone but webserver:backup still exists
docker images
After step 3, nginx:latest will be gone but webserver:backup which points to the same image data, will still be there. And you'll have a webserver.tar file you could move to another machine.
save/load vs export/import What's the Difference?
Docker has two pairs of commands that look similar but do very different things:
docker save / docker load works with images: it preserves every layer, all the metadata, environment variables, and the full layer history. This is what you should use almost always.
docker export / docker import works with a running or stopped container's filesystem: it flattens everything into a single layer and discards all history and metadata.
# Export a container's filesystem (flattened, loses history)
docker export my-container > container-fs.tar
# Import as a new image
docker import container-fs.tar myimage:imported
Unless you specifically want to flatten an image's layers, stick with save and load.
Full Cleanup: Starting Fresh
When your disk is getting full and you want to wipe the slate clean:
# Remove all stopped containers
docker container prune
# Remove all unused images
docker image prune -a
# Remove unused volumes
docker volume prune
# Remove unused networks
docker network prune
# Do all of the above in one command
docker system prune -a --volumes
The last command removes everything Docker isn't actively using. Run docker system df first to understand what you're about to delete, and make sure anything you want to keep is either running or pushed to a registry.
Key Takeaways
docker tagcreates a new label pointing to an existing image, and no data is copied.docker rmiremoves images. If a container (even stopped) still references it, remove the container first or use-f.- Run
docker system dfbefore pruning to see how much space you'll actually reclaim. docker pushsends your image to a registry. Always tag it with the registry address first.docker save/docker loadtransfers images as files, useful when you don't have registry access.docker system prune -a --volumesremoves everything unused. It's powerful and destructive.
Frequently Asked Questions
If I remove a tag, does it delete the image?
Only if it was the last tag pointing to that image. If the same image has multiple tags (latest, v1.0, production), removing one tag just removes that label, the image and its layers stay on disk until all tags pointing to it are removed.
Why can't I remove an image that I'm not using?
A stopped container still holds a reference to the image it was created from. Run docker ps -a to see stopped containers, remove them with docker rm <id>, and then try removing the image again.
What's the difference between docker image prune and docker image prune -a?
Without -a, it only removes dangling images, untagged leftovers from old builds. With -a, it removes any image not currently used by a running or stopped container. The -a version reclaims much more space but is more aggressive.
Do I need to be logged in to push to Docker Hub?
Yes. Run docker login first. For CI/CD pipelines, use a personal access token instead of your password as it's more secure and can be revoked independently.
Is docker save the same as making a backup?
It's a portable snapshot of your image that can be moved between machines without a registry. It's a reasonable backup approach for small setups, but for production workflows a registry (even a self-hosted one) is much more manageable at scale.