~/wiki

Docker

Mis à jour le 2026-08-07Confiance : high
dockerconteneurscomposedockerfiledevopsdeploiement

Le cycle quotidien

docker build -t monapp:dev .
docker run --rm -p 8000:8000 --env-file .env monapp:dev
docker ps
docker logs -f <container>
docker exec -it <container> bash
docker stop <container>
docker ps
CONTAINER ID   IMAGE        COMMAND         STATUS         PORTS                    NAMES
a3f1c9e21b04   monapp:dev   "uvicorn ap…"   Up 2 minutes   0.0.0.0:8000->8000/tcp   brave_liskov

docker ps -a inclut les conteneurs arrêtés. --rm supprime le conteneur à sa sortie, ce qui évite d'en accumuler des dizaines.

Flags de run à connaître

Flag Effet
-p 8000:8000 port hôte:conteneur
-v $(pwd):/app monte le dossier courant, code à chaud
--env-file .env charge les variables
-e KEY=value une variable à la volée
-d détaché, en arrière-plan
-it interactif + tty, pour un shell
--rm nettoie à la sortie
--name api nom fixe au lieu d'un nom généré

Dockerfile Python typique

FROM python:3.12-slim

WORKDIR /app

# Couche de dépendances séparée : elle n'est reconstruite que si les
# requirements changent, pas à chaque édition du code.
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

--host 0.0.0.0 est obligatoire : sur 127.0.0.1 le serveur n'écoute que l'intérieur du conteneur et le port publié ne sert à rien.

Un .dockerignore évite d'envoyer 1 Go de contexte au démon :

.venv
node_modules
.git
__pycache__
*.pyc
.env

Compose

services:
  api:
    build: .
    ports: ["8000:8000"]
    env_file: .env
    volumes: ["./app:/app/app"]      # code à chaud en dev
    depends_on: [db]

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: dev
    ports: ["5432:5432"]
    volumes: ["pgdata:/var/lib/postgresql/data"]

volumes:
  pgdata:
docker compose up              # au premier plan
docker compose up -d --build   # reconstruit puis détache
docker compose logs -f api
docker compose exec api bash
docker compose down            # -v pour supprimer aussi les volumes

--build n'est nécessaire que si le Dockerfile ou les dépendances changent. Avec un volume monté et un reload actif, le code est déjà à jour sans rebuild.

Nettoyer

docker system df               # où part la place
docker system prune -f         # conteneurs et réseaux inutilisés
docker system prune -a -f      # + toutes les images non utilisées
docker builder prune -f        # cache de build
docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          24        3         18.4GB    15.2GB (82%)
Containers      5         1         120MB     98MB (81%)
Local Volumes   7         2         2.1GB     1.4GB (66%)
Build Cache     183       0         9.8GB     9.8GB

Les erreurs qu'on rencontre vraiment

port is already allocated — un autre processus tient le port.

lsof -i :8000
kill -9 $(lsof -t -i :8000)

no space left on device pendant un build — le disque de la VM Docker est plein, faire un prune progressif avant d'envisager un reset.

Le conteneur démarre puis s'arrête aussitôt — le processus principal a rendu la main. docker logs <container> donne toujours la raison.

Build lent à chaque fois — l'ordre des couches est mauvais : COPY . . avant pip install invalide le cache à la moindre modification de code.

Inspecter

docker images
docker inspect <container> | rg -i "ipaddress|mounts" -A 5
docker stats                   # CPU / RAM en direct
docker history monapp:dev      # poids par couche

See also