Aller au contenu

Exercice 5 — Entrer dans un conteneur

Durée : ~35 min · Individuel · Théorie associée : Les commandes de base de Docker

Objectif

Vous savez entrer dans un conteneur qui tourne pour y regarder et y modifier des fichiers. Vous savez aussi régler une image avec une variable d'environnement, et lire les journaux d'un conteneur qui refuse de démarrer.

Prérequis

  • L'exercice 4 terminé : vous savez lancer nginx avec -p et l'ouvrir depuis votre poste.

Partie A — Modifier un site de l'intérieur

Étape 1 — Lancer le serveur web

Bash
docker run -d --name web -p 8080:80 nginx

Ouvrez http://10.70.#.31:8080 sur votre poste : la page Welcome to nginx! s'affiche.

Étape 2 — Trouver les fichiers du site

docker exec lance une commande dans un conteneur qui tourne déjà, sans le redémarrer :

Bash
docker exec web ls /usr/share/nginx/html
Texte
50x.html
index.html

Voilà les deux fichiers que nginx sert. index.html est la page d'accueil que vous voyez dans le navigateur. Le dossier /usr/share/nginx/html est celui du conteneur : il n'existe pas dans votre VM. Vérifiez :

Bash
ls /usr/share/nginx/html
Texte
ls: cannot access '/usr/share/nginx/html': No such file or directory

La console : docker exec web ls affiche 50x.html et index.html, alors que le dossier n'existe pas dans la VM

Étape 3 — Ouvrir un shell dans le conteneur

Bash
docker exec -it web bash

L'invite devient root@ suivi de 12 caractères : l'identifiant du conteneur. Vous êtes dans le conteneur, à côté de nginx qui continue de tourner.

Bash
cat /usr/share/nginx/html/index.html

Vous reconnaissez le texte de la page d'accueil, en HTML.

La console : l'invite devient root@b28496b36225, et cat affiche le code HTML de Welcome to nginx!

Étape 4 — Chercher un éditeur

Bash
nano /usr/share/nginx/html/index.html
Texte
bash: nano: command not found

Essayez vi : même réponse. L'image nginx ne contient que ce qu'il faut pour faire tourner nginx. Un éditeur de texte n'est pas nécessaire au serveur web, donc il n'y est pas. C'est voulu : moins il y a de programmes dans une image, plus elle est petite et moins elle a de failles.

On peut quand même écrire un fichier avec echo et une redirection.

La console : nano et vi répondent command not found

Étape 5 — Remplacer la page d'accueil

Toujours dans le conteneur, remplacez Votre prénom par votre prénom :

Bash
echo "<h1>Le site de Votre prénom</h1>" > /usr/share/nginx/html/index.html

Rafraîchissez la page dans votre navigateur : votre titre s'affiche. nginx n'a pas eu besoin de redémarrer, il lit le fichier à chaque visite.

Le navigateur sur http://10.70.4.31:8080 affiche Le site de Marc

Étape 6 — Sortir sans arrêter le conteneur

Bash
exit

Vous revenez à l'invite de la VM.

Bash
docker ps

web est toujours Up. Vous n'avez quitté que le shell de plus que docker exec avait lancé. Le programme principal du conteneur, nginx, n'a pas bougé. C'est la grande différence avec l'exercice 3, où exit arrêtait le conteneur : là, le shell était le programme principal.

La console : echo écrit la page, exit ramène à la VM, et docker ps affiche web toujours Up

Étape 7 — Arrêter et relancer

Bash
docker stop web
docker start web

docker stop peut prendre une dizaine de secondes : Docker envoie à nginx un signal d'arrêt, puis attend jusqu'à 10 secondes avant de le forcer. Rafraîchissez la page : votre titre est toujours là. Un conteneur arrêté garde son contenu.

La console : docker stop web, puis docker start web

Le navigateur affiche toujours Le site de Marc après l'arrêt et la relance

Étape 8 — Supprimer et recréer

Bash
docker rm -f web
docker run -d --name web -p 8080:80 nginx

Rafraîchissez la page : Welcome to nginx! est revenu. Votre modification a disparu.

Le conteneur porte le même nom, mais c'est un nouveau conteneur, sorti de l'image nginx. Votre index.html n'était écrit que dans l'ancien conteneur, et il a été supprimé avec lui. L'image, elle, n'a jamais changé.

La console : docker rm -f web, puis docker run crée un nouveau conteneur web

Le navigateur affiche de nouveau Welcome to nginx!

Ce qu'on écrit dans un conteneur ne survit pas à sa suppression

En production, les conteneurs sont supprimés et recréés tout le temps : pour une mise à jour, un changement de réglage, un déplacement. Un fichier modifié à la main dans un conteneur est donc un fichier perdu tôt ou tard. Vous verrez à la semaine 10 comment garder des données en dehors du conteneur, avec les volumes, et à la semaine 9 comment fabriquer votre propre image, avec votre page dedans.

Supprimez le conteneur :

Bash
docker rm -f web

Partie B — Une base de données qui refuse de démarrer

Étape 9 — Lancer MariaDB sans réglage

MariaDB est un serveur de base de données, un proche cousin de MySQL. Lancez-le comme vous avez lancé nginx :

Bash
docker run -d --name bdd mariadb:11

Cette fois, l'image a une étiquette : 11, la version majeure de MariaDB. Le téléchargement est plus long que pour nginx : l'image fait plus de 300 Mo.

Docker affiche l'identifiant du conteneur. Tout semble aller.

Étape 10 — Constater le problème

Bash
docker ps

bdd n'apparaît pas.

Bash
docker ps -a
Texte
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS                      PORTS     NAMES
4a8c1e7d2b90   mariadb:11   "docker-entrypoint.s…"   20 seconds ago   Exited (1) 17 seconds ago             bdd

Exited (1) : le programme s'est terminé sur une erreur, au bout de quelques secondes. Pour savoir laquelle, on lit les journaux.

La console : docker run télécharge mariadb:11, docker ps est vide, docker ps -a affiche bdd en Exited (1)

Étape 11 — Lire les journaux

Bash
docker logs bdd
Texte
... [Note] [Entrypoint]: Entrypoint script for MariaDB Server 1:11.8.9+maria~ubu2404 started.
... [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
    You need to specify one of MARIADB_ROOT_PASSWORD, MARIADB_ROOT_PASSWORD_HASH, MARIADB_ALLOW_EMPTY_ROOT_PASSWORD and MARIADB_RANDOM_ROOT_PASSWORD

Le message est clair : la base de données refuse de démarrer sans mot de passe pour son compte administrateur. Elle vous dit même comment le lui donner : avec une des variables MARIADB_ROOT_PASSWORD, MARIADB_RANDOM_ROOT_PASSWORD...

Retenez ce réflexe : un conteneur qui s'arrête tout seul, on lit ses journaux. La réponse y est presque toujours.

La console : docker logs bdd se termine par ERROR Database is uninitialized and password option is not specified

Étape 12 — Relancer avec une variable d'environnement

On ne peut pas ajouter une variable à un conteneur existant. Supprimez-le et créez-en un nouveau, avec l'option -e :

Bash
docker rm bdd
docker run -d --name bdd -e MARIADB_ROOT_PASSWORD=Secret123 mariadb:11

Attendez une quinzaine de secondes, puis :

Bash
docker ps

bdd est Up. Vérifiez dans les journaux que le serveur est prêt :

Bash
docker logs --tail 2 bdd
Texte
... [Note] mariadbd: ready for connections.
Version: '11.8.9-MariaDB-ubu2404'  socket: '/run/mysqld/mysqld.sock'  port: 3306  mariadb.org binary distribution

La même image a refusé de démarrer, puis a démarré. Seule la variable a changé. C'est ainsi qu'on règle une image sans la modifier : chaque conteneur reçoit ses propres réglages au docker run.

La console : bdd est Up avec 3306/tcp, et docker logs --tail 2 bdd affiche ready for connections, version 11.8.9

Étape 13 — Interroger la base de données

L'image MariaDB contient le client mariadb, qui permet de taper des requêtes SQL. Lancez-le dans le conteneur avec docker exec :

Bash
docker exec -it bdd mariadb -uroot -pSecret123

L'invite devient MariaDB [(none)]>. Tapez :

SQL
SELECT VERSION();
SHOW DATABASES;

La base de données répond. Tapez exit pour sortir du client. Le conteneur continue de tourner.

La console : le client mariadb répond à SELECT VERSION() et à SHOW DATABASES, puis exit

Étape 14 — Faire le ménage

Bash
docker rm -f bdd
docker ps -a

La liste est vide.

La console : docker rm -f bdd, puis docker ps -a est vide

Vérification finale

  • Votre titre s'est affiché dans le navigateur après l'étape 5
  • Votre titre était toujours là après docker stop et docker start, et avait disparu après docker rm et docker run
  • Vous avez trouvé dans docker logs pourquoi MariaDB refusait de démarrer
  • SELECT VERSION(); a répondu dans le conteneur bdd
  • docker ps -a est vide

Question 1

Dans l'exercice 3, exit arrêtait le conteneur. Ici, à l'étape 6, le conteneur a continué de tourner. Pourquoi ?

Voir la réponse Dans l'exercice 3, le shell avait été lancé par `docker run -it alpine sh` : il était **le programme principal** du conteneur. Quand il s'est terminé, le conteneur s'est arrêté. Ici, le programme principal est nginx. Le shell a été lancé **en plus** par `docker exec`. Le quitter ne touche pas à nginx, et le conteneur continue de tourner.

Question 2

Un collègue a corrigé une erreur dans la page d'un site en entrant dans le conteneur avec docker exec. Le lendemain, la mise à jour automatique a recréé le conteneur, et l'erreur est revenue. Que s'est-il passé ?

Voir la réponse Sa correction n'était écrite que dans l'ancien conteneur. La mise à jour a supprimé ce conteneur et en a créé un nouveau à partir de l'image, qui contient toujours la page avec l'erreur. La correction doit être faite dans l'image elle-même, en en fabriquant une nouvelle version. C'est le sujet de la semaine 9.

Question 3

Vous lancez un conteneur, et docker ps -a le montre en Exited (1) après deux secondes. Quelle est votre première commande ?

Voir la réponse
Bash
docker logs NOM_DU_CONTENEUR
Le code `1` signale que le programme s'est terminé sur une erreur. Tout ce que le programme a affiché avant de s'arrêter est conservé par Docker, et `docker logs` le relit. Le message d'erreur y est presque toujours.

En cas de problème

Symptôme Cause probable Correction
Error response from daemon: container ... is not running docker exec ne marche que sur un conteneur en marche docker ps -a pour voir son état. docker start NOM, ou lire docker logs NOM
docker exec -it web sh fonctionne, mais pas bash Selon l'image, bash n'est pas toujours installé Utiliser sh, présent dans presque toutes les images
ERROR 1045 (28000): Access denied for user 'root' Le mot de passe tapé après -p ne correspond pas à MARIADB_ROOT_PASSWORD Vérifier qu'il n'y a pas d'espace entre -p et le mot de passe
ERROR 2002 (HY000): Can't connect to local server MariaDB n'a pas fini de démarrer Attendre la ligne ready for connections dans docker logs bdd
Le titre affiche des caractères bizarres à la place des accents La page n'indique pas son encodage Sans gravité. Écrire le prénom sans accent, ou ajouter <meta charset="utf-8"> au début de la ligne echo