🗓️ 11112024 1435
What it is:
- Read-only template containing application code, runtime, libraries, dependencies
- Built from instructions in Dockerfile
- Composed of layered filesystem where each layer is immutable
Problem it solves:
- Distributing applications requires packaging code plus all dependencies, runtime environment, configuration
- Traditional deployment: "install X, then Y, configure Z" with endless variation
- Images are portable, reproducible application packages that run identically everywhere
Image vs Container
Relationship:
- Image: Static template (like a class in programming)
- docker_container: Running instance (like an object)
- One image can spawn many containers
- When you run container, it adds writable layer on top of image's read-only layers
Images don't execute or change. Containers execute and have state.
Layer System
Each Dockerfile instruction creates new layer:
- Layer = read-only filesystem change
- Layers stack on top of each other
Two key benefits:
Caching
- If layer hasn't changed, Docker reuses cached version
- Change one line of code, only rebuild layers above it
Sharing
- Multiple images share common base layers
- Ten Node.js apps share same Node runtime layers
- Saves disk space and transfer time
Pattern: Order Dockerfile instructions from least to most frequently changing. Put dependency installation before copying source code so changing code doesn't invalidate dependency cache. For comprehensive optimization, see dockerfile_best_practices.
Tags and Versions
Images identified by repository and tag:
- Format:
nginx:1.25-alpine latesttag is default but dangerous in production - it's mutable and can change- Always use specific version tags (
1.2.3) or immutable digests (sha256:abc123...) for production
Distribution via Registries
Where images live:
- Docker Hub, private registries, cloud provider registries
- Push images to share them
- Pull to download
- Separates build environment from runtime environment
- Build once, run anywhere
- For choosing and managing registries, see container_registries
Base Images
Most images start FROM a base image:
alpine: Minimal ~5MBubuntu: Familiar but larger- Language runtimes:
golang:1.23,node:20, etc.
Base images provide OS and runtime. You add your application on top.
For minimal images and better security, see docker_multistage_build to exclude build tools from final image.
Immutability Pattern
Images are immutable:
- Configuration that changes between environments (dev/prod) goes in environment variables or mounted config files
- Not baked into image
- This lets you use exact same image everywhere with different runtime config
Never put secrets in images - they persist in layer history even if you delete them in later layers.
Common Pitfalls
Secrets in image layers: If you copy secret file then delete it in next layer, it's still in image history. Anyone with image can extract it. Use build-time secrets or docker_multistage_build to avoid this.
Large bloated images: Installing unnecessary dependencies, keeping package manager caches, or using heavyweight base images makes images huge. Use minimal bases like alpine, clean up in same layer, and use docker_multistage_build for compiled languages.