Chapitre 2
02 — Containers & Docker
02 — Containers & Docker
Course: Containers & Docker
1. Container Fundamentals
1.1 What Are Containers?
Containers are lightweight, portable, isolated environments for running applications. They share the host OS kernel but have isolated filesystems, processes, and network stacks.
Containers vs VMs:
| Aspect | Container | VM |
|---|---|---|
| Kernel | Shares host kernel | Full OS kernel |
| Isolation | Namespaces + cgroups | Hypervisor-level |
| Startup | Milliseconds | Seconds to minutes |
| Size | MBs | GBs |
| Density | High | Lower |
1.2 OCI Standards
The Open Container Initiative (OCI) defines:
- Image Spec: Standard format for container images
- Runtime Spec: Standard behavior for container runtimes
OCI-compliant runtimes:
- runc (default Docker runtime)
- containerd (high-level container manager)
- crun (faster, written in C)
- Kata Containers (VM-level isolation via OCI)
2. Docker Images
2.1 Multi-Stage Builds
Multi-stage builds optimize image size by separating build and runtime environments.
# Build stage
FROM golang:1.21 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app/server .
# Runtime stage
FROM alpine:3.19
RUN apk add --no-cache ca-certificates tzdata
COPY --from=builder /app/server /server
EXPOSE 8080
USER nobody
ENTRYPOINT ["/server"]
2.2 Slim Images
| Base Image | Size | Use Case |
|---|---|---|
| alpine | ~5MB | Minimal, musl libc |
| distroless | ~10MB | Google's minimal, no package manager |
| scratch | 0MB | Fully static binaries |
| ubuntu:22.04 | ~77MB | Full distro, compatibility |
| debian:slim | ~80MB | Balanced |
2.3 Dockerfile Best Practices
# 1. Use specific tags (not latest)
FROM node:20-alpine
# 2. Set working directory
WORKDIR /app
# 3. Copy package files first (leverage cache)
COPY package*.json ./
RUN npm ci --only=production
# 4. Copy rest of application
COPY . .
# 5. Use non-root user
USER node
# 6. Metadata
LABEL org.opencontainers.image.source="https://github.com/org/app"
LABEL org.opencontainers.image.description="Production app"
# 7. Healthcheck
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
EXPOSE 8080
CMD ["node", "server.js"]
Best practices checklist:
- Pin base image versions
- Minimize layers (combine RUN commands)
- Use
.dockerignore - Use
COPYinstead ofADD(unless extracting tar) - Set
--no-cachefor apt/apk - Drop capabilities in runtime
- Scan images with
docker scout
3. Docker Networking
3.1 Network Drivers
| Driver | Isolation | Use Case |
|---|---|---|
| bridge | Per-host | Default, single-host containers |
| overlay | Multi-host | Swarm services, multi-node |
| macvlan | Direct MAC | Legacy apps needing physical IP |
| host | None | Maximum performance, no isolation |
| none | Full | Full isolation, manual config |
3.2 Bridge Network
# Create custom bridge
docker network create --driver bridge --subnet 172.20.0.0/16 mynet
# Run containers on custom network
docker run --network mynet --name web nginx
docker run --network mynet --name api myapp
# DNS resolution by container name
ping api # Works automatically
3.3 Overlay Network (Swarm)
# Create overlay network
docker network create --driver overlay --attachable my-overlay
# Services on overlay
docker service create --name web --network my-overlay nginx
4. Storage
4.1 Volume Types
| Type | Persistence | Use Case |
|---|---|---|
| Named volume | Persistent (managed by Docker) | Database data, config |
| Bind mount | Persistent (host path) | Development, config files |
| tmpfs | In-memory | Secrets, temporary data |
# Named volume
docker volume create mydata
docker run -v mydata:/data myapp
# Bind mount
docker run -v /host/path:/container/path myapp
# tmpfs
docker run --tmpfs /tmp:noexec,nosuid,size=64m myapp
5. Registries
5.1 Major Registries
| Registry | Provider | Features |
|---|---|---|
| Docker Hub | Docker Inc | Public/private, automated builds |
| Amazon ECR | AWS | IAM integration, lifecycle policies |
| Google GCR/GAR | GCP | Vulnerability scanning, IAM |
| Azure ACR | Azure | AD auth, geo-replication |
| Harbor | CNCF | Open-source, vulnerability scanning, replication |
5.2 Authentication
# Docker Hub
docker login
# ECR
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin <account>.dkr.ecr.us-east-1.amazonaws.com
# GCR
gcloud auth configure-docker
# ACR
az acr login --name myregistry
6. Docker Compose
6.1 Compose File Example
version: "3.9"
services:
web:
build:
context: ./web
dockerfile: Dockerfile.prod
ports:
- "80:8080"
environment:
- NODE_ENV=production
- DB_HOST=db
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
deploy:
replicas: 3
resources:
limits:
cpus: "0.5"
memory: "256M"
api:
image: myapi:latest
expose:
- "3000"
environment:
- REDIS_HOST=redis
secrets:
- api_key
db:
image: postgres:16-alpine
volumes:
- pgdata:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
volumes:
pgdata:
redis-data:
secrets:
api_key:
file: ./secrets/api_key.txt
db_password:
environment: DB_PASSWORD
7. Docker Security
7.1 Rootless Mode
Running Docker daemon without root privileges:
# Install rootless Docker
dockerd-rootless-setuptool.sh install
# Run container rootless
docker run --rm hello-world
export DOCKER_HOST=unix:///run/user/$UID/docker.sock
7.2 Dropping Capabilities
# Drop all capabilities, add only needed ones
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE myapp
# Privileged mode (avoid in production)
docker run --privileged myapp # ❌
7.3 Seccomp
# Default Docker seccomp profile
docker run --security-opt seccomp=/path/to/custom.json myapp
# Disable seccomp (not recommended)
docker run --security-opt seccomp=unconfined myapp
7.4 AppArmor
# Load a profile
apparmor_parser -r -W /etc/apparmor.d/docker-myapp
# Use with container
docker run --security-opt apparmor=docker-myapp myapp
7.5 Image Scanning
# Trivy
trivy image myapp:latest
# Docker Scout
docker scout quickview myapp:latest
docker scout recommendations myapp:latest
# Snyk
snyk container test myapp:latest
8. Containerd & Nerdctl
8.1 Containerd
containerd is an industry-standard container runtime that manages the complete container lifecycle:
# Namespaces
ctr namespace ls
# Images
ctr images pull docker.io/library/nginx:alpine
ctr images ls
# Run container
ctr run --rm docker.io/library/nginx:alpine nginx
# Task management
ctr task ls
8.2 Nerdctl
nerdctl is a Docker-compatible CLI for containerd:
# Equivalent to docker commands
nerdctl run -d --name web -p 80:80 nginx:alpine
nerdctl compose up -d
nerdctl build -t myapp .
nerdctl pull --platform linux/amd64 myapp
nerdctl network create mynet
nerdctl volume create myvol
8.3 containerd vs dockerd
| Feature | dockerd | containerd |
|---|---|---|
| Full Docker API | Yes | No (CRI) |
| Image build | Built-in | Via buildkit |
| Compose | Native | Via nerdctl |
| Swarm mode | Built-in | Not supported |
| Resource usage | Higher | Lower |
| Used by Kubernetes | Via dockershim (deprecated) | Native CRI |
Summary
Docker revolutionized containerization by making it accessible. Modern container workflows use multi-stage builds for small images, Docker Compose for local development, and containerd/nerdctl for lightweight production runtimes. Security is paramount — rootless mode, dropped capabilities, seccomp, AppArmor, and regular image scanning are essential practices.