Skip to content

Docker_images

Docker images are the building blocks of containers. They are read-only templates used to create containers.

A Docker image is a read-only template that contains:

  • A base operating system
  • Application code
  • Runtime libraries
  • Dependencies
  • Configuration files
┌─────────────────────────────────────────────────────────────────────────────┐
│ Docker Image Structure │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────┐ │
│ │ Docker Image │ │
│ ├────────────────────────────────────────────────────────────────┤ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ Application Layer │ │ │
│ │ │ (Your App Code) │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ Runtime Layer │ │ │
│ │ │ (Node.js, Python, Java, Go, etc.) │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ OS Libraries Layer │ │ │
│ │ │ (glibc, openssl, libcrypto) │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ Base OS Layer │ │ │
│ │ │ (Ubuntu, Alpine, Debian) │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Docker images are composed of multiple layers. Each instruction in a Dockerfile creates a new layer.

┌─────────────────────────────────────────────────────────────────────────────┐
│ Image Layer Architecture │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Dockerfile: │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ FROM ubuntu:20.04 │ │
│ │ RUN apt-get update && apt-get install -y nginx │ │
│ │ COPY index.html /var/www/html/ │ │
│ │ CMD ["nginx", "-g", "daemon off;"] │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
│ Resulting Layers: │
│ │
│ ┌─────────────┐ │
│ │ Layer 4 │ CMD - Container configuration │
│ ├─────────────┤ │
│ │ Layer 3 │ COPY - Application files │
│ ├─────────────┤ │
│ │ Layer 2 │ RUN - Installed packages │
│ ├─────────────┤ │
│ │ Layer 1 │ FROM - Base OS image │
│ └─────────────┘ │
│ │
│ Benefits: │
│ - Layers are cached and reused │
│ - Smaller storage footprint │
│ - Faster builds (only rebuild changed layers) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

A Docker registry stores Docker images. The most common registries:

2. Amazon ECR (Elastic Container Registry)

Section titled “2. Amazon ECR (Elastic Container Registry)”
  • AWS-managed private registry
  • Integrated with AWS IAM for authentication
  • Google Cloud’s container registry
  • Now replaced by Artifact Registry
  • Container registry integrated with GitHub
  • Harbor (open-source)
  • GitLab Container Registry
  • Nexus Repository
Terminal window
# Pull latest version
docker pull nginx
# Pull specific tag
docker pull nginx:1.25
# Pull specific architecture
docker pull --platform linux/arm64 nginx
# Pull all available platforms
docker pull --all-platforms nginx
┌─────────────────────────────────────────────────────────────────────────────┐
│ Image Tagging Format │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Format: registry/namespace/repository:tag │
│ │
│ Examples: │
│ │
│ ┌──────────────────────────────────────────────────────────────────┐ │
│ │ nginx:latest → nginx from Docker Hub (latest tag) │ │
│ │ nginx:1.25 → nginx version 1.25 │ │
│ │ nginx:alpine → nginx using Alpine base │ │
│ │ redis:7.0-alpine → Redis 7.0 on Alpine Linux │ │
│ │ myregistry.com:5000/myapp:v1 → Private registry image │ │
│ │ 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1 → AWS ECR │ │
│ └──────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Terminal window
# Pull with verbose output
docker pull -v nginx
# Pull and see progress
docker pull nginx 2>&1 | cat
Terminal window
# List all images
docker images
# List images with full length IDs
docker images --no-trunc
# List images in specific format
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# Filter images
docker images --filter "before=nginx:1.25"
docker images --filter "dangling=true"

Tagging assigns a name and version to an image:

Terminal window
# Tag image for Docker Hub
docker tag myapp:latest myusername/myapp:latest
# Tag for local registry
docker tag myapp:latest localhost:5000/myapp:v1
# Tag for AWS ECR
docker tag myapp:latest 123456789.dkr.ecr.us-east-1.amazonaws.com/myapp:v1
Terminal window
# Login to Docker Hub
docker login
# Push image
docker push myusername/myapp:latest
Terminal window
# Tag for private registry
docker tag myapp:latest myregistry.com:5000/myapp:v1
# Push to private registry
docker push myregistry.com:5000/myapp:v1
Terminal window
# Remove specific image
docker rmi nginx:1.25
# Remove unused images
docker image prune
# Remove all unused images
docker image prune -a
# Remove all dangling images
docker image prune -f
Terminal window
# View image details
docker image inspect nginx:latest
# View image history (layers)
docker history nginx:latest
# View image layers in detail
docker history --no-trunc nginx:latest
┌─────────────────────────────────────────────────────────────────────────────┐
│ Image Management Workflow │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. PULL 2. RUN 3. MODIFY 4. PUSH │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐│
│ │Registry│ │ Create │ │ Container│ │Registry ││
│ │ │──pull──▶ │Container│──run───▶│ (change)│──commit─▶│ ││
│ │ nginx │ │ │ │ │ │ myapp ││
│ │ redis │ │ │ └────┬────┘ │ ││
│ │ myapp │ └─────────┘ │ └────┬────┘│
│ └─────────┘ │ │ │
│ ▼ │ │
│ ┌─────────┐ │ │
│ │ New Image│◀─tag and push──┘ │
│ │ myapp:v2 │ │
│ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘

Docker supports multi-architecture images. When you pull an image, Docker automatically pulls the correct variant for your architecture.

Terminal window
# Check supported platforms
docker manifest inspect nginx
# Example output shows multiple architectures:
# {
# "manifests": [
# {
# "platform": {
# "architecture": "amd64",
# "os": "linux"
# }
# },
# {
# "platform": {
# "architecture": "arm64",
# "os": "linux"
# }
# }
# ]
# }
Terminal window
# Bad
docker pull nginx
# Good
docker pull nginx:1.25.3
Terminal window
# Bad - Large base image
FROM ubuntu:20.04
# Good - Minimal image
FROM alpine:3.18
# Best - Minimal with package manager
FROM node:18-alpine
.dockerignore
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
*.md
# Bad - Frequently changing first
COPY . .
RUN npm install
FROM node:18
# Good - Static dependencies first
FROM node:18
COPY package*.json ./
RUN npm install
COPY . .
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm run build
# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/index.js"]
Terminal window
# Save image to tar file
docker save -o myapp.tar myapp:latest
# Save with compression
docker save myapp:latest | gzip > myapp.tar.gz
Terminal window
# Load image from tar
docker load -i myapp.tar
# Load with compression
docker load < myapp.tar.gz

Enable content trust for secure image pulls:

Terminal window
# Enable Docker Content Trust
export DOCKER_CONTENT_TRUST=1
# Now pulls will only work with signed images
docker pull nginx

In this chapter, you learned:

  • Docker images are read-only templates
  • Images are composed of multiple layers
  • Registries store and distribute images
  • How to pull, tag, push, and manage images
  • Best practices for creating efficient images