Docker
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