← Réseaux

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èrePourquoi
Image officielle ou éditeur vérifiéUne image quelconque de Docker Hub peut contenir n'importe quoi
Variante alpine ou slimBeaucoup plus légère, donc moins de surface d'attaque
Date de mise à jour récenteUne image abandonnée embarque des vulnérabilités non corrigées
Tag expliciteReproductibilité

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
OptionEffet
-dDétaché : lance en arrière-plan et rend la main
--name webNomme le conteneur ; sinon Docker génère un nom aléatoire
-p 8080:80Publie le port 80 du conteneur sur le port 8080 de l'hôte
-itInteractif avec pseudo-terminal, pour un shell
--rmSupprime automatiquement le conteneur à son arrêt
-e VAR=valeurDéfinit une variable d'environnement
-v source:cibleMonte un volume
--network mon-reseauAttache le conteneur à un réseau
--restart unless-stoppedRedé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 stopdocker kill
SignalSIGTERM, puis SIGKILL après 10 sSIGKILL immédiat
Le processus peutFermer ses fichiers, vider ses tamponsRien, il est tué net
RisqueAucunCorruption 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 mountVolume nommé
EmplacementUn chemin précis de l'hôteGéré par Docker dans /var/lib/docker/volumes
UsageDéveloppement : on édite les fichiers directementProduction : données applicatives
PortabilitéDépend de l'arborescence de l'hôteIndépendant
SauvegardeAvec les fichiers de l'hôteVia 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.

TypeComportement
bridge (défaut)Réseau virtuel isolé ; sans réseau utilisateur, pas de résolution par nom
hostLe conteneur partage la pile réseau de l'hôte, sans isolation
noneAucun réseau
réseau utilisateurCréé 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
OptionEffet
-aÉtend aux images inutilisées, pas seulement aux images sans tag
-fSans demander confirmation
--volumesInclut 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