Manipuler les conteneurs

Démarrer un conteneur

Dans nos premiers pas, nous avons lancé un conteneur avec la commande docker run. C'est celle qui nous permet de démarrer un conteneur à partir d'une image. Instinctivement on pourrait lancer :

1
docker run debian:bookworm

Le résultat est cependant assez décevant, globalement rien ne se passe. En effet cette commande lance simplement un conteneur à partir de l'image debian:bookworm, mais on ne lui a rien demandé de plus.

Lorsque l'on lance un conteneur, il convient de spécifier 2 informations supplémentaires :

  • le processus que l'on souhaite démarrer dans le conteneur

  • si l'on souhaite interagir avec le processus dans le conteneur ou si l'on veut le lancer en arrière-plan

Concernant le processus, nous avions précédemment lancé le processus bash grâce à la commande docker run debian:bookworm bash. Le second paramètre de la commande docker run est la commande que l'on souhaite lancer dans le conteneur. Cependant, la plupart des images ont une commande par défaut à lancer, et dans le cas de debian:bookworm c'est la commande bash (il est possible d'obtenir cette information avec la commande docker image inspect debian:bookworm, mais nous ne nous attarderons pas là dessus).

La seconde information à spécifier est le mode de lancement du conteneur. Par défaut la commande docker run ne connecte pas le terminal de l'utilisateur dans le conteneur, pour cela on passe généralement 2 options :

- -i qui permet d'attacher le terminal à l'entrée standard du processus que l'on lance

- -t qui permet d'allouer un TTY au conteneur

Ces 2 options sont généralement passées ensemble et elles permettent de "connecter" son terminal au conteneur (au processus lancé dans le conteneur plus précisément).

En conclusion, pour refaire les manipulations du début de module, on peut lancer notre conteneur avec la commande :

1
docker run -it debian:bookworm

Cependant il est aussi possible de lancer un conteneur en mode détaché, c'est d'ailleurs le cas le plus fréquent. Par exemple si l'on veut faire tourner un service web et une base de données en arrière-plan sur le serveur. Pour cela on utilise simplement l'option -d. Par exemple la commande docker run -d debian:bookworm sleep 10 va lancer, en arrière plan, un processus sleep 10 dans un conteneur. Une fois le processus terminé le conteneur s'arrêtera.

Gérer les conteneurs

Maintenant que l'on sait démarrer nos conteneurs, il serait intéressant de pouvoir contrôler leur cycle de vie. En effet un conteneur Docker peut-être dans plusieurs états :

  • running indique que le conteneur est en cours d’exécution

  • exited indique le conteneur a terminé son exécution

  • paused indique que le conteneur est mis en pause dans son exécution

  • d'autres états de transition (created, restarting, removing) ou d'erreur (dead) qui ne seront pas approfondis ici

Lorsque l'on lance la commande docker run, Docker va d'abord créer un conteneur à partir de l'image choisie, puis le démarrer pour le mettre dans un état running. Quand le processus à l'intérieur du conteneur aura terminé de s’exécuter, le conteneur va s'arrêter et deviendra exited.

Sur notre machine, on peut lister tout les conteneurs existants avec la commande docker container ls -a.

Pour chaque conteneur on obtient les informations suivantes :

  • un identifiant unique pour le conteneur

  • l'image Docker utilisée par ce conteneur

  • la commande (ou le processus) lancée dans le conteneur

  • la date de création du conteneur

  • son statut et le temps depuis lequel il est dans ce statut

  • le nom du conteneur

Premier constat : Docker a donné des noms aux conteneurs alors que nous ne lui avons rien demandé ! En effet Docker génère automatiquement un nom (selon un algorithme plutôt rigolo) pour chaque nouveau conteneur, mais il est possible (et d'ailleurs fortement recommandé) de nommer les conteneurs autrement. Pour cela on utilisera l'option --name NOM_CONTENEUR au lancement de docker run.

Deuxième constat : tout les conteneurs que nous avons lancé jusqu'ici sont listés, même si ils sont arrêtés. En effet l'option -a permet de lister la totalité des conteneurs (sans cela seuls ceux qui sont démarrés seraient listés). On peut d'ailleurs supprimer rapidement les conteneurs en statut Exited avec la commande docker container rm NOM_CONTENEUR, pour éviter que la liste ne grandisse trop au fur et à mesure de nos manipulations. Il est aussi possible d'indiquer à Docker de supprimer automatiquement un conteneur lorsque celui-ci se termine, grâce à l'option --rm dans la commande docker run (nous avions utilisé cette option au tout début de la prise en main des conteneurs).

Stopper, suspendre et lancer un processus dans un conteneur

Avec Docker il est possible de changer l'état de son conteneur manuellement. Par exemple démarrer un conteneur qui est arrêté, on utilisera tout simplement docker start NOM_CONTENEUR. De la même manière c'est avec docker stop que l'on peut stopper le conteneur prématurément.

Une autre action est aussi possible : mettre en "pause" un conteneur. Avec docker pause, le processus dans le conteneur verra son exécution suspendue. La commande docker unpause permet de relancer le processus qui reprendra son exécution dans le même état que lors de son interruption. C'est une fonctionnalité qui peut s'avérer intéressante lorsque l'on veut sauvegarder des données qui sont manipulées par le conteneur (par exemple dans le cas d'une base de donnée) et donc bloquer les I/O très temporairement.

Enfin, il est possible de lancer des commandes directement dans un conteneur en cours d’exécution, en parallèle du processus courant. Ceci est possible grâce à la commande docker exec -it NOM_CONTENEUR COMMANDE, elle est très souvent utilisé lorsqu'il est nécessaire d'ouvrir un shell dans un conteneur. Prenons l'exemple d'un conteneur qui exécute une instance de base de donnée : PostgreSQL. On peut très simplement démarrer un conteneur à partir de l'image officielle postgres qui démarre une instance PostgreSQL :

Le conteneur démarre en mode détaché et l'instance PostgreSQL est démarrée. Si on souhaite accèder au SGBD afin de créer une base de données (par exemple) on peut tout simplement

lancer "docker exec -it postgresql psql -U postgres".

Ceci va simplement lancer la commande "psql -U postgres" à l'intérieur du conteneur, nous permettant de faire ensuite des manipulations (par exemple créer une BDD avec "CREATE DATABASE").

1
docker run -d --name postgresql -e POSTGRES_PASSWORD=votresupermotdepassepourlabasededonnee postgres

Le conteneur démarre en mode détaché et l'instance PostgreSQL est démarrée. Si on souhaite accéder au SGBD afin de créer une base de données (par exemple) on peut tout simplement lancer :

1
 docker exec -it postgresql psql -U postgres

Ceci va simplement lancer la commande psql -U postgres à l'intérieur du conteneur, nous permettant de faire ensuite des manipulations (par exemple créer une BDD avec CREATE DATABASE).

Conclusion

Nous venons d'aborder, de manière un peu condensée, les commandes et mécanismes de bases de Docker. Il est particulièrement important de les maîtriser, et il peut-être judicieux de prendre le temps de manipuler quelques conteneurs (éventuellement tester des images présentes sur le Docker Hub) pour s'assurer que ces bases sont acquises.