Docker
1. Installation
1.1 Installation sur Debian / Ubuntu
Supprimez d'abord les anciennes versions si elles existent :
sudo apt-get remove docker docker-engine docker.io containerd runc
Installez les prérequis et ajoutez le dépôt officiel Docker :
# Installer les dépendances
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg lsb-release
# Ajouter la clé GPG officielle Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Ajouter le dépôt Docker
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Installer Docker Engine
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
ubuntu par debian dans l'URL du dépôt et utilisez $(. /etc/os-release && echo "$VERSION_CODENAME") au lieu de $(lsb_release -cs).
1.2 Installation sur CentOS / RHEL / Rocky Linux
# Supprimer les anciennes versions
sudo yum remove docker docker-client docker-client-latest docker-common \
docker-latest docker-latest-logrotate docker-logrotate docker-engine
# Installer le dépôt Docker
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# Installer Docker Engine
sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Démarrer et activer Docker
sudo systemctl start docker
sudo systemctl enable docker
1.3 Post-installation (toutes distributions)
Ajoutez votre utilisateur au groupe docker pour éviter d'utiliser sudo en permanence :
# Ajouter l'utilisateur courant au groupe docker
sudo usermod -aG docker $USER
# Appliquer les changements (ou se déconnecter/reconnecter)
newgrp docker
# Vérifier que Docker fonctionne
docker run hello-world
docker lui donne un accès équivalent à root sur la machine. Ne le faites que pour les utilisateurs de confiance.
1.4 Configurer le démon Docker
Le fichier de configuration principal est /etc/docker/daemon.json :
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"storage-driver": "overlay2",
"default-address-pools": [
{ "base": "172.20.0.0/16", "size": 24 }
],
"dns": ["8.8.8.8", "8.8.4.4"]
}
Après modification, redémarrez le démon :
sudo systemctl restart docker
daemon.json. Sans limite, les fichiers de logs peuvent remplir le disque rapidement sur un serveur en production.
2. Commandes essentielles
2.1 Gestion des images
# Télécharger une image depuis Docker Hub
docker pull nginx:latest
docker pull php:8.2-fpm-alpine
# Lister les images locales
docker images
docker image ls
# Lister les images avec filtre
docker images --filter "dangling=true"
docker images | grep nginx
# Supprimer une image
docker rmi nginx:latest
docker image rm nginx:latest
# Supprimer toutes les images non utilisées
docker image prune -a
# Inspecter une image (couches, variables, ports)
docker image inspect nginx:latest
# Voir l'historique de construction d'une image
docker image history nginx:latest
# Sauvegarder / Charger une image (transfert hors-ligne)
docker save -o mon_image.tar nginx:latest
docker load -i mon_image.tar
2.2 Gestion des conteneurs
# Lancer un conteneur en arrière-plan
docker run -d --name mon-nginx -p 8080:80 nginx:latest
# Lancer un conteneur interactif (shell)
docker run -it --rm ubuntu:22.04 /bin/bash
# Lister les conteneurs en cours d'exécution
docker ps
# Lister tous les conteneurs (y compris arrêtés)
docker ps -a
# Lister avec format personnalisé
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Ports}}"
# Arrêter / Démarrer / Redémarrer un conteneur
docker stop mon-nginx
docker start mon-nginx
docker restart mon-nginx
# Arrêter tous les conteneurs en cours
docker stop $(docker ps -q)
# Supprimer un conteneur
docker rm mon-nginx
# Supprimer un conteneur en cours d'exécution (forcé)
docker rm -f mon-nginx
# Supprimer tous les conteneurs arrêtés
docker container prune
# Exécuter une commande dans un conteneur actif
docker exec -it mon-nginx /bin/bash
docker exec mon-nginx nginx -t
# Copier des fichiers entre hôte et conteneur
docker cp fichier.conf mon-nginx:/etc/nginx/conf.d/
docker cp mon-nginx:/var/log/nginx/access.log ./access.log
# Voir les stats en temps réel (CPU, RAM, réseau)
docker stats
docker stats mon-nginx
# Inspecter un conteneur (config, réseau, volumes)
docker inspect mon-nginx
# Voir les processus dans un conteneur
docker top mon-nginx
2.3 Logs
# Voir les logs d'un conteneur
docker logs mon-nginx
# Suivre les logs en temps réel
docker logs -f mon-nginx
# Logs avec horodatage
docker logs -t mon-nginx
# Derniers N logs
docker logs --tail 100 mon-nginx
# Logs depuis une date
docker logs --since 2024-01-15T10:00:00 mon-nginx
docker logs --since 30m mon-nginx
# Combiner les options
docker logs -f --tail 50 -t mon-nginx
docker logs --since 1h mon-conteneur 2>&1 | grep -i error pour rechercher rapidement les erreurs de la dernière heure.
3. Dockerfile
3.1 Syntaxe de base
Un Dockerfile définit les instructions pour construire une image Docker :
# Image de base
FROM php:8.2-apache
# Métadonnées
LABEL maintainer="admin@example.com"
LABEL version="1.0"
LABEL description="Application PHP avec Apache"
# Variables d'environnement
ENV APP_ENV=production
ENV APP_DEBUG=false
# Installer des paquets système
RUN apt-get update && apt-get install -y \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
zip unzip \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install gd pdo pdo_mysql opcache \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Répertoire de travail
WORKDIR /var/www/html
# Copier les fichiers de l'application
COPY --chown=www-data:www-data . /var/www/html/
# Exposer le port
EXPOSE 80
# Commande de démarrage
CMD ["apache2-foreground"]
3.2 Instructions principales
| Instruction | Description | Exemple |
|---|---|---|
FROM |
Image de base | FROM ubuntu:22.04 |
RUN |
Exécute une commande lors du build | RUN apt-get update && apt-get install -y curl |
COPY |
Copie des fichiers depuis le contexte de build | COPY ./app /var/www/html |
ADD |
Comme COPY + décompression automatique des archives | ADD archive.tar.gz /opt/ |
WORKDIR |
Définit le répertoire de travail | WORKDIR /app |
ENV |
Définit une variable d'environnement | ENV NODE_ENV=production |
ARG |
Variable de build uniquement | ARG PHP_VERSION=8.2 |
EXPOSE |
Documente le port exposé | EXPOSE 80 443 |
VOLUME |
Déclare un point de montage | VOLUME /data |
CMD |
Commande par défaut (remplacable au run) | CMD ["nginx", "-g", "daemon off;"] |
ENTRYPOINT |
Point d'entrée fixe du conteneur | ENTRYPOINT ["docker-entrypoint.sh"] |
HEALTHCHECK |
Vérification de santé du conteneur | HEALTHCHECK CMD curl -f http://localhost/ || exit 1 |
USER |
Définit l'utilisateur d'exécution | USER www-data |
3.3 Bonnes pratiques
- Minimiser les couches : Regroupez les commandes
RUNavec&&pour réduire le nombre de couches. - Utiliser des images Alpine : Préférez
php:8.2-fpm-alpineàphp:8.2-fpm(image 5x plus petite). - Nettoyer le cache : Ajoutez
&& apt-get clean && rm -rf /var/lib/apt/lists/*après chaqueapt-get install. - Utiliser un .dockerignore : Excluez les fichiers inutiles du contexte de build.
- Ordonner les instructions : Placez les instructions qui changent rarement en haut (FROM, RUN apt install) et les fichiers applicatifs en bas pour optimiser le cache.
- Ne pas exécuter en root : Utilisez
USERpour définir un utilisateur non-root. - Utiliser COPY plutôt que ADD : Sauf si vous avez besoin de la décompression automatique.
- Ajouter un HEALTHCHECK : Pour permettre à Docker de surveiller la santé du service.
Exemple de fichier .dockerignore :
.git
.gitignore
node_modules
*.md
docker-compose*.yml
Dockerfile
.env
.env.*
logs/
tmp/
3.4 Build multi-stage
Le multi-stage build permet de séparer les étapes de compilation et d'exécution, pour produire une image finale légère :
# ---- Étape 1 : Build ----
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# ---- Étape 2 : Image finale ----
FROM nginx:alpine AS production
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -f http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
Construire l'image :
# Build standard
docker build -t mon-app:1.0 .
# Build avec arguments
docker build --build-arg PHP_VERSION=8.2 -t mon-app:1.0 .
# Build avec un fichier Dockerfile alternatif
docker build -f Dockerfile.prod -t mon-app:prod .
# Build sans cache
docker build --no-cache -t mon-app:1.0 .
# Build ciblant une étape spécifique du multi-stage
docker build --target builder -t mon-app:build .
4. Docker Compose
4.1 Structure de base
Docker Compose permet de définir et gérer des applications multi-conteneurs via un fichier docker-compose.yml :
services:
web:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./html:/usr/share/nginx/html:ro
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- php
restart: unless-stopped
networks:
- frontend
php:
build:
context: ./php
dockerfile: Dockerfile
volumes:
- ./html:/var/www/html
environment:
- DB_HOST=db
- DB_NAME=myapp
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- frontend
- backend
db:
image: mariadb:10.11
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
MYSQL_DATABASE: myapp
MYSQL_USER: myapp_user
MYSQL_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_root_password
- db_password
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- backend
volumes:
db_data:
driver: local
networks:
frontend:
backend:
secrets:
db_root_password:
file: ./secrets/db_root_password.txt
db_password:
file: ./secrets/db_password.txt
4.2 Commandes Docker Compose
# Démarrer tous les services en arrière-plan
docker compose up -d
# Démarrer et forcer le rebuild des images
docker compose up -d --build
# Démarrer un service spécifique
docker compose up -d web
# Arrêter tous les services
docker compose down
# Arrêter et supprimer les volumes associés
docker compose down -v
# Voir le statut des services
docker compose ps
# Voir les logs de tous les services
docker compose logs
# Suivre les logs d'un service spécifique
docker compose logs -f php
# Exécuter une commande dans un service
docker compose exec php bash
docker compose exec db mysql -u root -p
# Redémarrer un service
docker compose restart php
# Mettre à jour un service sans arrêter les autres
docker compose up -d --no-deps --build php
# Valider la syntaxe du fichier compose
docker compose config
# Voir la configuration résolue (avec variables substituées)
docker compose config --resolve-image-digests
4.3 Variables d'environnement
Plusieurs méthodes pour passer des variables d'environnement :
Méthode 1 : Directement dans le compose
services:
web:
environment:
- APP_ENV=production
- APP_DEBUG=false
Méthode 2 : Fichier .env
Créez un fichier .env à côté du docker-compose.yml :
# .env
MYSQL_ROOT_PASSWORD=motdepasse_securise
MYSQL_DATABASE=myapp
PHP_VERSION=8.2
NGINX_PORT=80
Puis référencez-les dans le compose :
services:
db:
image: mariadb:10.11
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
web:
ports:
- "${NGINX_PORT}:80"
Méthode 3 : Fichier env_file dédié
services:
web:
env_file:
- ./config/app.env
- ./config/db.env
.env contenant des mots de passe. Ajoutez .env dans votre .gitignore et fournissez un fichier .env.example comme modèle.
4.4 Profiles et déploiement conditionnel
Les profiles permettent de définir des services optionnels (debug, monitoring, etc.) :
services:
web:
image: nginx:alpine
# Pas de profile = démarre toujours
phpmyadmin:
image: phpmyadmin:latest
ports:
- "8080:80"
profiles:
- debug
mailhog:
image: mailhog/mailhog
ports:
- "8025:8025"
profiles:
- debug
# Démarrer uniquement les services sans profile
docker compose up -d
# Démarrer avec les services debug
docker compose --profile debug up -d
5. Volumes et persistance des données
5.1 Types de montage
Docker propose trois types de montage pour la persistance des données :
| Type | Description | Usage recommandé |
|---|---|---|
| volume | Géré par Docker dans /var/lib/docker/volumes/ |
Bases de données, données persistantes |
| bind mount | Montage d'un répertoire de l'hôte | Développement, fichiers de configuration |
| tmpfs | Stocké en mémoire RAM uniquement | Données temporaires, secrets |
5.2 Volumes nommés (recommandé)
# Créer un volume
docker volume create mon_volume
# Lister les volumes
docker volume ls
# Inspecter un volume (voir le chemin sur l'hôte)
docker volume inspect mon_volume
# Utiliser un volume avec docker run
docker run -d --name db \
-v db_data:/var/lib/mysql \
mariadb:10.11
# Supprimer un volume
docker volume rm mon_volume
# Supprimer tous les volumes non utilisés
docker volume prune
5.3 Bind mounts
# Monter un répertoire de l'hôte
docker run -d --name web \
-v /srv/www:/usr/share/nginx/html:ro \
-v /srv/nginx/nginx.conf:/etc/nginx/nginx.conf:ro \
nginx:alpine
# Syntaxe longue (--mount), plus explicite
docker run -d --name web \
--mount type=bind,source=/srv/www,target=/usr/share/nginx/html,readonly \
nginx:alpine
5.4 Volumes dans Docker Compose
services:
db:
image: mariadb:10.11
volumes:
# Volume nommé (persistance gérée par Docker)
- db_data:/var/lib/mysql
# Bind mount en lecture seule pour la config
- ./config/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
# Bind mount pour les scripts d'init
- ./init-db:/docker-entrypoint-initdb.d
volumes:
db_data:
driver: local
# Optionnel : stocker le volume à un emplacement spécifique
driver_opts:
type: none
device: /mnt/data/mysql
o: bind
5.5 Sauvegarder et restaurer un volume
# Sauvegarder un volume dans une archive tar
docker run --rm \
-v db_data:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/db_data_backup.tar.gz -C /source .
# Restaurer un volume depuis une archive
docker run --rm \
-v db_data:/target \
-v $(pwd):/backup \
alpine sh -c "cd /target && tar xzf /backup/db_data_backup.tar.gz"
mysqldump, pg_dump) plutôt qu'une copie des fichiers bruts du volume. C'est plus fiable et portable.
6. Réseaux Docker
6.1 Types de réseaux
| Driver | Description | Usage |
|---|---|---|
| bridge | Réseau isolé par défaut. Les conteneurs communiquent entre eux via DNS interne. | Cas général, applications sur un seul hôte |
| host | Le conteneur utilise directement la pile réseau de l'hôte. Pas d'isolation. | Performance réseau maximale, monitoring |
| overlay | Réseau multi-hôte pour Docker Swarm. | Clusters, microservices distribués |
| macvlan | Attribue une adresse MAC propre au conteneur, visible sur le LAN. | Intégration réseau LAN, appareils IoT |
| none | Aucune connectivité réseau. | Sécurité, traitements isolés |
6.2 Commandes réseau
# Lister les réseaux
docker network ls
# Créer un réseau bridge personnalisé
docker network create mon_reseau
docker network create --subnet=172.28.0.0/16 --gateway=172.28.0.1 mon_reseau
# Inspecter un réseau (voir les conteneurs connectés)
docker network inspect mon_reseau
# Connecter un conteneur existant à un réseau
docker network connect mon_reseau mon-conteneur
# Déconnecter un conteneur d'un réseau
docker network disconnect mon_reseau mon-conteneur
# Supprimer un réseau
docker network rm mon_reseau
# Supprimer tous les réseaux inutilisés
docker network prune
6.3 Réseau bridge personnalisé (recommandé)
Les réseaux bridge personnalisés offrent la résolution DNS automatique par nom de conteneur, contrairement au bridge par défaut :
# Créer un réseau
docker network create app_network
# Lancer des conteneurs sur ce réseau
docker run -d --name web --network app_network nginx:alpine
docker run -d --name api --network app_network node:20-alpine
# Le conteneur "web" peut joindre "api" par son nom
# curl http://api:3000 fonctionne depuis le conteneur "web"
docker0) ne supporte PAS la résolution DNS par nom. Créez toujours un réseau bridge personnalisé pour vos applications multi-conteneurs.
6.4 Réseau host
# Le conteneur partage la pile réseau de l'hôte
# Pas besoin de mapper les ports (-p)
docker run -d --name monitoring --network host prometheus:latest
host est utile pour les outils de monitoring ou de découverte réseau qui ont besoin de voir tout le trafic de l'hôte. En revanche, il supprime complètement l'isolation réseau.
6.5 Réseau macvlan
Permet d'attribuer une adresse IP du LAN directement au conteneur :
# Créer un réseau macvlan
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
lan_network
# Lancer un conteneur avec une IP fixe sur le LAN
docker run -d --name srv-dns \
--network lan_network \
--ip 192.168.1.50 \
pihole/pihole:latest
7. Docker Registry
7.1 Docker Hub
# Se connecter à Docker Hub
docker login
# Se connecter avec un token (CI/CD)
echo $DOCKER_TOKEN | docker login -u monuser --password-stdin
# Taguer une image pour le push
docker tag mon-app:1.0 monuser/mon-app:1.0
docker tag mon-app:1.0 monuser/mon-app:latest
# Pousser l'image
docker push monuser/mon-app:1.0
docker push monuser/mon-app:latest
# Télécharger une image
docker pull monuser/mon-app:1.0
# Se déconnecter
docker logout
7.2 Registry privé
Déployer un registry privé pour stocker vos images en interne :
# Lancer un registry privé
docker run -d -p 5000:5000 --restart=always \
--name registry \
-v registry_data:/var/lib/registry \
registry:2
# Taguer et pousser vers le registry privé
docker tag mon-app:1.0 srv-registry.local:5000/mon-app:1.0
docker push srv-registry.local:5000/mon-app:1.0
# Télécharger depuis le registry privé
docker pull srv-registry.local:5000/mon-app:1.0
# Lister les images du registry (API v2)
curl -s http://srv-registry.local:5000/v2/_catalog | python3 -m json.tool
# Lister les tags d'une image
curl -s http://srv-registry.local:5000/v2/mon-app/tags/list | python3 -m json.tool
/etc/docker/daemon.json :
{
"insecure-registries": ["srv-registry.local:5000"]
}
7.3 Se connecter à d'autres registries
# GitHub Container Registry (ghcr.io)
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin
docker push ghcr.io/USERNAME/mon-app:1.0
# GitLab Container Registry
docker login registry.gitlab.com
docker push registry.gitlab.com/groupe/projet/mon-app:1.0
# AWS ECR
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin 123456789.dkr.ecr.eu-west-1.amazonaws.com
7.4 Stratégie de tags
Adoptez une convention de nommage claire pour vos images :
# Tag par version sémantique
docker tag mon-app:build monuser/mon-app:1.2.3
docker tag mon-app:build monuser/mon-app:1.2
docker tag mon-app:build monuser/mon-app:1
docker tag mon-app:build monuser/mon-app:latest
# Tag par commit Git (utile en CI/CD)
docker tag mon-app:build monuser/mon-app:$(git rev-parse --short HEAD)
# Tag par date
docker tag mon-app:build monuser/mon-app:$(date +%Y%m%d-%H%M%S)
latest en production. Utilisez toujours un tag versionné explicite pour garantir la reproductibilité des déploiements.
8. Commandes de maintenance
8.1 Espace disque
# Voir l'espace utilisé par Docker (résumé)
docker system df
# Version détaillée (chaque image, conteneur, volume)
docker system df -v
8.2 Nettoyage (prune)
# Nettoyage complet (ATTENTION : supprime beaucoup de choses)
# Supprime : conteneurs arrêtés, réseaux inutilisés, images pendantes, cache de build
docker system prune
# Nettoyage complet + images non utilisées + volumes orphelins
docker system prune -a --volumes
# Nettoyage ciblé par type
docker container prune # Conteneurs arrêtés
docker image prune # Images dangling (sans tag)
docker image prune -a # Toutes les images non utilisées
docker volume prune # Volumes orphelins
docker network prune # Réseaux inutilisés
docker builder prune # Cache de build
# Supprimer les images de plus de 24h
docker image prune -a --filter "until=24h"
# Nettoyage sans confirmation
docker system prune -f
docker system prune -a --volumes est destructif. Il supprimera toutes les images non utilisées par un conteneur actif ET tous les volumes orphelins. Vérifiez avec docker system df -v avant d'exécuter cette commande.
8.3 Gestion des logs
# Voir la taille des logs de chaque conteneur
du -sh /var/lib/docker/containers/*/*-json.log
# Tronquer les logs d'un conteneur spécifique (sans redémarrage)
truncate -s 0 $(docker inspect --format='{{.LogPath}}' mon-conteneur)
# Configurer la rotation des logs globalement (/etc/docker/daemon.json)
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
# Configurer la rotation pour un conteneur spécifique
docker run -d \
--log-opt max-size=5m \
--log-opt max-file=3 \
--name mon-app \
mon-image:latest
8.4 Mise à jour des images
# Vérifier si des mises à jour sont disponibles
docker pull nginx:latest
# Mettre à jour un service Compose
docker compose pull
docker compose up -d
# Mettre à jour un service spécifique
docker compose pull db
docker compose up -d --no-deps db
# Script de mise à jour avec vérification de changement
#!/bin/bash
IMAGE="nginx:latest"
OLD_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' $IMAGE 2>/dev/null)
docker pull $IMAGE
NEW_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' $IMAGE)
if [ "$OLD_DIGEST" != "$NEW_DIGEST" ]; then
echo "Image mise à jour, redémarrage du conteneur..."
docker compose up -d --no-deps web
else
echo "Image déjà à jour."
fi
8.5 Surveillance
# Stats en temps réel de tous les conteneurs
docker stats
# Stats formatées
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
# Vérifier l'état de santé des conteneurs
docker ps --filter "health=unhealthy"
# Événements Docker en temps réel
docker events
# Événements filtrés
docker events --filter 'type=container' --filter 'event=die'
docker events --since '1h'
0 3 * * 0 docker system prune -f --filter "until=168h" supprime chaque dimanche les ressources inutilisées de plus de 7 jours.
9. Dépannage courant
9.1 Le conteneur ne démarre pas
# Vérifier les logs du conteneur
docker logs mon-conteneur
# Inspecter la configuration
docker inspect mon-conteneur
# Vérifier l'état de sortie
docker inspect --format='{{.State.ExitCode}}' mon-conteneur
docker inspect --format='{{.State.Error}}' mon-conteneur
# Lancer le conteneur en mode interactif pour débugger
docker run -it --entrypoint /bin/sh mon-image:latest
9.2 Problèmes de réseau
# Vérifier l'adresse IP d'un conteneur
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' mon-conteneur
# Vérifier la connectivité entre conteneurs
docker exec mon-conteneur ping -c 3 autre-conteneur
# Vérifier la résolution DNS dans un conteneur
docker exec mon-conteneur nslookup autre-conteneur
# Tester un port depuis l'intérieur du conteneur
docker exec mon-conteneur curl -v http://autre-conteneur:8080
# Vérifier les ports exposés
docker port mon-conteneur
# Vérifier iptables (si les ports ne sont pas accessibles)
sudo iptables -L -n -t nat | grep DOCKER
9.3 Problèmes de permissions
# Vérifier l'utilisateur du conteneur
docker exec mon-conteneur whoami
docker exec mon-conteneur id
# Vérifier les permissions dans le volume
docker exec mon-conteneur ls -la /var/www/html
# Corriger les permissions (depuis l'hôte)
# UID 33 = www-data dans les images Debian/Ubuntu
sudo chown -R 33:33 /chemin/du/volume
# Corriger les permissions (dans le conteneur)
docker exec mon-conteneur chown -R www-data:www-data /var/www/html
# Lancer avec un utilisateur spécifique
docker run -u 1000:1000 mon-image:latest
9.4 Espace disque saturé
# Diagnostic rapide
docker system df
df -h /var/lib/docker
# Identifier les plus gros conteneurs (logs)
du -sh /var/lib/docker/containers/* | sort -rh | head -10
# Identifier les plus gros volumes
docker system df -v | grep -A 100 "VOLUME NAME"
# Nettoyage d'urgence
docker container prune -f
docker image prune -a -f
docker builder prune -f
# Tronquer les logs de TOUS les conteneurs
for c in $(docker ps -aq); do truncate -s 0 $(docker inspect --format='{{.LogPath}}' $c); done
9.5 Conteneur qui consomme trop de ressources
# Identifier le conteneur gourmand
docker stats --no-stream
# Limiter la mémoire
docker run -d --memory=512m --memory-swap=1g mon-image:latest
# Limiter le CPU
docker run -d --cpus=1.5 mon-image:latest
# Limiter dans Docker Compose
services:
web:
image: nginx:alpine
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 256M
9.6 Problèmes courants avec Docker Compose
# "port is already allocated"
# Un autre service utilise déjà le port
sudo lsof -i :80
sudo ss -tlnp | grep :80
# "network not found" après un docker compose down
docker network prune
docker compose up -d
# "image not found" - forcer le rebuild
docker compose build --no-cache
docker compose up -d --build
# "depends_on" ne suffit pas (le service n'est pas prêt)
# Utilisez la condition "service_healthy" avec un healthcheck
services:
app:
depends_on:
db:
condition: service_healthy
db:
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"]
interval: 5s
timeout: 3s
retries: 10
9.7 Démon Docker en panne
# Vérifier le statut du service
sudo systemctl status docker
# Redémarrer Docker
sudo systemctl restart docker
# Voir les logs du démon
sudo journalctl -u docker --since "10 minutes ago"
sudo journalctl -u docker -f
# Vérifier la configuration
docker info
dockerd --validate
9.8 Commandes utiles de debug
# Lancer un conteneur de debug sur le même réseau
docker run -it --rm --network container:mon-conteneur nicolaka/netshoot
# Lancer un conteneur de debug avec accès au PID namespace
docker run -it --rm --pid container:mon-conteneur alpine sh
# Obtenir un dump complet de la config d'un conteneur
docker inspect mon-conteneur | python3 -m json.tool
# Voir les différences entre l'image et le conteneur en cours
docker diff mon-conteneur
# Exporter un filesystem de conteneur pour analyse
docker export mon-conteneur > conteneur_fs.tar
nicolaka/netshoot est un outil précieux pour le dépannage réseau. Elle contient curl, ping, dig, nslookup, tcpdump, iperf et bien d'autres outils réseau, le tout dans un conteneur léger.