Docker — utilisation au quotidien
Sommaire
Les commandes du quotidien : importer des images, lancer des conteneurs, les connecter entre eux et faire persister les données.
1. Récupérer et gérer les images
Une image se récupère depuis un registre, par défaut Docker Hub.
docker search nginx # chercher une image
docker pull nginx # télécharger la dernière version (tag latest)
docker pull nginx:1.25 # télécharger une version précise
docker pull ubuntu:22.04
docker images # lister les images locales
docker image ls # forme moderne, équivalente
docker inspect nginx # métadonnées complètes
docker history nginx # les couches qui composent l'image
docker rmi nginx # supprimer une image
docker rmi -f nginx # forcer, même si un conteneur l'utilise
Toujours préciser un tag en production. latest n'est pas une version
figée : c'est un alias qui change. Un déploiement reproductible aujourd'hui ne le sera plus dans six mois si
l'image sous-jacente a évolué. nginx:1.25 est un contrat, nginx ne l'est pas.
Choisir une image
| Critère | Pourquoi |
|---|---|
| Image officielle ou éditeur vérifié | Une image quelconque de Docker Hub peut contenir n'importe quoi |
| Variante alpine ou slim | Beaucoup plus légère, donc moins de surface d'attaque |
| Date de mise à jour récente | Une image abandonnée embarque des vulnérabilités non corrigées |
| Tag explicite | Reproductibilité |
Importer et exporter sans registre
docker save nginx:1.25 -o nginx.tar # exporter une image vers un fichier
docker load -i nginx.tar # importer une image depuis un fichier
Utile en salle de TP quand l'accès à Docker Hub est filtré, ou pour transférer une image sur un réseau isolé.
2. Lancer un conteneur
docker run -d --name web -p 8080:80 nginx
| Option | Effet |
|---|---|
-d | Détaché : lance en arrière-plan et rend la main |
--name web | Nomme le conteneur ; sinon Docker génère un nom aléatoire |
-p 8080:80 | Publie le port 80 du conteneur sur le port 8080 de l'hôte |
-it | Interactif avec pseudo-terminal, pour un shell |
--rm | Supprime automatiquement le conteneur à son arrêt |
-e VAR=valeur | Définit une variable d'environnement |
-v source:cible | Monte un volume |
--network mon-reseau | Attache le conteneur à un réseau |
--restart unless-stopped | Redémarre le conteneur au boot de l'hôte |
Si l'image n'est pas présente localement, docker run la télécharge automatiquement : le
pull préalable n'est pas obligatoire.
3. Cycle de vie
docker ps # conteneurs en cours d'exécution
docker ps -a # tous, y compris arrêtés
docker ps -q # uniquement les identifiants
docker stop web # arrêt propre
docker start web # relancer
docker restart web
docker kill web # arrêt brutal
docker rm web # supprimer (le conteneur doit être arrêté)
docker rm -f web # forcer l'arrêt et la suppression
docker exec -it web bash # ouvrir un shell dans un conteneur qui tourne
docker exec -it web sh # pour les images minimales (alpine)
docker stats # consommation CPU et mémoire en temps réel
docker top web # processus tournant dans le conteneur
docker stop | docker kill | |
|---|---|---|
| Signal | SIGTERM, puis SIGKILL après 10 s | SIGKILL immédiat |
| Le processus peut | Fermer ses fichiers, vider ses tampons | Rien, il est tué net |
| Risque | Aucun | Corruption de données |
Même logique que kill et kill -9 sous Linux : on tente toujours l'arrêt propre
d'abord. Et docker rm exige un conteneur arrêté, précisément pour éviter de supprimer une
application en train d'écrire.
4. Publication de ports
-p PORT_HÔTE:PORT_CONTENEUR
Sans -p, le conteneur reste joignable par les autres conteneurs de son réseau, mais
pas depuis l'extérieur.
docker run -d --name web1 -p 8080:80 nginx
docker run -d --name web2 -p 8081:80 nginx # second port hôte
docker port web1 # vérifier les redirections
Deux conteneurs ne peuvent pas publier sur le même port hôte : le second échoue avec port is already allocated. C'est justement l'intérêt du mécanisme — plusieurs instances du même service sur une seule machine, chacune sur son port.
5. Logs et inspection
docker logs web # afficher les logs
docker logs -f web # suivre en temps réel (Ctrl+C quitte l'affichage)
docker logs --tail 50 web # les 50 dernières lignes
docker logs -t web # avec horodatage
docker inspect web # configuration complète en JSON
Ctrl + C sur logs -f quitte l'affichage mais n'arrête pas le
conteneur.
Point important : les logs sont stockés avec le conteneur. Le supprimer les supprime. Trois
façons de les conserver : les rediriger avant suppression (docker logs web > web.log), monter un
volume sur le répertoire de logs de l'application, ou configurer un logging driver qui les envoie vers
un collecteur externe (syslog, Fluentd).
6. Volumes et persistance
Le système de fichiers d'un conteneur est éphémère : tout ce qui y est écrit disparaît avec lui. Les volumes règlent ce problème.
Montage d'un dossier de l'hôte (bind mount)
mkdir -p ~/nginxdata
echo "<h1>Ceci est ma page perso</h1>" > ~/nginxdata/index.html
docker run -d --name web-vol -p 8080:80 \
-v ~/nginxdata:/usr/share/nginx/html \
nginx
Volume géré par Docker
docker volume create mesdonnees
docker run -d --name bdd -v mesdonnees:/var/lib/mysql mysql:8
docker volume ls
docker volume inspect mesdonnees
docker volume rm mesdonnees
| Bind mount | Volume nommé | |
|---|---|---|
| Emplacement | Un chemin précis de l'hôte | Géré par Docker dans /var/lib/docker/volumes |
| Usage | Développement : on édite les fichiers directement | Production : données applicatives |
| Portabilité | Dépend de l'arborescence de l'hôte | Indépendant |
| Sauvegarde | Avec les fichiers de l'hôte | Via docker volume ou un conteneur dédié |
Pourquoi la suppression du conteneur n'efface-t-elle pas les données ? Parce que le dossier
appartient à l'hôte : le conteneur ne fait que le monter, comme on monte une clé USB.
Les deux cycles de vie sont indépendants. Même chose pour un volume nommé, qui survit jusqu'à un
docker volume rm explicite.
7. Variables d'environnement
docker run -d --name bdd \
-e MYSQL_ROOT_PASSWORD=motdepasse \
-e MYSQL_DATABASE=gameon \
-v mesdonnees:/var/lib/mysql \
mysql:8
docker exec -it bdd bash
echo $MYSQL_DATABASE
exit
Elles permettent de configurer une image sans la reconstruire : mot de passe d'une base, mode debug, nom d'hôte d'un service. C'est le mécanisme de configuration standard des images officielles, documenté sur leur page Docker Hub.
Pour éviter d'exposer un mot de passe dans l'historique du shell, on utilise un fichier :
docker run --env-file ./config.env -d mysql:8
8. Réseaux Docker
docker network create monreseau
docker network ls
docker network inspect monreseau
docker run -d --name nginx1 --network monreseau nginx
docker run -d --name alpine1 --network monreseau alpine sleep 3600
docker exec -it alpine1 sh
ping nginx1 # répond : résolution par nom
exit
docker network connect monreseau autre-conteneur
docker network disconnect monreseau autre-conteneur
docker network rm monreseau
Sur un réseau utilisateur, Docker fournit un DNS interne : chaque conteneur est joignable
par son nom. C'est ce qui permet à une application de contacter mysql sans
connaître son adresse IP, laquelle change à chaque redémarrage.
Deux conteneurs qui n'appartiennent pas au même réseau ne peuvent pas communiquer : ils sont sur des segments isolés et le DNS interne ne les connaît pas. C'est une fonctionnalité, pas une limite : elle permet de cloisonner, par exemple en plaçant la base de données sur un réseau que le frontal public ne voit pas.
| Type | Comportement |
|---|---|
| bridge (défaut) | Réseau virtuel isolé ; sans réseau utilisateur, pas de résolution par nom |
| host | Le conteneur partage la pile réseau de l'hôte, sans isolation |
| none | Aucun réseau |
| réseau utilisateur | Créé avec docker network create : isolé et avec DNS interne |
9. Plusieurs conteneurs ensemble
Cas typique : une base MySQL et une interface phpMyAdmin sur un réseau commun.
docker network create reseauAdmin
docker run -d --name mysql-db --network reseauAdmin \
-e MYSQL_ROOT_PASSWORD=root \
-e MYSQL_DATABASE=gameon \
-v mysqldata:/var/lib/mysql \
mysql:8
docker run -d --name phpmyadmin --network reseauAdmin \
-e PMA_HOST=mysql-db \
-p 8081:80 \
phpmyadmin
PMA_HOST=mysql-db fonctionne grâce au DNS interne, qui résout le nom du
conteneur. Sans réseau commun, phpMyAdmin ne trouverait pas la base.
La même chose avec Docker Compose
Dans un fichier compose.yaml :
services:
db:
image: mysql:8
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: gameon
volumes:
- mysqldata:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
environment:
PMA_HOST: db
ports:
- "8081:80"
depends_on:
- db
volumes:
mysqldata:
docker compose up -d # démarrer l'ensemble
docker compose ps
docker compose logs -f
docker compose stop
docker compose down # arrêter et supprimer
docker compose down -v # ... y compris les volumes
Compose crée automatiquement un réseau dédié au projet, ce qui rend le docker network create
inutile. Tout l'environnement est décrit dans un fichier versionnable : c'est la forme retenue en production
pour tout déploiement multi-conteneurs.
10. Nettoyage
docker system df # espace disque occupé
docker container prune # conteneurs arrêtés
docker image prune # images sans tag (dangling)
docker volume prune # volumes non utilisés
docker network prune # réseaux non utilisés
docker system prune # les quatre à la fois
docker system prune -af --volumes # TOUT, sans confirmation
| Option | Effet |
|---|---|
-a | Étend aux images inutilisées, pas seulement aux images sans tag |
-f | Sans demander confirmation |
--volumes | Inclut les volumes orphelins — donc les données |
docker system prune -af --volumes supprime tous les conteneurs arrêtés, tous les
réseaux inutilisés, toutes les images non utilisées par un conteneur actif, le cache de
construction et les volumes orphelins. Sur un poste de développement, c'est commode. Sur un serveur, c'est une
commande destructrice : les volumes contiennent les données. Pour conserver des images, on les
garde taguées et rattachées à un conteneur, ou on les pousse sur un registre avant de nettoyer.
À retenir
docker pull image:tag— toujours préciser le tag,latestn'est pas figé- Images officielles et variantes alpine : moins de surface d'attaque
save/loadpour transférer une image sans registre-ddétaché,-p hôte:conteneur,-vvolume,-evariablestop= SIGTERM (propre) |kill= SIGKILL (brutal)rmexige un conteneur arrêté- Sans
-p, le conteneur n'est pas joignable depuis l'extérieur - Deux conteneurs ne peuvent pas publier sur le même port hôte
- Les logs meurent avec le conteneur → rediriger ou monter un volume
- Système de fichiers éphémère → volume pour persister
- Réseau utilisateur → DNS interne, les conteneurs se joignent par leur nom
- Réseaux différents → aucune communication
system prune -af --volumessupprime aussi les données