Je vous propose une série de travaux autour de Docker CE (Community Edition), afin de découvrir progressivement et maîtriser cet environnement de gestion de conteneurs, devenu aujourd'hui incontournable. Dans cette première partie, on va :
Prérequis : connaissance de Linux, des réseaux. Il faut également avoir suivi le cours introductif sur les conteneurs et Docker.
Nous allons nous appuyer sur une VM Debian x64 en mode core, version Bookworm (12), installée convenablement selon ce tutoriel détaillé.
On modifie ensuite légèrement la configuration :
Une fois la VM démarrée, loggé en root, on configure le hostname de la machine en docker-xy (xy représentent vos initiales) en modifiant :
nano /etc/hostname
Exemple ici avec mes initiales pm :
docker-pm
nano /etc/hosts
On modifie les références au nom de la machine (ligne 2):
127.0.0.1 localhost
127.0.1.1 docker-pm
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
Puis on redémarre pour la prise en compte :
nano /etc/hostname
nano /etc/hosts
reboot
On continue (toujours avec root) avec une mise à jour de l’index apt et une mise à jour éventuelle des paquets :
apt update && apt upgrade
l'installation de sudo et d'un serveur ssh :
apt -y install sudo openssh-server
Puis on donne des droits sudo à notre utilisateur principal (ici pascal
, à adapter selon votre cas) :
adduser pascal sudo
Enfin, on va repérer (et mémoriser) l’adresse IP de notre serveur :
ip -c a
et se déconnecter:
exit
On peut également utilise CTRL D pour se déconnecter d'une session bash.
On va accéder désormais à notre serveur Debianb en SSH depuis la machine hôte, avec le compte de l'utilisateur sudoer :
Nous allons depuis ce terminal installer Docker Community Edition sur notre serveur.
Cette partie est largement inspirée de la documentation Docker.
Le nom du paquet officiel pour Docker Community Edition est docker-ce. Il n’est pas dans la distribution de base, aussi nous allons devoir ajouter le dépôt Docker à notre système.
Comme il est indiqué dans la documentation officielle, il existe des paquets non officiels pour Docker, comme docker.io ou docker-doc.
Supprimons d'abord les paquets qui pourraient être en conflit (peu probable avec une machine toute neuve) :
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt remove $pkg; done
Installons quelques paquets prérequis (certains seront déjà présents suite à l'installation du serveur ssh notamment) :
sudo apt -y install ca-certificates curl
? sudo apt install apt-transport-https
? sudo apt install software-properties-common
On ajoute la clé publique GPG Docker officielle au trousseau apt :
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
Utilisez la commande suivante (sur une seule ligne) pour ajouter le dépôt stable :
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
La commande
. /etc/os-release && echo "$VERSION_CODENAME"
subsituée ci-dessus retourne le nom de votre distribution Debian, comme "bullseye" ou "bookworm". Sur une distribution dérivée, comme Kali Linux, il faudra directement saisir le nom de la distribution.
Pour voir l’entrée qui a été créée par cette commande :
cat /etc/apt/sources.list.d/docker.list
On relance une mise à jour de l’index apt :
sudo apt update
Le dépôt Docker doit être visible dans la sortie (lignes 3 et 4):
Atteint :1 http://deb.debian.org/debian bookworm InRelease
Atteint :2 http://deb.debian.org/debian bookworm-updates InRelease
Réception de :3 https://download.docker.com/linux/debian bookworm InRelease [43,3 kB]
Réception de :4 https://download.docker.com/linux/debian bookworm/stable amd64 Packages [31,3 kB]
Atteint :5 http://security.debian.org/debian-security bookworm-security InRelease
74,6 ko réceptionnés en 5s (14,2 ko/s)
Lecture des listes de paquets... Fait
Construction de l'arbre des dépendances... Fait
Lecture des informations d'état... Fait
Tous les paquets sont à jour.
On peut maintenant installer la dernière version de Docker CE et ses outils :
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Pour vérifier l’état du service Docker Engine, un classique :
systemctl status docker
Le service Docker est lié via un socket Unix au lieu d'un port TCP. Par défaut, le socket Unix appartient à l'utilisateur root et les autres utilisateurs ne peuvent y accéder qu'en utilisant sudo. Le démon Docker s'exécute toujours en tant qu'utilisateur root.
Si vous ne souhaitez pas faire précéder la commande docker de sudo, il existe un un groupe Unix spécifique appelé docker créé au moment de l'installation. Lorsque le service Docker démarre, il crée un socket Unix accessible aux membres du groupe docker.
Attention : Le groupe docker accorde des privilèges équivalents à l'utilisateur root.
Ajoutez votre utilisateur au groupe Docker (adaptez bien entendu en fonction du nom choisi) :
sudo adduser pascal docker
Il faut déconnecter (CTRL D) et reconnecter l’utilisateur pour que l’appartenance au groupe soit prise en compte.
La plupart des distributions Linux actuelles utilisent systemd pour gérer les services qui démarrent au démarrage du système. Pour activer Docker au démarrage avec systemd :
sudo systemctl enable docker.service
sudo systemctl enable containerd.service
Voir ici : https://docs.docker.com/install/linux/linux-postinstall/
Docker se pilote en mode ligne de commande (CLI) ; notons qu’il existe également des clients GUI.
Le mode CLI est simple, tout commence par le mot-clé docker ; par exemple, pour obtenir la version actuelle de Docker :
docker version
ou, plus succinct :
docker --version
Le lancement d’un conteneur Docker se réalise avec la commande docker run
.
Dans la commande suivante, Docker devrait vous afficher qu’il ne trouve pas l’image du nom de hello-world mais il la télécharge (pull) automatiquement sur le Docker hub :
docker run hello-world
Rappels :
Lorsqu’il est apporté des modifications à une image, seule la différence est prise en compte et placée dans la couche supérieure d'exécution du conteneur. Les modifications peuvent être sauvegardées sous la forme d'une image qui sera juste composée de la couche de différences par le moteur de Docker, définie par un identifiant unique. Ainsi, cette seule version pourra être envoyée vers le dépôt public de Docker (ou vers un dépôt privé), sans avoir à envoyer toutes les couches dans leur intégralité.
Le Docker Hub contient un très grand nombre d’images permettant d’utiliser sous forme de conteneur la plupart des outils utilisées aujourd’hui : apache, php, mysql, mariadb, haproxy, debian, ubuntu, odoo, etc.
Docker Hub comporte des dépôts officiels, mais aussi des images créées par n’importe quel utilisateur.
Il y a d'ailleurs ici un point de vigilance concernant la sécurité : lorsqu’on récupère une image, il faut toujours en vérifier son auteur, des logiciels malveillants pouvant être installés.
Pour interroger le dépôt officiel en ligne de commandes sans passer par le site web, on utilise la commande docker search, par exemple :
docker search ubuntu
La commande renvoie les résultats (limités par défaut à 25) classés par ordre décroissant de popularité.
Il est possible d’affiner cette commande. Comme pour n’importe quelle autre commande, les options sont décrites avec la commande :
docker search --help
On peut aussi de rechercher des images sur le site web https://hub.docker.com/search :
Docker permet d’ajouter un tag à une image, pour choisir une version donnée (par exemple : ubuntu:noble). Par défaut c’est la dernière image (latest) qui est téléchargée :
Téléchargeons par exemple l’image ubuntu (dans sa dernière version, option par défaut) :
docker pull ubuntu
Pour récupérer une autre version de l’image, il faut associer le nom du tag au nom de l’image. Dans l’exemple précédent, pour récupérer la version mantic, il faut utiliser la commande suivante :
docker pull ubuntu:mantic
La liste des images téléchargées localement s’obtient avec la commande :
docker images
Nous retrouvons les différentes images que nous avons récupérées jusque là :
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 59ab366372d5 10 days ago 78.1MB
ubuntu mantic 77081d4f1e72 4 months ago 71.1MB
hello-world latest d2c94e258dcb 17 months ago 13.3kB
Pour supprimer une image locale, on utilise la commande docker rmi <nom image>
.
A noter que :
-f
(ou --force
)docker rmi hello-world
Va générer une erreur :
Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container deeaee1f4209 is using its referenced image d2c94e258dcb
Par contre, cette commande va bien supprimer l'image :
docker rmi hello-world -f
Untagged: hello-world:latest
Untagged: hello-world@sha256:d211f485f2dd1dee407a80973c8f129f00d54604d2c90732e8e320e5038a0348
Deleted: sha256:d2c94e258dcb3c5ac2798d32e1249e42ef01cba4841c2234249495f87264ac5a
On rappelle que l’image est un fichier en lecture seule, contenant lui-même un système de fichiers avec tout le nécessaire pour faire fonctionner la ou les applications. Le conteneur est le processus qui utilise l’image pour faire tourner la ou les applications.
Pour lancer (instancier est le terme exact) un conteneur, on utilise la commande :
docker run [OPTIONS] <nom image> [COMMANDE]
Selon ce que l’on veut faire, il est possible de lancer un conteneur :
[COMMANDE]
est facultative : si l’on ne met rien, l’image a une commande par défaut (prévue par le concepteur de l’image)run
le fait automatiquement (sans requérir un pull
préalable)La commande suivante lance un conteneur (sans options et commandes spécifiques à exécuter dans le conteneur) à partir de l'image ubuntu :
docker run ubuntu
Mais rien ne semble s’être passé !...
La commande docker ps
permet de lister les conteneurs en cours d’exécution :
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
L’option -a
sur la commande docker ps
va nous permettre de visualiser également les conteneurs non actifs :
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e8b1664d923 ubuntu "/bin/bash" 36 seconds ago Exited (0) 34 seconds ago flamboyant_wozniak
deeaee1f4209 d2c94e258dcb "/hello" 33 minutes ago Exited (0) 33 minutes ago confident_mcclintock
/bin/bash
(le shell Bash) ; il s’agit du processus lancé par défaut, prévu par les concepteurs de l'image.--name
.Si on lance de nouveau le conteneur avec la même commande docker run
, ce n’est pas le même conteneur qui est exécuté mais un nouveau conteneur qui est créé :
docker run ubuntu
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
da45bf7c8733 ubuntu "/bin/bash" Less than a second ago Exited (0) Less than a second ago keen_shtern
8e8b1664d923 ubuntu "/bin/bash" 6 minutes ago Exited (0) 6 minutes ago flamboyant_wozniak
deeaee1f4209 d2c94e258dcb "/hello" 38 minutes ago Exited (0) 38 minutes ago confident_mcclintock
Pour relancer un conteneur, Il faudra utiliser plutôt la commande docker start
(mais on indiquera alors le nom du conteneur, et non le nom d’une image).
NB : on voit que la commande par défaut est pour cette image est : /bin/bash
Pour lancer un conteneur en lui faisant exécuter une commande spécifique (par exemple cat /etc/os-release
) :
docker run ubuntu cat /etc/os-release
Ce qui affiche (si la version latest est comme au moment d'écrire ces lignes Noble Numbat) :
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
Avec une autre image (une version spécifique de ubuntu) :
docker run ubuntu:xenial cat /etc/os-release
Dans ce cas, l'image sera préalablement téléchargée :
Unable to find image 'ubuntu:xenial' locally
xenial: Pulling from library/ubuntu
58690f9b18fc: Pull complete
b51569e7c507: Pull complete
da8ef40b9eca: Pull complete
fb15d46c38dc: Pull complete
Digest: sha256:1f1a2d56de1d604801a9671f301190704c25d604a416f59e03c04f5c6ffee0d6
Status: Downloaded newer image for ubuntu:xenial
NAME="Ubuntu"
VERSION="16.04.7 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.7 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
La commande run
a lancé un conteneur à partir de l'image ubuntu et a exécuté dessus la commande shell cat
pour afficher le fichier de version d’Ubuntu.
Le résultat apparaît sur la sortie standard.
Evidemment, à chaque commande run
, un conteneur est ajouté dans la mémoire :
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf9f5c62fd76 ubuntu:xenial "cat /etc/os-release" 2 minutes ago Exited (0) 2 minutes ago laughing_mendel
e1cdda3e617a ubuntu "cat /etc/os-release" 5 minutes ago Exited (0) 5 minutes ago serene_jepsen
da45bf7c8733 ubuntu "/bin/bash" 7 minutes ago Exited (0) 7 minutes ago keen_shtern
8e8b1664d923 ubuntu "/bin/bash" 13 minutes ago Exited (0) 13 minutes ago flamboyant_wozniak
deeaee1f4209 d2c94e258dcb "/hello" 46 minutes ago Exited (0) 46 minutes ago confident_mcclintock
Nous pouvons ainsi nous retrouver très facilement avec de multiples conteneurs totalement inutiles qu’il faut supprimer.
Pour supprimer un conteneur, deux possibilités :
docker rm <id conteneur>
ou
docker rm <nom du conteneur>
Par exemple ici, pour effacer le dernier de la liste ci-dessus :
docker rm confident_mcclintock
Et alors :
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cf9f5c62fd76 ubuntu:xenial "cat /etc/os-release" 5 minutes ago Exited (0) 5 minutes ago laughing_mendel
e1cdda3e617a ubuntu "cat /etc/os-release" 8 minutes ago Exited (0) 8 minutes ago serene_jepsen
da45bf7c8733 ubuntu "/bin/bash" 11 minutes ago Exited (0) 11 minutes ago keen_shtern
8e8b1664d923 ubuntu "/bin/bash" 17 minutes ago Exited (0) 17 minutes ago flamboyant_wozniak
NB : seul un conteneur avec un statut « exited » peut être supprimé.
La commande docker ps
avec l'option -aq
nous donne la liste de tous les identifiants de conteneurs en mémoire :
docker ps -aq
cf9f5c62fd76
e1cdda3e617a
da45bf7c8733
8e8b1664d923
On récupère cette liste dans une variable avec la substitution de commande $(docker ps -aq)
du shell, que l’on passe en argument à la commande docker rm
, ce qui donne :
docker rm $(docker ps -aq)
cf9f5c62fd76
e1cdda3e617a
da45bf7c8733
8e8b1664d923
Dans la même idée, il est possible de supprimer toutes les images avec :
docker rmi $(docker images -q) -f
Untagged: ubuntu:latest
Untagged: ubuntu@sha256:99c35190e22d294cdace2783ac55effc69d32896daaa265f0bbedbcde4fbe3e5
Deleted: sha256:59ab366372d56772eb54e426183435e6b0642152cb449ec7ab52473af8ca6e3f
Deleted: sha256:a46a5fb872b554648d9d0262f302b2c1ded46eeb1ef4dc727ecc5274605937af
Untagged: ubuntu:mantic
Untagged: ubuntu@sha256:fd7fe639db24c4e005643921beea92bc449aac4f4d40d60cd9ad9ab6456aec01
Deleted: sha256:77081d4f1e7217ffd2b55df73979d33fd493ad941b3c1f67f1e2364b9ee7672f
Deleted: sha256:97f383acf79d194e4b447b5c631e3abc4470c56fa29ed3bb37730a727c70662c
Untagged: ubuntu:xenial
Untagged: ubuntu@sha256:1f1a2d56de1d604801a9671f301190704c25d604a416f59e03c04f5c6ffee0d6
Deleted: sha256:b6f50765242581c887ff1acc2511fa2d885c52d8fb3ac8c4bba131fd86567f2e
Deleted: sha256:0214f4b057d78b44fd12702828152f67c0ce115f9346acc63acdf997cab7e7c8
Deleted: sha256:1b9d0485372c5562fa614d5b35766f6c442539bcee9825a6e90d1158c3299a61
Deleted: sha256:3c0f34be6eb98057c607b9080237cce0be0b86f52d51ba620dc018a3d421baea
Deleted: sha256:be96a3f634de79f523f07c7e4e0216c28af45eb5776e7a6238a2392f71e01069
Si un conteneur a pour seule vocation de lancer une commande, il est inutile de le conserver sur la machine hôte ; il peut être supprimé dès qu’il a rempli sa fonction : cela peut se faire avec l’option --rm
:
docker run --rm ubuntu cat /etc/os-release
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
ff65ddf9395b: Pull complete
Digest: sha256:99c35190e22d294cdace2783ac55effc69d32896daaa265f0bbedbcde4fbe3e5
Status: Downloaded newer image for ubuntu:latest
PRETTY_NAME="Ubuntu 24.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04.1 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
Mais ensuite si on lance la commande docker ps -a
:
docker ps -a
aucun nouveau conteneur - même exited - n’apparaît :
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
NB : tant qu’un conteneur n’est pas supprimé, son environnement est sauvegardé et il peut être relancé.
Pour relancer un conteneur déjà présent en mémoire, là aussi deux options :
docker start <id conteneur>
ou
docker start <nom du conteneur>
L’option -a
de start
dirige (attache) la sortie du conteneur vers la sortie standard actuelle (STDOUT et STDERR)
Exemple :
docker run --name pascal ubuntu uname -a
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
ff65ddf9395b: Pull complete
Digest: sha256:99c35190e22d294cdace2783ac55effc69d32896daaa265f0bbedbcde4fbe3e5
Status: Downloaded newer image for ubuntu:latest
Linux fd3359949ce7 6.1.0-26-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.112-1 (2024-09-30) x86_64 x86_64 x86_64 GNU/Linux
Sur la dernière ligne, on voit la sortie de la commande passée en argument : uname -a
Le conteneur est maintenant présent en mémoire :
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fd3359949ce7 ubuntu "uname -a" About a minute ago Exited (0) About a minute ago pascal
On peut le relancer :
docker start -a pascal
La commande associée au conteneur est relancée :
Linux fd3359949ce7 6.1.0-26-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.112-1 (2024-09-30) x86_64 x86_64 x86_64 GNU/Linux
On peut remarquer que le hostname est le même que le nom de conteneur (fd3359949ce7)
Nous allons désormais interagir avec le conteneur, via l’entrée et la sortie standard.
docker run --name monserveur -it ubuntu
On obtient bien un prompt shell sur le conteneur, nous sommes root sur la machine db9e7f55a881 :
root@db9e7f55a881:/#
--name
permet de nommer le conteneur pour plus de confort dans sa manipulation future.-i
permet d’activer le mode interactif, qui récupère l’entrée standard (clavier).-t
permet d’avoir un pseudo-terminal (tty) pour exécuter des commandes dans le conteneur une fois lancé.Il est donc possible d’interagir avec le système pour le mettre à jour par exemple et y installer les applications que l’on veut :
apt update
Qui affichera quelque chose de ce genre :
Get:1 http://security.ubuntu.com/ubuntu noble-security InRelease [126 kB]
Get:2 http://archive.ubuntu.com/ubuntu noble InRelease [256 kB]
Get:3 http://archive.ubuntu.com/ubuntu noble-updates InRelease [126 kB]
Get:4 http://archive.ubuntu.com/ubuntu noble-backports InRelease [126 kB]
Get:5 http://security.ubuntu.com/ubuntu noble-security/main amd64 Packages [541 kB]
Get:6 http://security.ubuntu.com/ubuntu noble-security/restricted amd64 Packages [491 kB]
Get:7 http://security.ubuntu.com/ubuntu noble-security/universe amd64 Packages [715 kB]
Get:8 http://security.ubuntu.com/ubuntu noble-security/multiverse amd64 Packages [13.7 kB]
Get:9 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages [1808 kB]
Get:10 http://archive.ubuntu.com/ubuntu noble/restricted amd64 Packages [117 kB]
Get:11 http://archive.ubuntu.com/ubuntu noble/universe amd64 Packages [19.3 MB]
Get:12 http://archive.ubuntu.com/ubuntu noble/multiverse amd64 Packages [331 kB]
Get:13 http://archive.ubuntu.com/ubuntu noble-updates/multiverse amd64 Packages [18.2 kB]
Get:14 http://archive.ubuntu.com/ubuntu noble-updates/universe amd64 Packages [915 kB]
Get:15 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages [759 kB]
Get:16 http://archive.ubuntu.com/ubuntu noble-updates/restricted amd64 Packages [491 kB]
Get:17 http://archive.ubuntu.com/ubuntu noble-backports/universe amd64 Packages [11.8 kB]
Fetched 26.2 MB in 3s (9707 kB/s)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
3 packages can be upgraded. Run 'apt list --upgradable' to see them.
Depuis ce shell interactif du conteneur, lancez ces quelques autres commandes :
apt upgrade
apt install openssh-server sudo
adduser pascal
adduser pascal sudo
Les dépendances de base étant absentes (l'image est ultra-minimale), ceci devrait déclencher l'installation d'un certain nombres de paquets supplémentaires...
Quand le travail est terminé, on sort du conteneur par la commande exit
(ou CTRL D) qui sort du shell courant, et donc du conteneur puisque celui-ci n’a pour but que de faire tourner cet unique processus : le statut du conteneur passe donc à exited.
Ce qui a été fait est sauvegardé tant que le conteneur n’est pas supprimé : même s’il est arrêté, le conteneur contient tous les fichiers ajoutés (typiquement ici le paquet ssh et le nouvel utilisateur pascal).
Pour le réactiver et y accéder de nouveau en interactif :
docker start monserveur
docker attach monserveur
Ou encore :
docker start -ai monserveur
On retrouve le shell du conteneur, et son historique notamment (vérifiez en parcourant l'histrique des commandes).
Ne pas oublier de sortir du shell du conteneur
Il est possible de visualiser la (très) longue liste des modifications apportées au conteneur (commande diff
) ; on prend soin de sortir du conteneur avant :
docker diff monserveur
Ici en limitant aux 20 premières lignes :
Pour voir les processus lancés dans le conteneur (qui doit être démarré) :
docker start monserveur
docker top monserveur
UID PID PPID C STIME TTY TIME CMD
root 11917 11897 0 18:28 pts/0 00:00:00 /bin/bash
Nous pouvons constater que le service ssh que nous avons installé n’est pas lancé. On va utiliser la commande exec
pour lancer le démarrage du service sur le conteneur actif :
docker exec monserveur service ssh start
* Starting OpenBSD Secure Shell server sshd
...done.
Et dès lors la commande :
docker top monserveur
Nous donne :
UID PID PPID C STIME TTY TIME CMD
root 11917 11897 0 18:28 pts/0 00:00:00 /bin/bash
root 12047 11917 0 18:30 ? 00:00:00 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
La commande exec
permet de lancer une commande dans un conteneur actif, avec des options identiques à la commande run
, notamment :
-d
de exec
lance la commande en arrière-plan.-i
active le mode interactif, qui récupère l’entrée standard (clavier).-t
permet d’avoir un pseudo-terminal (tty) pour interagir avec la commande (associé à l’option -i
)Il existe deux méthodes pour créer des images Docker.
La première (que nous n’aborderons pas encore ici) consiste à écrire un dockerfile contenant une liste de commandes permettant de créer l’image.
La deuxième utilise la commande commit
:
docker commit <nom conteneur> <nom image>
Le seul paramètre obligatoire ici est le nom ou l’identifiant du container. La commande ci-dessus n’utilise pas les nombreuses options disponibles.
Le nom de la future image est libre mais nous pouvons utiliser les règles d’usage en préfixant le nom et en y associant un tag pour identifier la modification plus simplement parmi les autres.
docker commit monserveur ubuntu/pm:ssh
La commande produit un hash (sha256) permettant au système d’identifier de manière unique la nouvelle image :
sha256:dd0e78e96657dfc3f2a91198387f6a23c93c1f300d5693e9fed4f995dafa47b4
L'image créée apparaît dans la liste des images du système :
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu/pm ssh dd0e78e96657 9 seconds ago 253MB
ubuntu latest 59ab366372d5 10 days ago 78.1MB```
C’est cette nouvelle image (et non plus l’image téléchargée du Hub) que nous allons exploiter maintenant.
IMPORTANT : la commande par défaut associée à cette nouvelle image sera la commande qui a été saisie au lancement du conteneur. Par exemple, si je crée un conteneur toto avec cette commande :
docker run --name toto ubuntu cat /etc/os-release
et que je crée une image à partir du conteneur toto :
docker commit toto ubuntoto
Tout lancement de l’image sans commande spécifique :
docker run ubuntoto
Lancera la commandecat /etc/os-release
Supprimons maintenant le conteneur (après l’avoir arrêté).
docker stop monserveur
docker rm monserveur
Il peut être utile de sauvegarder une image localement à des fins d’exploitation sur un autre PC (en attendant de publier notre image sur le Hub officiel ou un autre Hub).
On utilise l’opérateur de redirection de la sortie standard >
vers un fichier ; docker refusera la commande si cette redirection n’est pas faite :
docker save <image> > <nom_fichier.tar>
Par exemple :
docker save ubuntu/pm:ssh > serv_ubuntu-ssh.tar
ls -lh
total 250M
-rw-r--r-- 1 pascal pascal 250M 21 oct. 20:02 serv_ubuntu-ssh.tar
Pour récupérer une image depuis une archive enregistrée localement :
docker load -i <nom_fichier.tar>
Par exemple :
docker load -i serv_ubuntu-ssh.tar
Pour rendre le service fourni par un conteneur accessible, il faut tout d'abords que ce conteneur soit lancé en arrière-plan.
Docker utilise ensuite (par défaut) la technique classique du mappage de port : un port de l’hôte va être redirigé vers un port du container (nat masquerading).
Docker dispose pour cela d’une interface réseau spécifique docker0 sur la machine hôte :
ip -4 -c a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:22:4e:2c brd ff:ff:ff:ff:ff:ff
inet 192.168.68.111/24 brd 192.168.68.255 scope global dynamic enp0s3
valid_lft 6804sec preferred_lft 6804sec
inet6 fe80::a00:27ff:fe22:4e2c/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:3a:89:c3:01 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
Les conteneurs en cours de fonctionnement sur notre système auront une (ou plusieurs) interfaces réseau dans 172.17.0.0/16
, qui est appelé le réseau bridge de Docker.
Un routage (natté) est en place - géré par Docker - entre ce réseau bridge et le LAN.
L’interface docker0 de la machine hôte est donc le lien avec le réseau bridge de Docker. Pour obtenir des infos sur ce réseau, et notamment les conteneurs connectés dedans, on utilise la commande network inspect :
docker network inspect bridge
Voici une représentation du réseau interne du Docker Engine :
Une commande possible pour exposer un conteneur dans le réseau local est la suivante :
docker run -d -p <@IP:port-hôte:port-conteneur> --name <nom conteneur> <image> COMMANDE
Le paramètre permettant le mappage est -p <IP:port-hôte:port-container>
:
Utilisons l’image que nous avons créée pour lancer un serveur ssh.
Le principe est ensuite de lancer le service en même temps que le conteneur, via la commande, sachant que :
-d
qui permet cela.docker run -d -p 2222:22 --name srvssh ubuntu/pm:ssh /usr/sbin/sshd -D
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a2a42040823f ubuntu/pm:ssh "/usr/sbin/sshd -D" 7 seconds ago Up 6 seconds 0.0.0.0:2222->22/tcp, [::]:2222->22/tcp srvssh
Regardons bien la rubrique PORTS ci-dessus : on n'a pas précisé l’adresse IP dans le paramètre
-p
, le port tcp/2222 est donc ouvert sur toutes les interfaces de la machine hôte, en IPv4 (0.0.0.0) et en IPv6 [::].
Voici le schéma de l'exposition du service ssh du conteneur depuis le réseau local de l'hôte :
On peut maintenant accéder au conteneur en ssh sur le port 2222 à partir de n’importe quel hôte sur le même LAN que le serveur Docker (l’adresse IP est celle du serveur Docker, et dépend bien sûr de votre environnement) :
ssh pascal@192.168.68.111 -p 2222
The authenticity of host '[192.168.68.111]:2222 ([192.168.68.111]:2222)' can't be established.
ED25519 key fingerprint is SHA256:ISRQ14PD8oELYAnfULidDYCqxfVzORvmm60F7i42Xkg.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[192.168.68.111]:2222' (ED25519) to the list of known hosts.
pascal@192.168.68.111's password:
Welcome to Ubuntu 24.04.1 LTS (GNU/Linux 6.1.0-26-amd64 x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
This system has been minimized by removing packages and content that are
not required on a system that users do not log into.
To restore this content, you can run the 'unminimize' command.
The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
pascal@a2a42040823f:~$
Nous disposons bien du shell sur notre conteneur actif.
Il s’agit d’une commande utile notamment si la création du conteneur se passe mal et si l’accès en ssh n’est pas possible (cette commande ne renvoie rien dans ce cas si tout se passe bien).
docker logs srvssh
Voilà donc terminée cette première phase d'approche des conteneurs avec Docker. Nous avons pu installer un serveur, récupérer des images, lancer des conteneurs, modifier et sauvegarder des images, et exposer un conteneur au travers du réseau Docker.
Il reste bien des choses à explorer, comme la gestion des volumes, les liaisons, les variables d'environnement ou encore le déploiement avancé avec dockerfile ou Docker Compose.