Concept and Structure of Layers

A Docker image is composed of multiple read-only layers. Each layer stores the filesystem changes introduced by a command in the Dockerfile. This is similar to commits in Git. It improves efficiency by storing only the changes.

Docker mounts the layers as a single filesystem using a union file system. A writable container layer is added on top of the last layer. This can be visualized as multiple transparent sheets stacked on top of each other.

How Layers Work

Each instruction in the Dockerfile creates a new layer. Let’s understand this with a simple example:

1
2
3
4
FROM ubuntu:20.04      # Layer 1: Base Ubuntu filesystem
RUN apt-get update    # Layer 2: Package list updates
RUN apt-get install nginx  # Layer 3: Nginx files
COPY app /app        # Layer 4: Application files

Each layer contains only the changes from the previous layer. For example, the nginx installation layer contains only the installed files and does not store the files from previous layers again.

Properties and Benefits of Layers

Key benefits of the layer approach:

  1. Space Efficiency: The same layer can be shared among multiple images. For instance, multiple images based on ubuntu:20.04 share the base Ubuntu layer.

  2. Build Cache: Docker caches layers individually. When building an image, layers that haven’t changed are reused from the cache.

  3. Incremental Pulls: When pulling an image, only the layers that are not already present are pulled again.

Layers and Container Storage

Layer structure when a container runs:

  1. Read-only image layers
  2. Read-write container layer
  3. Copy-on-Write is used when files are modified in the container

If a file modification occurs:

  1. Copies the original file to the container layer
  2. Modifies the copied file
  3. Subsequent accesses go to the modified file

Layer Optimization Strategies

Practices for efficient layer organization:

  1. Place Frequently Changing Layers at the End:
1
2
3
4
5
6
7
8
# Good approach
COPY package.json .
RUN npm install
COPY . .

# Bad approach
COPY . .
RUN npm install
  1. Combine Related Commands:
1
2
3
4
5
6
7
8
9
# Good approach
RUN apt-get update && 
    apt-get install -y nginx && 
    apt-get clean

# Bad approach
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get clean
  1. Delete Unnecessary Files:
1
2
3
RUN apt-get update && 
    apt-get install -y nginx && 
    rm -rf /var/lib/apt/lists/*

Multi-Stage Builds and Layers

Multi-stage builds minimize the layers in the final image:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build

# Runtime stage
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html

The final image contains only the files needed for runtime, without build tools.

Layer Inspection and Analysis

Docker provides tools to inspect layer information:

1
2
3
4
5
# Check layer history
docker history nginx:latest

# Detailed layer information
docker inspect nginx:latest

This gives information about each layer’s:

  • Size
  • Creating command
  • Creation time
  • ID information

Docker’s layer system is a fundamental part of container technology. Understanding and leveraging the properties of layers facilitate efficient image management. This is particularly valuable for reducing build times and saving disk space.