| name | docker-avance |
| description | Conteneurisation avancée avec Docker — multi-stage builds, réseaux overlay, volumes, registries privés, sécurité d'images, Docker Compose production, debugging de conteneurs |
| version | 1.0.0 |
| author | EVA |
| license | Privée EVA |
| category | mlops |
| metadata | {"EVA":{"tags":["docker","conteneurisation","multi-stage","docker-compose","registry","sécurité","volumes","réseaux"],"related_skills":["kubernetes-avance","ci-cd-pipelines","gitops-argocd"]}} |
Docker — Conteneurisation Avancée
Vue d'ensemble
Docker est la plateforme standard de conteneurisation Linux. Cette compétence couvre la construction d'images optimisées (multi-stage, distroless), la gestion des réseaux et volumes, les registres privés, la sécurité des conteneurs, le debugging avancé et les patterns Docker Compose pour la production.
Quand l'utiliser
- Optimiser la taille et la sécurité d'une image Docker
- Configurer des réseaux multi-conteneurs complexes
- Gérer des volumes persistants avec drivers avancés
- Mettre en place un registre privé (Harbor, Docker Registry)
- Analyser une image pour vulnérabilités
- Debugger un conteneur qui crash au démarrage
- Orchestrer des stacks multi-services avec Docker Compose
1. Multi-stage Builds Optimisés
Python — trois étapes
# STAGE 1 : Dépendances de build
FROM python:3.12-slim AS builder
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
# STAGE 2 : Test & lint
FROM builder AS tester
COPY . .
RUN pip install ruff pytest && \
ruff check . && \
pytest --cov=app tests/
# STAGE 3 : Runtime ultra-léger
FROM python:3.12-alpine AS runner
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY --from=tester /app /app
ENV PATH=/root/.local/bin:$PATH
RUN adduser -D -u 10001 appuser && chown -R appuser:appuser /app
USER appuser
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Go — image distroless (sans OS)
FROM golang:1.23-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/server ./cmd/
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/server /server
USER 65532:65532
EXPOSE 8080
CMD ["/server"]
Résultat : Image Go de ~15 Mo (vs ~800 Mo avec golang:1.23).
2. Réseaux Docker Avancés
docker network create \
--driver overlay \
--attachable \
--subnet 10.0.50.0/24 \
--gateway 10.0.50.1 \
eva-overlay
docker network create \
--driver bridge \
--internal \
--subnet 172.20.0.0/24 \
eva-internal
docker run --network eva-internal --network eva-overlay --name api nginx
docker exec -t api tcpdump -i eth0 port 80
Docker Compose — réseaux isolés
version: "3.8"
networks:
frontend:
driver: bridge
backend:
driver: bridge
internal: true
services:
nginx:
image: nginx:alpine
networks:
- frontend
- backend
ports:
- "443:443"
api:
image: api:latest
networks:
- backend
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
networks:
- backend
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
3. Volumes & Stockage
Drivers de volume avancés
docker volume create \
--driver local \
--opt type=nfs \
--opt o=addr=192.168.1.100,rw,nfsvers=4 \
--opt device=:/exports/data \
eva-nfs-volume
docker run --tmpfs /app/cache:rw,noexec,nosuid,size=512m alpine
docker run -v /host/data:/container/data:z,ro alpine
Backup de volumes
docker run --rm -v eva-data:/source -v $(pwd):/backup alpine \
tar czf /backup/eva-data-$(date +%Y%m%d).tar.gz -C /source .
4. Registre Privé
version: "3.8"
services:
registry:
image: registry:2.8
environment:
REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
volumes:
- registry-data:/data
- ./auth:/auth
ports:
- "5000:5000"
ui:
image: joxit/docker-registry-ui:latest
environment:
REGISTRY_TITLE: "EVA Registry"
REGISTRY_URL: http://registry:5000
DELETE_IMAGES_ENABLED: true
ports:
- "8080:80"
volumes:
registry-data:
docker login registry.eva.local:5000
docker tag api:latest registry.eva.local:5000/api:1.2.3
docker push registry.eva.local:5000/api:1.2.3
docker exec registry bin/registry garbage-collect /etc/docker/registry/config.yml
5. Sécurité des Images
Scan de vulnérabilités
trivy image registry.eva.local/api:1.2.3
trivy image --severity CRITICAL,HIGH --format sarif python:3.12-slim
docker scout quickview nginx:alpine
docker sbom api:latest > sbom.spdx.json
Bonnes pratiques Dockerfile
# MAUVAIS — tout en root, secrets exposés
FROM node:20
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
# BON — utilisateur non-root, sans cache, multi-stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
FROM node:20-alpine
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
COPY --from=builder /app /app
RUN chown -R appuser:appgroup /app
USER appuser
EXPOSE 3000
CMD ["node", "app.js"]
Docker Bench Security (audit CIS)
docker run --rm --net host --pid host --userns host \
--cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /var/lib:/var/lib \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /etc:/etc \
docker/docker-bench-security
6. Debugging Avancé
docker top <container>
docker stats --no-stream <container>
docker stats <container>
docker export <container> | tar tf - | head -20
docker cp <container>:/app/config.yaml ./backup.yaml
docker inspect -f '{{.State.Pid}}' <container>
sudo nsenter -t <PID> -n -- ip addr
docker logs -f --tail=100 --timestamps <container> 2>&1
docker logs <container> 2>&1 | jq 'select(.level == "ERROR")'
docker system df -v
docker buildx du
7. Docker Compose Avancé (patterns production)
version: "3.8"
x-logging: &default-logging
driver: json-file
options:
max-size: "10m"
max-file: "3"
x-healthcheck: &healthcheck
interval: 10s
timeout: 5s
retries: 3
start_period: 30s
services:
app:
image: eva/app:${APP_VERSION:-latest}
restart: unless-stopped
logging: *default-logging
healthcheck:
<<: *healthcheck
test: ["CMD", "wget", "--spider", "http://localhost:8000/healthz"]
deploy:
resources:
limits:
cpus: "2"
memory: "1G"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/app
depends_on:
db:
condition: service_healthy
networks:
- backend
[, ]
[, , ]
8. Pièges Courants
- Tag
latest en production : Impossible de rollback proprement. Toujours taguer avec le SHA du commit ou la version sémantique.
- Build sans cache :
docker build --no-cache jette tout le layer caching. Préférer --cache-from pour les builds CI.
- Variables d'environnement en clair : Ne jamais mettre de secrets dans
docker-compose.yml. Utiliser un fichier .env ou Docker Secrets en Swarm.
- Layer unique géant : Tout mettre dans un seul
RUN rend le cache inutile. Séparer : déps système → déps pip → code.
- Port mapping sur 0.0.0.0 :
ports: ["5432:5432"] expose PostgreSQL à toute la machine. Limiter à 127.0.0.1:5432:5432.
- Pas de .dockerignore : Le contexte du build (dossier entier) est envoyé au daemon — y compris
.git, node_modules, .venv. Créer un .dockerignore avec ces exclusions.
- Conteneur vs processus : Docker ne redémarre pas un processus qui crash dans le conteneur. Utiliser
restart: unless-stopped et healthcheck.
9. Checklist Production