Conteneurs: Notions de base (Usage)

Cycle de vie, volumes, réseaux, ressources, bonnes pratiques

Université de Toulon

LIS UMR CNRS 7020

2026-01-28

Environnement et reproductibilite

Jupyter Kernel: bash

🖥️ Env Ubuntu 24.04.3 LTS / x86_64 • 🐳 Docker Client 29.1.5 / Server 29.1.5 • 🌿 Git Branch @ 7b914bd

Ce support a été généré par Quarto : les cellules sont exécutées par le noyau indiqué lors du rendu.

Certaines parties ont été rédigées avec l’assistance d’un modèle de langage ; le contenu a été relu et validé par l’auteur.

Objectifs du cours

À l’issue de ce cours, vous devez être capables de :

  • Manipuler des conteneurs Docker (run, stop, start, rm)
  • Utiliser les volumes pour la persistance
  • Connecter des conteneurs via des réseaux
  • Exposer des ports vers l’hôte
  • Gérer les ressources d’un conteneur (CPU / RAM / PIDs)
  • Comprendre et appliquer les bonnes pratiques d’usage

Rappel rapide

Un conteneur est une instance d’une image. L’image est un artefact immuable (voir le cours “Image”). Le conteneur est un processus isolé qui tourne sur le noyau de l’hôte.

Astuce

  • Image = template immuable
  • Conteneur = exécution d’un processus isolé

Les images

  • Une image contient tout le nécessaire pour exécuter une application (code, runtime, bibliothèques, dépendances, fichiers de configuration).
  • Chaque couche est en lecture seule, sauf la dernière (couche de conteneur).
  • Les images sont stockées dans des registres (Docker Hub, GitHub Container Registry, etc.).
  • Les images sont identifiées par un nom : [registre/]nom[:tag] (ex: docker.io/library/nginx:1.23).
    • Si le registre n’est pas spécifié, Docker Hub est utilisé par défaut.
    • Si le tag n’est pas spécifié, latest est utilisé par défaut.
    • Une image peut être référencée par son digest (SHA256).
    • Une image peut avoir plusieurs tags.
      • Ex: nginx:1, nginx:1.29,nginx:mainline, nginx:latest, nginx:f3524ef8b874 peuvent référencer la même image.
  • Une image est destinée à une plateforme spécifique (architecture CPU, OS).
    • Ex: linux/amd64, linux/arm64/v8, windows/amd64.
    • Il est possible de créer des images multi-plateformes (multi-arch).

Cycle de vie d’un conteneur

Exécution simple

  • La commande docker run crée et démarre un conteneur à partir d’une image.
  • Le conteneur s’arrête lorsque le processus principal se termine (--rm pour supprimer automatiquement après).
  • Le format général est docker run [OPTIONS] IMAGE [COMMAND] [ARG...].
  • Si l’image n’est pas présente localement, Docker la télécharge depuis le registre.
#| label: lst-run-alpine
#| title: "Premier conteneur Docker"
#| caption: "Exécution d’un conteneur Alpine jetable affichant un message"
#| code-fold: true
#| code-summary: "Afficher la commande Docker"
#| collapse: true
docker run --rm alpine:3.18 echo "Hello"
Unable to find image 'alpine:3.18' locally
3.18: Pulling from library/alpine

44cf07d57ee4: Pulling fs layer 
431d356fe850: Download complete 
54d130656ede: Downloading  75.85kB/75.85kB54d130656ede: Download complete 44cf07d57ee4: Download complete 44cf07d57ee4: Pull complete Digest: sha256:de0eb0b3f2a47ba1eb89389859a9bd88b28e82f5826b6969ad604979713c2d4f
Status: Downloaded newer image for alpine:3.18
Hello

Conteneur en arrière-plan (--detach, -d)

  • La commande docker run -d démarre un conteneur en arrière-plan (détaché --detach).
#| label: lst-run-nginx
#| title: "Conteneur Nginx en arrière-plan"
#| caption: "Démarrage d’un conteneur Nginx en arrière-plan"
docker run -d --name my-nginx nginx:1.23
Unable to find image 'nginx:1.23' locally
1.23: Pulling from library/nginx

9989f7b33228: Pulling fs layer 
d24b987aa74e: Pulling fs layer 
a85095acb896: Pulling fs layer 
f03b40093957: Pulling fs layer 
0972072e0e8a: Pulling fs layer 
6c1a86118ade: Pulling fs layer 9989f7b33228: Download complete d24b987aa74e: Download complete a85095acb896: Download complete 6c1a86118ade: Download complete 0972072e0e8a: Downloading  1.049MB/25.58MBf03b40093957: Downloading  2.097MB/31.4MB0972072e0e8a: Downloading  5.243MB/25.58MBf03b40093957: Downloading  3.146MB/31.4MB0972072e0e8a: Downloading   7.34MB/25.58MBf03b40093957: Downloading  5.243MB/31.4MB0972072e0e8a: Downloading  12.58MB/25.58MBf03b40093957: Downloading  10.49MB/31.4MB0972072e0e8a: Downloading  20.97MB/25.58MBf03b40093957: Downloading   14.6MB/31.4MB0972072e0e8a: Downloading  25.58MB/25.58MBf03b40093957: Downloading  15.73MB/31.4MB0972072e0e8a: Download complete f03b40093957: Downloading  17.83MB/31.4MBf03b40093957: Downloading  24.12MB/31.4MBf03b40093957: Downloading   31.4MB/31.4MBf03b40093957: Download complete f03b40093957: Extracting 1 sf03b40093957: Extracting 1 sf03b40093957: Extracting 1 sf03b40093957: Extracting 1 sf03b40093957: Extracting 1 sf03b40093957: Extracting 1 s0972072e0e8a: Extracting 1 sf03b40093957: Pull complete 0972072e0e8a: Extracting 1 s0972072e0e8a: Extracting 1 s0972072e0e8a: Extracting 1 s0972072e0e8a: Extracting 1 s0972072e0e8a: Extracting 1 s0972072e0e8a: Extracting 1 sa85095acb896: Pull complete 0972072e0e8a: Pull complete d24b987aa74e: Pull complete 9989f7b33228: Extracting 1 s6c1a86118ade: Pull complete 9989f7b33228: Pull complete Digest: sha256:f5747a42e3adcb3168049d63278d7251d91185bb5111d2563d58729a5c9179b0
Status: Downloaded newer image for nginx:1.23
610c598659a1ad37a6820142756a7343515bac919a2e595acccc62df776deeb1

Liste des conteneurs (container ls, ps)

  • La commande docker ps (docker container ls) liste les conteneurs en cours d’exécution.
  • L’option -a liste tous les conteneurs (y compris arrêtés).
  • Chaque conteneur a un ID unique, un nom, un statut, des ports exposés, etc.
#| label: lst-docker-ps
#| title: "Liste des conteneurs en cours d’exécution"
#| caption: "Affichage des conteneurs Docker en cours d’exécution"
docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED        STATUS                  PORTS     NAMES
610c598659a1   nginx:1.23   "/docker-entrypoint.…"   1 second ago   Up Less than a second   80/tcp    my-nginx

Arrêter (stop) / démarrer (start) / supprimer (rm)

  • Le cycle de vie d’un conteneur inclut les états : démarré, arrêté, supprimé.
  • Lorsqu’un conteneur est arrêté, il reste sur le système jusqu’à sa suppression (rm).
#| label: lst-stop-nginx
docker stop my-nginx
my-nginx
#| label: lst-docker-ps-all
docker ps -a
CONTAINER ID   IMAGE        COMMAND                  CREATED         STATUS                              PORTS     NAMES
610c598659a1   nginx:1.23   "/docker-entrypoint.…"   2 seconds ago   Exited (0) Less than a second ago             my-nginx
#| label: lst-start-nginx
docker start my-nginx
my-nginx
#| label: lst-rm-nginx
docker stop my-nginx
my-nginx
#| label: lst-rm-nginx
docker rm my-nginx
my-nginx

Exercice 1

Lancer un conteneur alpine, exécuter uname -a, puis le supprimer.

#| label: lst-run-alpine-uname
docker run --name my-alpine alpine:3.18 uname -a
docker rm my-alpine
Linux 3ced0c9cb525 6.18.6-200.fc43.x86_64 #1 SMP PREEMPT_DYNAMIC Sun Jan 18 18:57:00 UTC 2026 x86_64 Linux
my-alpine
  • L’option --rm peut être utilisée avec docker run pour supprimer automatiquement le conteneur après son arrêt.

Logs, exec et monitoring

  • Les logs d’un conteneur sont accessibles via docker logs.
  • L’option -f permet de suivre les logs en temps réel.
#| label: lst-run-nginx-logs
docker run --name my-nginx -d nginx:1.23
83b1c39ca6a2f17c1b3e80e1df11883a4136cf9da9c9c52ac408797dd95a46db
#| label: lst-docker-logs
docker logs my-nginx
# docker logs -f my-nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2026/01/28 12:49:56 [notice] 1#1: using the "epoll" event method
2026/01/28 12:49:56 [notice] 1#1: nginx/1.23.4
2026/01/28 12:49:56 [notice] 1#1: built by gcc 10.2.1 20210110 (Debian 10.2.1-6) 
2026/01/28 12:49:56 [notice] 1#1: OS: Linux 6.18.6-200.fc43.x86_64
2026/01/28 12:49:56 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 524288:524288
2026/01/28 12:49:56 [notice] 1#1: start worker processes
2026/01/28 12:49:56 [notice] 1#1: start worker process 29
2026/01/28 12:49:56 [notice] 1#1: start worker process 30
2026/01/28 12:49:56 [notice] 1#1: start worker process 31
2026/01/28 12:49:56 [notice] 1#1: start worker process 32
2026/01/28 12:49:56 [notice] 1#1: start worker process 33
2026/01/28 12:49:56 [notice] 1#1: start worker process 34
2026/01/28 12:49:56 [notice] 1#1: start worker process 35
2026/01/28 12:49:56 [notice] 1#1: start worker process 36
2026/01/28 12:49:56 [notice] 1#1: start worker process 37
2026/01/28 12:49:56 [notice] 1#1: start worker process 38
2026/01/28 12:49:56 [notice] 1#1: start worker process 39
2026/01/28 12:49:56 [notice] 1#1: start worker process 40
2026/01/28 12:49:56 [notice] 1#1: start worker process 41
2026/01/28 12:49:56 [notice] 1#1: start worker process 42
2026/01/28 12:49:56 [notice] 1#1: start worker process 43
2026/01/28 12:49:56 [notice] 1#1: start worker process 44
2026/01/28 12:49:56 [notice] 1#1: start worker process 45
2026/01/28 12:49:56 [notice] 1#1: start worker process 46
2026/01/28 12:49:56 [notice] 1#1: start worker process 47
2026/01/28 12:49:56 [notice] 1#1: start worker process 48
2026/01/28 12:49:56 [notice] 1#1: start worker process 49
2026/01/28 12:49:56 [notice] 1#1: start worker process 50

Exécuter une commande dans un conteneur en cours

  • La commande docker exec permet d’exécuter des commandes dans un conteneur en cours d’exécution.
  • Lance un nouveau processus dans le conteneur
    • docker exec container <cmd> → non interactif
    • docker exec -it container sh→ interactif (ou un autre shell ou programme interactif)
#| label: lst-run-nginx-exec
docker exec my-nginx ls /usr/share/nginx/html
50x.html
index.html
#| label: lst-run-nginx-exec-interactive
docker stop my-nginx
docker rm my-nginx
my-nginx
my-nginx

Monitoring

  • La commande docker stats affiche l’utilisation des ressources (CPU, mémoire, réseau, disques) des conteneurs en cours d’exécution.
  • L’option --no-stream affiche une seule fois les statistiques.
#| label: lst-docker-stats
docker stats --no-stream

Réseau

  • Chaque conteneur a une interface réseau virtuelle et une adresse IP.
  • Par défaut, les conteneurs sont connectés à un réseau bridge par défaut.
  • Il est possible de créer des réseaux custom pour isoler les conteneurs.
  • Les conteneurs sur le même réseau custom peuvent communiquer entre eux par nom (DNS interne).

Réseau par défaut (bridge)

  • Par défaut, Docker crée un réseau bridge nommé bridge.
#| label: lst-docker-network-ls
docker run -d --name c1 alpine sleep 3600
docker run -d --name c2 alpine sleep 3600
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine

589002ba0eae: Pulling fs layer 
9e595aac14e0: Download complete 
caa817ad3aea: Download complete 589002ba0eae: Downloading  1.049MB/3.862MB589002ba0eae: Download complete 589002ba0eae: Extracting 1 s589002ba0eae: Pull complete Digest: sha256:25109184c71bdad752c8312a8623239686a9a2071e8825f20acb8f2198c3f659
Status: Downloaded newer image for alpine:latest
1ae555f505d1f10c5fc6141d8c95ea71155e57317d8e1a29dacc9449971e7f24
0d5b50e3d37bacd0cbf052423bf66946095ebbf61c23937911c354adc90b0660
  • Les conteneurs ont une adresse IP dans le réseau bridge par défaut.
    • La commande docker inspect permet de voir les détails d’un conteneur et permet de définir un format personnalisé (ici l’adresse IP).
#| label: lst-docker-inspect-ip
docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' c1 c2
/c1 - 172.17.0.2
/c2 - 172.17.0.3

❌ Sur le réseau bridge par défaut :

  • les conteneurs n’ont pas de DNS interne
  • ils ne peuvent pas se résoudre par nom
#| label: lst-docker-ping-fail
docker exec c1 ping -c 1 c2
ping: bad address 'c2'
: 1

Réseau custom (bonne pratique)

  • Créer un réseau custom avec docker network create.
  • Lancer des conteneurs (un serveur web, une base de données) sur ce réseau avec --network.
#| label: lst-docker-network-create
docker network create app-net

docker run --detach --name web \
  --network app-net \
  nginx:1.23

docker run --detach --name db  \
  --network app-net \
  redis:7.0.9
b67ad3385b3f5de4fbc31acc8b9c62ccdbfcba18badec86dca1aa08ee7b5e226
fb8934b0eb36c344a7e94e255d965ef6deb9e592399c13629d68950df7cd09d7
Unable to find image 'redis:7.0.9' locally
7.0.9: Pulling from library/redis

b483de716a47: Pulling fs layer 
65e8ba9473fe: Pulling fs layer 
585124038cab: Pulling fs layer 
89515d93a23e: Pulling fs layer 
3f9582a2cbe7: Pulling fs layer 
241c2d338588: Pulling fs layer b483de716a47: Download complete 585124038cab: Download complete 241c2d338588: Download complete 89515d93a23e: Download complete 3f9582a2cbe7: Downloading  1.049MB/31.41MB65e8ba9473fe: Downloading  1.049MB/9.579MB65e8ba9473fe: Downloading  6.291MB/9.579MB3f9582a2cbe7: Downloading  5.243MB/31.41MB65e8ba9473fe: Downloading  8.389MB/9.579MB3f9582a2cbe7: Downloading   7.34MB/31.41MB3f9582a2cbe7: Downloading  14.68MB/31.41MB65e8ba9473fe: Download complete 3f9582a2cbe7: Downloading  19.92MB/31.41MB3f9582a2cbe7: Downloading  26.21MB/31.41MB3f9582a2cbe7: Downloading  29.36MB/31.41MB3f9582a2cbe7: Download complete 3f9582a2cbe7: Extracting 1 s3f9582a2cbe7: Extracting 1 s3f9582a2cbe7: Extracting 1 s3f9582a2cbe7: Extracting 1 s3f9582a2cbe7: Extracting 1 s3f9582a2cbe7: Pull complete 241c2d338588: Extracting 1 s241c2d338588: Extracting 1 s241c2d338588: Pull complete 89515d93a23e: Extracting 1 s89515d93a23e: Extracting 1 s89515d93a23e: Extracting 1 s89515d93a23e: Pull complete 65e8ba9473fe: Extracting 1 s65e8ba9473fe: Extracting 1 s65e8ba9473fe: Extracting 1 s65e8ba9473fe: Extracting 1 s65e8ba9473fe: Pull complete b483de716a47: Extracting 1 s585124038cab: Pull complete b483de716a47: Pull complete Digest: sha256:e50c7e23f79ae81351beacb20e004720d4bed657415e68c2b1a2b5557c075ce0
Status: Downloaded newer image for redis:7.0.9
db4481cc826754681ec5aea920a0cfa61212d6e3e7d59773d40b6721fa22f610

Vérifier le réseau (Avancé)

#| label: lst-docker-network-inspect
docker network inspect app-net
[
    {
        "Name": "app-net",
        "Id": "b67ad3385b3f5de4fbc31acc8b9c62ccdbfcba18badec86dca1aa08ee7b5e226",
        "Created": "2026-01-28T12:50:26.163420723Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv4": true,
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "IPRange": "",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Options": {},
        "Labels": {},
        "Containers": {
            "db4481cc826754681ec5aea920a0cfa61212d6e3e7d59773d40b6721fa22f610": {
                "Name": "db",
                "EndpointID": "eca47d494a9e573e800e376b0f27a431b93df9fb677fc74c2ff47ae2c68b444f",
                "MacAddress": "9a:8f:59:5f:e4:90",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "fb8934b0eb36c344a7e94e255d965ef6deb9e592399c13629d68950df7cd09d7": {
                "Name": "web",
                "EndpointID": "8d33e4b5810fe7117e0330743f1b96aa376825a1010cf57e2a4de8121a9334e9",
                "MacAddress": "62:26:97:d5:2d:7e",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Status": {
            "IPAM": {
                "Subnets": {
                    "172.18.0.0/16": {
                        "IPsInUse": 5,
                        "DynamicIPsAvailable": 65531
                    }
                }
            }
        }
    }
]

Communication conteneur → conteneur

#| label: lst-docker-ping-success
docker run --rm --network app-net curlimages/curl:7.88.1 http://web
Unable to find image 'curlimages/curl:7.88.1' locally
7.88.1: Pulling from curlimages/curl

d4c655b444ee: Pulling fs layer 
b0ca1de0cc3e: Pulling fs layer 
659101a913e8: Pulling fs layer 
ea634e3b33ec: Pulling fs layer 
8d68097e7e08: Pulling fs layer 
473ceed980f8: Pulling fs layer 
213ec9aee27d: Pulling fs layer 
55bfd993f83a: Pulling fs layer 
4c26da78c210: Pulling fs layer 
df0b84b7230e: Pulling fs layer 
45477c99a790: Pulling fs layer 
142e60c0dead: Downloading  1.178kB/1.178kBd4c655b444ee: Downloading     291B/291B142e60c0dead: Download complete b0ca1de0cc3e: Download complete d4c655b444ee: Download complete 659101a913e8: Download complete 8d68097e7e08: Download complete ea634e3b33ec: Downloading  4.396MB/4.396MB473ceed980f8: Download complete 45477c99a790: Download complete 55bfd993f83a: Download complete ea634e3b33ec: Download complete 4c26da78c210: Download complete 213ec9aee27d: Downloading  2.097MB/2.806MBdf0b84b7230e: Download complete 213ec9aee27d: Download complete 213ec9aee27d: Extracting 1 sea634e3b33ec: Extracting 1 s213ec9aee27d: Pull complete ea634e3b33ec: Extracting 1 sea634e3b33ec: Extracting 1 s55bfd993f83a: Extracting 1 sea634e3b33ec: Pull complete 55bfd993f83a: Pull complete df0b84b7230e: Extracting 1 s8d68097e7e08: Extracting 1 sdf0b84b7230e: Pull complete 8d68097e7e08: Pull complete 4c26da78c210: Extracting 1 s659101a913e8: Extracting 1 s4c26da78c210: Pull complete 659101a913e8: Pull complete 473ceed980f8: Extracting 1 sb0ca1de0cc3e: Extracting 1 s473ceed980f8: Pull complete b0ca1de0cc3e: Pull complete 45477c99a790: Extracting 1 sd4c655b444ee: Extracting 1 s45477c99a790: Pull complete d4c655b444ee: Pull complete Digest: sha256:48318407b8d98e8c7d5bd4741c88e8e1a5442de660b47f63ba656e5c910bc3da
Status: Downloaded newer image for curlimages/curl:7.88.1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
100   615  100   615    0     0   724k      0 --:--:-- --:--:-- --:--:--  600k

Exercice 2 (Max 10 min)

Créer un réseau mynet, lancer deux conteneurs alpine nommés a1 et a2 sur ce réseau, puis vérifier qu’ils se ping par nom en exécutant une commande dans un conteneur en mode non-interactif.

Port mapping

  • Chaque conteneur a son propre espace réseau isolé.
  • Ils peuvent donc utiliser les mêmes ports en interne sans conflit.
    • Ex: plusieurs conteneurs postgres peuvent écouter sur leur port 5432.
  • Pour exposer un service d’un conteneur vers l’hôte, utiliser --publish hôte:conteneur.
  • Cela mappe un port de l’hôte vers un port du conteneur.
    • Ex: --publish 8080:80 mappe le port 8080 de l’hôte vers le port 80 du conteneur.
    • Attention aux conflits de ports sur l’hôte.
    • Attention si docker tourne dans une VM (WSL, Docker Desktop) : le port est exposé sur la VM, pas directement sur l’hôte.
    • Le port mapping est une règle de NAT entre l’hôte et le réseau bridge Docker.
#| label: lst-docker-port-mapping
docker run --detach --name web-port-1 --publish 8080:80 nginx:1.28

docker run --detach --name web-port-2 --publish 8081:80 nginx:1.23
Unable to find image 'nginx:1.28' locally
1.28: Pulling from library/nginx

ae9b786964d0: Pulling fs layer 
998d5e4721ac: Pulling fs layer 
8d96ce5090ec: Pulling fs layer 
119d43eec815: Pulling fs layer 
a5163318194d: Pulling fs layer 
6697c8ec7c25: Pulling fs layer 
7621fff433f2: Pulling fs layer 
212c51a5503f: Downloading  1.049MB/2.816MB
3c43a66c8ef2: Download complete 212c51a5503f: Download complete 7621fff433f2: Download complete a5163318194d: Download complete 6697c8ec7c25: Download complete 998d5e4721ac: Downloading  1.049MB/33.04MBae9b786964d0: Download complete 998d5e4721ac: Downloading  5.243MB/33.04MB8d96ce5090ec: Download complete 998d5e4721ac: Downloading  11.53MB/33.04MB998d5e4721ac: Downloading  19.92MB/33.04MB998d5e4721ac: Downloading  26.21MB/33.04MB998d5e4721ac: Downloading  29.36MB/33.04MB998d5e4721ac: Download complete 119d43eec815: Downloading  1.049MB/29.77MB119d43eec815: Downloading  6.291MB/29.77MB119d43eec815: Downloading  13.63MB/29.77MB119d43eec815: Downloading  18.87MB/29.77MB119d43eec815: Downloading  29.77MB/29.77MB119d43eec815: Download complete 119d43eec815: Extracting 1 s119d43eec815: Extracting 1 s119d43eec815: Extracting 1 s119d43eec815: Extracting 1 s998d5e4721ac: Extracting 1 s119d43eec815: Pull complete 998d5e4721ac: Extracting 1 s998d5e4721ac: Extracting 1 s998d5e4721ac: Extracting 1 s998d5e4721ac: Extracting 1 s998d5e4721ac: Extracting 1 s998d5e4721ac: Extracting 1 s998d5e4721ac: Extracting 1 s998d5e4721ac: Extracting 1 s998d5e4721ac: Pull complete 8d96ce5090ec: Pull complete 7621fff433f2: Pull complete a5163318194d: Extracting 1 sa5163318194d: Pull complete 6697c8ec7c25: Extracting 1 s6697c8ec7c25: Pull complete ae9b786964d0: Extracting 1 sae9b786964d0: Pull complete Digest: sha256:0a1f2fb3231e1c0c1360ba383a2d02728b5912bb13eb87406839e2002e472fae
Status: Downloaded newer image for nginx:1.28
1037efc59cc7dddcfad818252834f07ae277810abdb73a648ad3e6a7859ce154
f3ff63a26dea8ab670593b16af5502f49a9fc3ee8e514c27166839e9b9c95f33

Tester depuis l’hôte

  • Il est possible de tester l’accès au service exposé depuis l’hôte avec curl ou un navigateur.
  • Avec l’adresse http://localhost:8080 si Docker est natif.
  • Avec l’adresse IP de la VM si Docker tourne dans une VM (ex: WSL, Docker Desktop).
  • A moins que Docker soit configuré pour exposer les ports vers l’hôte directement.
curl --max-time 30 -I http://localhost:8080

curl --max-time 30 -I http://localhost:8081
#| label: lst-docker-port-mapping-curl
curl --max-time 30 -I http://dind:8080

curl --max-time 30 -I http://dind:8081
HTTP/1.1 200 OK


Server: nginx/1.28.1


Date: Wed, 28 Jan 2026 12:50:48 GMT


Content-Type: text/html


Content-Length: 615


Last-Modified: Tue, 23 Dec 2025 18:40:33 GMT


Connection: keep-alive


ETag: "694ae221-267"


Accept-Ranges: bytes





HTTP/1.1 200 OK


Server: nginx/1.23.4


Date: Wed, 28 Jan 2026 12:50:48 GMT


Content-Type: text/html


Content-Length: 615


Last-Modified: Tue, 28 Mar 2023 15:01:54 GMT


Connection: keep-alive


ETag: "64230162-267"


Accept-Ranges: bytes




Accès conteneur -> hôte

  • Il est possible d’accéder à un service exposé sur l’hôte depuis un conteneur.
  • Utiliser host.docker.internal comme nom d’hôte.
  • ATTENTION : host.docker.internal fonctionne nativement sur Docker Desktop (Windows/Mac) et Docker sous Linux (depuis Docker 20.10) mais n’est standardisé que sur Docker Desktop.
docker run --rm \
    curlimages/curl:7.88.1 http://host.docker.internal:8080

Volumes : persistance

  • Les données dans un conteneur sont éphémères : elles disparaissent à l’arrêt/suppression du conteneur.
  • Pour persister les données, utiliser des volumes.
  • Un volume est un espace de stockage géré par Docker, indépendant du cycle de vie des conteneurs.
  • Les volumes peuvent être montés dans un conteneur avec --volume volume:chemin_dans_conteneur.
  • Il existe deux types de volumes :
    • Bind mount : mappe un répertoire de l’hôte vers un répertoire du conteneur.
    • Volume nommé : volume géré par Docker, stocké dans l’espace de stockage Docker.

Astuce

  • bind mount = couplage fort hôte ↔︎ conteneur
  • volume nommé = abstraction portable

Bind mount (risky, dev)

  • montage avec --volume /chemin/host:/chemin/conteneur
#| output: true
#| echo: true

#| label: lst-bind-mount-nginx
echo "hello" > ${TP_DIR}/www/index.html

docker run --rm -v ${TP_DIR}/www:/usr/share/nginx/html \
  -p 8081:80 nginx:1.23

- Utile en développement pour monter du code source.
- Permet d’éditer les fichiers sur l’hôte et de les voir dans le conteneur.
- Dangers :
  - les permissions peuvent poser problème selon l’OS hôte
  - les performances peuvent être dégradées (ex: Docker Desktop sur Windows/Mac)
  - le conteneur ne peut pas être déplacé facilement (dépendance à l’hôte)

Volume nommé (better, prod)

  • montage avec --volume nom_volume:chemin/conteneur
#| label: lst-named-volume-postgres
IMAGE="postgres:15.2"
VOLUME="pgdata"
PW="secret"

docker volume create "$VOLUME"

# Initialisation de la base et création d'une table
docker run -d --name db \
  -v "$VOLUME":/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD="$PW" \
  "$IMAGE"

# Attendre que la base soit prête
timeout 60 sh -c 'until docker exec db pg_isready -U postgres >/dev/null 2>&1; do echo -n '.'; sleep 1; done' || (echo "Postgres not ready after 60s" >&2; exit 1)

# Créer une table et insérer des données depuis le conteneur de la base
docker exec db psql -U postgres -c "CREATE TABLE test (id SERIAL PRIMARY KEY, name VARCHAR(50));"
docker exec db psql -U postgres -c "INSERT INTO test (name) VALUES ('Alice'), ('Bob');"

# Arrêter et supprimer le conteneur mais conserver le volume
docker stop db && docker rm db
pgdata
99085d8ce20b237fd98be7cd6c85c1124f7811da60449372e145b81c2fbbac84
.......
CREATE TABLE
INSERT 0 2
db
db
#| label: lst-verify-named-volume
# Redémarrer un nouveau conteneur avec le même volume
docker run -d --name db2 \
  -v "$VOLUME":/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD="$PW" \
  "$IMAGE"

# Attendre que la base soit prête
timeout 60 sh -c 'until docker exec db2 pg_isready -U postgres >/dev/null 2>&1; do echo -n '.'; sleep 1; done' || (echo "Postgres not ready after 60s" >&2; exit 1)

# Vérifier que les données persistent
docker exec db2 psql -U postgres -c "SELECT * FROM test;"

# Nettoyage
docker stop db2 && docker rm db2
docker volume rm "$VOLUME"
4464cf359a6bffb9c7191c968508ffb6687d99e7e1c90698ce6d1656ab4a7496
 id | name  
----+-------
  1 | Alice
  2 | Bob
(2 rows)

db2
db2
pgdata

Exercice de persistance

  • lancer MySQL sans volume → perdre les données
  • relancer avec volume → conserver les données

Hint: l’image officielle MySQL stocke les données dans /var/lib/mysql. Voir la page Docker Hub : https://hub.docker.com/_/mysql

Exercice 3 (10 min)

Démarrer MySQL au premier plan, observer l’initialisation (création de la base), arrêter avec Ctrl‑C, puis relancer le même volume et constater qu’il n’y a plus d’initialisation.

Consignes :

  • Lisez la page Docker Hub de MySQL pour comprendre
    • les variables d’environnement essentielles (notamment MYSQL_ROOT_PASSWORD, MYSQL_DATABASE) : https://hub.docker.com/_/mysql
    • le chemmin de stockage des données dans le conteneur (/var/lib/mysql)
  • Créez un volume nommé mysql-data pour stocker les données persistantes.
  • Démarrez MySQL en mode attaché (sans --detach
#| label: lst-mysql-persistence

# create a named volume for MySQL data (one-time)
docker volume create mysql-data

export MYSQL_ROOT_PASSWORD=secretpw
export MYSQL_DATABASE=demo

# Run MySQL in the foreground so you see initialization logs
docker run --name mysql-db --detach\
  --env MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
  --env MYSQL_DATABASE=${MYSQL_DATABASE} \
  --volume mysql-data:/var/lib/mysql \
  mysql:8.0

# Wait for MySQL to be ready
timeout 60 sh -c 'until docker exec mysql-db mysqladmin ping -h "localhost" --silent >/dev/null 2>&1; do echo -n "."; sleep 1; done' || (echo "MySQL not ready after 60s" >&2; exit 1)

# Stop and remove the container to simulate a restart
docker stop mysql-db && docker rm mysql-db

# Start a new container with the same volume to see data persistence.
docker run --name mysql-db --detach\
  --env MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
  --env MYSQL_DATABASE=${MYSQL_DATABASE} \
  --volume mysql-data:/var/lib/mysql \
  mysql:8.0

# Wait for MySQL to be ready again
timeout 60 sh -c 'until docker exec mysql-db mysqladmin ping -h "localhost" --silent >/dev/null 2>&1; do echo -n "."; sleep 1; done' || (echo "MySQL not ready after 60s" >&2; exit 1)

# Check the logs to confirm no re-initialization
docker logs mysql-db|head -n 20
mysql-data
Unable to find image 'mysql:8.0' locally
8.0: Pulling from library/mysql

1c0ceff8a81b: Pulling fs layer 
05ed66656b21: Pulling fs layer 
9e9c9ba70723: Pulling fs layer 
be113d11b355: Pulling fs layer 
16506d4b4233: Pulling fs layer 
3387bdf9bfcc: Pulling fs layer 
5a35458f48a1: Pulling fs layer 
1bed572afc9f: Pulling fs layer 
f3e7871685d1: Pulling fs layer 
54a2bfb30cdf: Pulling fs layer 
05bdba050124: Pulling fs layer 
e032523bbbc9: Downloading  2.097MB/14.96MBe032523bbbc9: Downloading   7.34MB/14.96MB
1ef2ef3fb862: Download complete 1c0ceff8a81b: Download complete e032523bbbc9: Downloading  11.53MB/14.96MB05ed66656b21: Download complete e032523bbbc9: Download complete 3387bdf9bfcc: Downloading     884B/884B9e9c9ba70723: Download complete 3387bdf9bfcc: Download complete 16506d4b4233: Downloading  2.097MB/47.31MBf3e7871685d1: Download complete be113d11b355: Downloading  1.049MB/49.92MBbe113d11b355: Downloading  4.194MB/49.92MB16506d4b4233: Downloading  5.243MB/47.31MB5a35458f48a1: Download complete 05bdba050124: Download complete be113d11b355: Downloading  4.194MB/49.92MB16506d4b4233: Downloading  5.243MB/47.31MB16506d4b4233: Downloading  14.68MB/47.31MB1bed572afc9f: Downloading  3.146MB/6.174MBbe113d11b355: Downloading  12.58MB/49.92MB54a2bfb30cdf: Downloading  1.049MB/128.1MB16506d4b4233: Downloading  14.68MB/47.31MB1bed572afc9f: Downloading  3.146MB/6.174MBbe113d11b355: Downloading  13.63MB/49.92MB54a2bfb30cdf: Downloading  1.049MB/128.1MBbe113d11b355: Downloading  15.73MB/49.92MB54a2bfb30cdf: Downloading  3.146MB/128.1MB16506d4b4233: Downloading  14.68MB/47.31MB1bed572afc9f: Downloading  4.194MB/6.174MBbe113d11b355: Downloading  15.73MB/49.92MB54a2bfb30cdf: Downloading  3.146MB/128.1MB16506d4b4233: Downloading  18.87MB/47.31MB1bed572afc9f: Downloading  6.174MB/6.174MB54a2bfb30cdf: Downloading  5.243MB/128.1MB16506d4b4233: Downloading  18.87MB/47.31MB1bed572afc9f: Download complete be113d11b355: Downloading  15.73MB/49.92MBbe113d11b355: Downloading  25.17MB/49.92MB54a2bfb30cdf: Downloading  6.291MB/128.1MB16506d4b4233: Downloading  27.26MB/47.31MB16506d4b4233: Downloading  27.26MB/47.31MBbe113d11b355: Downloading  26.21MB/49.92MB54a2bfb30cdf: Downloading  6.291MB/128.1MB16506d4b4233: Downloading  29.36MB/47.31MBbe113d11b355: Downloading  26.21MB/49.92MB54a2bfb30cdf: Downloading  6.291MB/128.1MB16506d4b4233: Downloading  32.51MB/47.31MBbe113d11b355: Downloading  32.51MB/49.92MB54a2bfb30cdf: Downloading  10.49MB/128.1MB16506d4b4233: Downloading  40.89MB/47.31MBbe113d11b355: Downloading   38.8MB/49.92MB54a2bfb30cdf: Downloading  14.68MB/128.1MBbe113d11b355: Downloading   38.8MB/49.92MB54a2bfb30cdf: Downloading  14.68MB/128.1MB16506d4b4233: Downloading  41.94MB/47.31MBbe113d11b355: Downloading  44.04MB/49.92MB54a2bfb30cdf: Downloading  17.83MB/128.1MB16506d4b4233: Download complete 16506d4b4233: Extracting 1 sbe113d11b355: Downloading  48.23MB/49.92MB54a2bfb30cdf: Downloading  19.92MB/128.1MB16506d4b4233: Extracting 1 sbe113d11b355: Download complete 54a2bfb30cdf: Downloading  23.07MB/128.1MB16506d4b4233: Extracting 1 s54a2bfb30cdf: Downloading  25.17MB/128.1MB16506d4b4233: Extracting 1 s54a2bfb30cdf: Downloading  28.31MB/128.1MB16506d4b4233: Extracting 1 s54a2bfb30cdf: Downloading  32.51MB/128.1MB16506d4b4233: Extracting 1 s54a2bfb30cdf: Downloading   36.7MB/128.1MB54a2bfb30cdf: Downloading  41.94MB/128.1MB3387bdf9bfcc: Extracting 1 s16506d4b4233: Pull complete 54a2bfb30cdf: Downloading  48.23MB/128.1MB54a2bfb30cdf: Downloading  53.48MB/128.1MB3387bdf9bfcc: Pull complete 54a2bfb30cdf: Downloading  57.67MB/128.1MB5a35458f48a1: Pull complete 1bed572afc9f: Extracting 1 s54a2bfb30cdf: Downloading  63.96MB/128.1MB1bed572afc9f: Extracting 1 s54a2bfb30cdf: Downloading  68.16MB/128.1MB1bed572afc9f: Extracting 1 s54a2bfb30cdf: Downloading  74.45MB/128.1MBf3e7871685d1: Extracting 1 s1bed572afc9f: Pull complete 54a2bfb30cdf: Downloading  81.79MB/128.1MBf3e7871685d1: Pull complete 54a2bfb30cdf: Downloading  89.13MB/128.1MB9e9c9ba70723: Pull complete be113d11b355: Extracting 1 s54a2bfb30cdf: Downloading  94.37MB/128.1MBbe113d11b355: Extracting 1 s54a2bfb30cdf: Downloading  102.8MB/128.1MBbe113d11b355: Extracting 1 s54a2bfb30cdf: Downloading    108MB/128.1MBbe113d11b355: Extracting 1 s54a2bfb30cdf: Downloading  112.2MB/128.1MBbe113d11b355: Extracting 1 s54a2bfb30cdf: Downloading  116.4MB/128.1MBbe113d11b355: Extracting 1 s54a2bfb30cdf: Downloading  120.6MB/128.1MBbe113d11b355: Extracting 1 s54a2bfb30cdf: Downloading  124.8MB/128.1MBbe113d11b355: Extracting 1 s54a2bfb30cdf: Download complete be113d11b355: Pull complete 05bdba050124: Pull complete 54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 1 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 2 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 3 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 4 s54a2bfb30cdf: Extracting 5 s54a2bfb30cdf: Extracting 5 s05ed66656b21: Extracting 1 s54a2bfb30cdf: Pull complete 1c0ceff8a81b: Extracting 1 s05ed66656b21: Pull complete 1c0ceff8a81b: Pull complete Digest: sha256:7a9d63525e8072408862dd62226440db869e745e37f36968b26e3ef03d6e9641
Status: Downloaded newer image for mysql:8.0
f8c9cb9adf8ee7c47035c59318308058e68300f1f48fcf4c95f032df284b287d
...........
mysql-db
mysql-db
6f5352ac9cb753385a75bb98ec580b769682d542879a09dd16ef8d98122f3bf8
..
2026-01-28 12:51:47+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.45-1.el9 started.
2026-01-28 12:51:48+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2026-01-28 12:51:48+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.45-1.el9 started.
'/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock'
2026-01-28T12:51:48.383007Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead.
2026-01-28T12:51:48.384049Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.45) starting as process 1
2026-01-28T12:51:48.387583Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started.
2026-01-28T12:51:48.968824Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended.
2026-01-28T12:51:49.117383Z 0 [System] [MY-010229] [Server] Starting XA crash recovery...
2026-01-28T12:51:49.125485Z 0 [System] [MY-010232] [Server] XA crash recovery finished.
2026-01-28T12:51:49.265791Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
2026-01-28T12:51:49.265811Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel.
2026-01-28T12:51:49.273139Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory.
2026-01-28T12:51:49.303276Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.45'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.
2026-01-28T12:51:49.303331Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock

Gestion des ressources (Avancé)

  • Docker permet de limiter les ressources utilisées par un conteneur.
  • Cela inclut la mémoire, le CPU, et le nombre de PIDs.

Limiter CPU / mémoire / PIDs

#| label: lst-limit-cpu-mem

docker run --detach --name cpu-test \
  --memory="512m" \
  --cpus="0.5" \
  python:3.11-slim \
  python -c "while True: pass"
Unable to find image 'python:3.11-slim' locally
3.11-slim: Pulling from library/python

3e731abb5c1d: Pulling fs layer 
0b2bf04f68e9: Pulling fs layer 
5b09819094bb: Pulling fs layer 
6a59d23a42b3: Download complete 
5d468228012d: Download complete 0b2bf04f68e9: Download complete 3e731abb5c1d: Downloading  1.049MB/14.36MB3e731abb5c1d: Downloading   7.34MB/14.36MB3e731abb5c1d: Downloading  13.63MB/14.36MB3e731abb5c1d: Download complete 5b09819094bb: Downloading  1.049MB/1.293MB5b09819094bb: Download complete 5b09819094bb: Extracting 1 s5b09819094bb: Extracting 1 s5b09819094bb: Pull complete 3e731abb5c1d: Extracting 1 s3e731abb5c1d: Extracting 1 s3e731abb5c1d: Extracting 1 s3e731abb5c1d: Extracting 1 s3e731abb5c1d: Extracting 1 s3e731abb5c1d: Extracting 1 s0b2bf04f68e9: Extracting 1 s3e731abb5c1d: Pull complete 0b2bf04f68e9: Pull complete Digest: sha256:5be45dbade29bebd6886af6b438fd7e0b4eb7b611f39ba62b430263f82de36d2
Status: Downloaded newer image for python:3.11-slim
1d8aaa888d1a743500c599869c267f5a47cf6a24a62df0e7e3a7a560ab175568
#| label: lst-monitor-cpu-mem

docker stats --no-stream cpu-test
CONTAINER ID   NAME       CPU %     MEM USAGE / LIMIT   MEM %     NET I/O      BLOCK I/O    PIDS
1d8aaa888d1a   cpu-test   50.09%    4.445MiB / 512MiB   0.87%     486B / 84B   0B / 397kB   1

Pensez à arrêter et supprimer le conteneur après le test :

#| label: lst-cleanup-cpu-test

docker stop cpu-test
docker rm cpu-test
cpu-test
cpu-test

Modifier les limites d’un conteneur existant

  • Il est possible de modifier les limites d’un conteneur en cours d’exécution avec docker update.
docker update --memory="1g" --cpus="1" cpu-test

Bonnes pratiques d’usage

  • Nettoyage régulier
docker container prune
docker image prune
docker volume prune
docker network prune
docker system prune --all

# NETTOYAGE COMPLET (ATTENTION : SUPPRIME TOUT)
# Y COMPRIS LES DONNESS DANS DES VOLUMES !
docker system prune --all --volumes --force # RISQUE
  • Éviter latest en production

    • Utiliser des tags de version stables.
  • Ne pas stocker de secrets dans l’environnement

    • Préférer --secret (ou mécanismes externes).
  • Logs sur stdout/stderr

    • Les conteneurs doivent produire des logs vers la sortie standard.

Atelier final

  • Déployer une application simple composée de deux conteneurs :
    • une application Java accédant à une base de données via JDBC
    • une base de données PostgreSQL
  • Contraintes :
    • chaque composant doit être dans son propre conteneur
    • les deux conteneurs doivent communiquer via un réseau Docker personnalisé
    • les données de la base doivent être persistées dans un volume Docker
    • l’application Java doit se connecter à la base par le nom du conteneur, pas par localhost
  • Objectif :
    • vérifier la communication entre conteneurs, l’usage des réseaux et la persistance des données.

Conclusion

A Retenir

  • Un conteneur est une instance d’une image, exécutant un processus isolé.

  • Le cycle de vie d’un conteneur inclut les états : démarré, arrêté, supprimé.

  • Les conteneurs peuvent être connectés via des réseaux custom pour la communication.

  • Les volumes permettent de persister les données indépendamment du cycle de vie des conteneurs.

  • Il est possible de limiter les ressources (CPU, mémoire) utilisées par un conteneur.

  • Appliquer les bonnes pratiques d’usage pour une gestion efficace des conteneurs.

  • Gérer les conteneurs manuellement n’est pas viable en production : il faut automatiser

    • Outils d’Orchestration : docker compose, Kubernetes, …