Learning Guides
Menu

Working with Docker Images

10 min readDocker for Developers

Working with Docker Images

Docker images are the blueprints for containers. This chapter explores how images work, how to find and pull them, and how to manage them effectively on your system.

What Is a Docker Image?

A Docker image is a read-only template containing instructions for creating a container. Images include:

  • A base operating system or runtime
  • Application code and dependencies
  • Configuration files
  • Environment variables
  • Default commands to run

Note

Think of an image as a snapshot or template. You can create many containers from a single image, just like you can create many instances from a class in object-oriented programming.

Image Layers

Docker images are built in layers. Each layer represents a set of filesystem changes:

PLAINTEXT
┌─────────────────────────────────────┐
│  Layer 5: CMD ["npm", "start"]      │  ← Metadata layer
├─────────────────────────────────────┤
│  Layer 4: COPY . .                  │  ← Application code
├─────────────────────────────────────┤
│  Layer 3: RUN npm install           │  ← Dependencies
├─────────────────────────────────────┤
│  Layer 2: COPY package.json ./      │  ← Package file
├─────────────────────────────────────┤
│  Layer 1: FROM node:20-alpine       │  ← Base image
└─────────────────────────────────────┘

Layer Benefits

Reusability: Common layers are shared between images. If you have 10 Node.js apps using node:20-alpine, that base layer is stored only once.

Caching: When building images, unchanged layers are cached. Only modified layers need to be rebuilt.

Efficiency: Downloading an image only requires fetching layers you don't already have.

BASH
# When pulling an image, Docker shows layer progress
$ docker pull node:20-alpine
20-alpine: Pulling from library/node
4abcf2066143: Already exists    # Shared layer
5c95156aab8b: Pull complete
...

Layer Sharing

BASH
# Two images might share the same base layers:
 
Image A (node-app:1.0)           Image B (node-app:2.0)
├── app code v1.0                ├── app code v2.0
├── npm dependencies             ├── npm dependencies Same if unchanged
├── node:20-alpine               ├── node:20-alpine Shared
└── alpine:3.19                  └── alpine:3.19 Shared
 
# Only the different layers need additional storage

Finding Images

Docker Hub

Docker Hub is the default public registry with millions of images:

BASH
# Search from command line
docker search nginx
 
# Search with filters
docker search --filter is-official=true nginx
docker search --filter stars=100 python

Search Results

BASH
$ docker search --filter is-official=true postgres
NAME       DESCRIPTION                                     STARS   OFFICIAL
postgres   The PostgreSQL object-relational database sy…   13245   [OK]

Image Types on Docker Hub

TypeDescriptionExample
OfficialMaintained by Docker or vendorsnginx, postgres, node
Verified PublisherFrom verified organizationsbitnami/nginx
CommunityUser-contributed imagesusername/myapp

Warning

Only use official or verified publisher images for production. Community images may contain outdated software, security vulnerabilities, or even malicious code.

Reading Image Documentation

Each image on Docker Hub has documentation explaining:

  • Supported tags and versions
  • How to use the image
  • Environment variables
  • Volume mount points
  • Default commands

Pulling Images

Download images from a registry:

BASH
# Pull the latest version
docker pull nginx
 
# Pull a specific version (tag)
docker pull nginx:1.25
 
# Pull from a specific registry
docker pull gcr.io/google-samples/hello-app:1.0
 
# Pull all tags (rarely needed)
docker pull -a nginx

Understanding Image Tags

Tags identify specific versions of an image:

BASH
# Image name format
registry/repository:tag
 
# Examples
nginx:latest           # Latest version (default)
nginx:1.25             # Version 1.25
nginx:1.25.4           # Specific patch version
nginx:1.25-alpine      # Alpine-based variant
node:20-slim           # Slim Debian variant
python:3.12-bookworm   # Specific Debian version

Note

Always specify explicit version tags in production. The latest tag can change without notice, breaking your deployments.

Common Tag Patterns

PatternMeaningExample
latestMost recent build (avoid in prod)nginx:latest
X.Y.ZSemantic versionnode:20.11.0
X.YMinor version (gets patch updates)node:20.11
XMajor version (gets minor updates)node:20
alpineAlpine Linux base (smaller)node:20-alpine
slimMinimal Debian (smaller)python:3.12-slim
bookwormDebian version namepython:3.12-bookworm

Managing Local Images

Listing Images

BASH
# List all images
docker images
 
# Alternative command
docker image ls
 
# Show all images (including intermediate layers)
docker images -a
 
# Show only image IDs
docker images -q
 
# Filter images
docker images --filter "dangling=true"
docker images --filter "before=nginx:1.24"
docker images node

Image List Output

BASH
$ docker images
REPOSITORY   TAG         IMAGE ID       CREATED        SIZE
node         20-alpine   abcd1234ef56   2 days ago     182MB
nginx        1.25        7890abcd1234   1 week ago     187MB
postgres     16          ef56abcd7890   2 weeks ago    432MB

Image Details

BASH
# Detailed image information
docker inspect nginx:1.25
 
# View image history (layers)
docker history nginx:1.25
 
# Show only layer sizes
docker history --no-trunc nginx:1.25

Removing Images

BASH
# Remove an image
docker rmi nginx:1.25
 
# Remove by image ID
docker rmi abcd1234ef56
 
# Force remove (even if containers use it)
docker rmi -f nginx:1.25
 
# Remove multiple images
docker rmi nginx redis postgres
 
# Remove dangling images (untagged)
docker image prune
 
# Remove all unused images
docker image prune -a
 
# Remove all images (careful!)
docker rmi $(docker images -q)

Warning

You cannot remove an image if a container (running or stopped) is using it. Stop and remove the container first, or use -f to force removal.

Image Variants

Most official images offer multiple variants:

Full Images

Based on Debian/Ubuntu with common tools:

BASH
# Full Debian-based image
docker pull python:3.12
 
# Includes: bash, apt, common utilities
# Size: ~1GB

Slim Images

Minimal Debian with reduced packages:

BASH
# Slim variant
docker pull python:3.12-slim
 
# Smaller but still Debian-based
# Size: ~150MB

Alpine Images

Based on Alpine Linux, extremely small:

BASH
# Alpine variant
docker pull python:3.12-alpine
 
# Minimal, uses musl libc instead of glibc
# Size: ~50MB

Image Size Comparison

ImageSizeUse Case
python:3.12~1 GBFull development environment
python:3.12-slim~150 MBProduction without extras
python:3.12-alpine~50 MBMinimal production images

Note

Alpine uses musl libc instead of glibc, which can cause compatibility issues with some packages. Test thoroughly if using Alpine for complex applications.

Working with Image Tags

Tagging Images

Create additional tags for images:

BASH
# Tag an existing image
docker tag nginx:1.25 myregistry.com/nginx:1.25
docker tag nginx:1.25 myregistry.com/nginx:latest
 
# Tag with a new name
docker tag myapp:latest myapp:v1.0.0
docker tag myapp:latest production/myapp:v1.0.0

Tag Best Practices

BASH
# Use semantic versioning
myapp:1.0.0
myapp:1.0
myapp:1
 
# Include build information
myapp:1.0.0-build.123
myapp:1.0.0-abc1234    # Git commit hash
 
# Environment-specific tags
myapp:1.0.0-dev
myapp:1.0.0-staging
myapp:1.0.0-prod

Saving and Loading Images

Export Images to Files

BASH
# Save an image to a tar archive
docker save -o nginx.tar nginx:1.25
 
# Save multiple images
docker save -o images.tar nginx:1.25 redis:7 postgres:16
 
# Compress while saving
docker save nginx:1.25 | gzip > nginx.tar.gz

Import Images from Files

BASH
# Load an image from a tar archive
docker load -i nginx.tar
 
# Load from compressed file
gunzip -c nginx.tar.gz | docker load
 
# Load from stdin
cat nginx.tar | docker load

Note

Use docker save/load to transfer images between machines without a registry. This is useful for air-gapped environments or quick transfers.

Export vs Save

There's a difference between docker save and docker export:

BASH
# docker save: Saves an image with layers and metadata
docker save myapp:1.0 > myapp-image.tar
 
# docker export: Saves a container's filesystem (flat, no layers)
docker export mycontainer > mycontainer-fs.tar

Image Digests

Digests provide immutable references to specific image builds:

BASH
# Pull by digest (immutable reference)
docker pull nginx@sha256:abc123def456...
 
# View digest of local image
docker inspect --format='{{.RepoDigests}}' nginx:1.25
 
# View digests when listing
docker images --digests

Why Use Digests?

BASH
# Tags can be overwritten
docker pull myapp:1.0    # Could be different builds on different days
 
# Digests are immutable
docker pull myapp@sha256:abc123...    # Always the exact same image
 
# Use digests for reproducible deployments

Inspecting Images

Get detailed information about images:

BASH
# Full inspection output (JSON)
docker inspect nginx:1.25
 
# Extract specific information
docker inspect --format='{{.Config.Env}}' nginx:1.25
docker inspect --format='{{.Config.ExposedPorts}}' nginx:1.25
docker inspect --format='{{.Config.Cmd}}' nginx:1.25
 
# View image architecture
docker inspect --format='{{.Architecture}}' nginx:1.25

Image History

See how an image was built:

BASH
$ docker history node:20-alpine
IMAGE          CREATED       CREATED BY                                      SIZE
abc123def456   2 days ago    CMD ["node"]                                    0B
<missing>      2 days ago    ENTRYPOINT ["docker-entrypoint.sh"]             0B
<missing>      2 days ago    COPY docker-entrypoint.sh /usr/local/bin/ #…    388B
<missing>      2 days ago    RUN /bin/sh -c apk add --no-cache --virtual …   7.85MB
...

Multi-Architecture Images

Modern images support multiple CPU architectures:

BASH
# Docker automatically pulls the right architecture
docker pull nginx:1.25
# Pulls amd64 on Intel/AMD, arm64 on Apple Silicon
 
# View available architectures
docker manifest inspect nginx:1.25
 
# Explicitly specify architecture
docker pull --platform linux/amd64 nginx:1.25
docker pull --platform linux/arm64 nginx:1.25

Note

Docker Desktop on Apple Silicon (M1/M2/M3) can run both arm64 and amd64 images. The amd64 images run via emulation and may be slower.

Disk Space Management

Images consume significant disk space. Monitor and manage it:

BASH
# View Docker disk usage
docker system df
 
# Detailed breakdown
docker system df -v
 
# Clean up everything unused
docker system prune
 
# Clean up everything, including unused images
docker system prune -a
 
# Clean up with volume removal (careful!)
docker system prune -a --volumes

Disk Usage Output

BASH
$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          15        5         4.523GB   3.129GB (69%)
Containers      8         3         234.5MB   125.3MB (53%)
Local Volumes   12        4         892.1MB   456.7MB (51%)
Build Cache     45        0         1.234GB   1.234GB (100%)

Best Practices

Choose the Right Base Image

BASH
# Development: Use full images for debugging
FROM python:3.12
 
# Production: Use slim or alpine for smaller images
FROM python:3.12-slim
# or
FROM python:3.12-alpine

Pin Specific Versions

BASH
# Bad: Can change unexpectedly
FROM node:latest
 
# Better: Major version
FROM node:20
 
# Best: Specific version
FROM node:20.11.0-alpine

Use Official Images

BASH
# Prefer official images
FROM nginx:1.25-alpine
 
# Over community images
# FROM some-user/nginx-custom

Regularly Update Images

BASH
# Pull latest versions of your images
docker pull nginx:1.25
docker pull node:20-alpine
 
# Check for security updates
docker scout cves nginx:1.25

Quick Reference

CommandPurpose
docker pullDownload an image
docker imagesList local images
docker rmiRemove an image
docker tagCreate a new tag for an image
docker saveSave image to tar archive
docker loadLoad image from tar archive
docker inspectView image details
docker historyView image layers
docker image pruneRemove unused images
docker searchSearch Docker Hub

In the next chapter, you'll learn to create your own images using Dockerfiles.