Voici le sixième volet de la formation Docker. Dans mon précédent article, nous avons vu en détail l’exposition d’un conteneur et le partage de données entre le conteneur et le système hôte. Aujourd’hui nous allons nous intéresser de plus près à l’ouverture d’un shell interactif sur un conteneur en état d’exécution.
Interagir avec un conteneur
En temps normal, on n’utilise pas SSH pour se connecter à un conteneur comme on le ferait avec une machine virtuelle, par exemple. Plutôt que de modifier un conteneur en cours d’exécution, on préférera adapter le Dockerfile
correspondant pour ensuite reconstruire l’image du conteneur.
Ceci étant dit, il peut être utile dans certains cas de figure de se connecter directement à un conteneur pour savoir ce qui se passe à l’intérieur, et de le faire de manière interactive plutôt que de simplement regarder les logs ou les données générées par le conteneur.
Docker fournit la commande exec
pour accéder à un conteneur en état d’exécution. Avant de faire ça, nous allons nous connecter directement au shell d’un conteneur au moment de son lancement.
Connexion avec la commande run
Pour démarrer un conteneur Apache auquel nous pouvons accéder directement via le shell au moment du lancement, nous allons utiliser la commande suivante :
$ docker run -it --name apache httpd /bin/bash root@d724f090a8cf:/usr/local/apache2#
- L’option
-it
est requise si vous voulez disposer d’un shell interactif. - Nous n’avons pas utilisé l’option
-d
pour détacher le conteneur et l’exécuter en arrière-plan. Cette fois-ci nous exécutons la commande en avant-plan. - Nous avons indiqué une commande à exécuter à Docker, en l’occurrence
/bin/bash
. - Une fois que la commande s’exécute, nous voyons que l’invite de commande change. C’est l’invite de l’interpréteur de commandes Bash, qui nous affiche l’utilisateur
root
, le nom d’hôted724f090a8cf
du conteneur suivi de deux-points, puis le répertoire courant, en l’occurrence/usr/local/apache2
.
Une fois que nous sommes dans le conteneur, nous pouvons exécuter n’importe quelle commande disponible dans le shell Bash :
root@d724f090a8cf:/usr/local/apache2# pwd /usr/local/apache2 root@d724f090a8cf:/usr/local/apache2# ls bin build cgi-bin conf error htdocs icons include logs modules
Pour quitter le conteneur, nous pouvons utiliser le raccourci Ctrl+D ou la commande exit
et nous retrouvons l’invite de l’hôte :
root@d724f090a8cf:/usr/local/apache2# exit exit [kikinovak@alphamule:~] $
Jetons un œil sur docker ps
:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Le conteneur ne s’affiche pas ici, étant donné qu’il n’est plus en cours d’exécution. Cela tient au fait que nous n’avons pas fourni l’option -d
pour le détacher et l’exécuter en arrière-plan.
Il a exécuté la commande que nous lui avons fournie en argument – en l’occurrence /bin/bash
– et dès que nous avons quitté Bash, le conteneur s’est arrêté.
Maintenant, exécutons la commande à nouveau, mais en ajoutant l’option -d
:
$ docker run -dit --name autre_apache httpd /bin/bash 96e278c968a813c01194424236e588cb5e9284fd6d85b1d837cf04ae3e67e5d2 $ docker ps CONTAINER ID IMAGE COMMAND ... NAMES 96e278c968a8 httpd "/bin/bash" ... autre_apache
- Cette fois-ci, le conteneur s’est immédiatement détaché, étant donné que nous avons utilisé l’option
-d
. - L’argument final
/bin/bash
n’a pas vraiment de sens ici. Le conteneur est certes en état d’exécution, mais nous n’y sommes pas connectés. Nous ne pouvons donc pas taper des commandes dans l’interpréteur de commandes Bash.
Modérez vos attentes en matière de shells avec les conteneurs Docker. Beaucoup de conteneurs sont basés sur Alpine Linux, une distribution Linux minimaliste qui permet de construire des conteneurs très réduits. Alpine n’utilise pas une version complète de Bash, vous devez donc ajouter /bin/sh
pour accéder à une invite. D’autres distributions procèdent de même. Certaines utilisent un lien symbolique /bin/bash
vers un shell sh
à l’ancienne. Quoi qu’il en soit, attendez-vous à ne pas pouvoir accéder à toutes les commandes que vous utilisez habituellement, à la complétion automatique et l’historique des commandes, etc.
Voici une petite astuce, qui est juste une manière différente de faire les choses. Un peu plus haut, nous avons fourni le chemin complet /bin/bash
à notre commande run
, ce qui est la façon orthodoxe de procéder. Or, vous pouvez très bien passer bash
ou sh
comme dernier paramètre. Ce qui fonctionnera tant que la variable d’environnement PATH
interne est configurée pour le conteneur et que la commande bash
ou sh
se trouve dans le PATH
, ce qui est généralement le cas.
Connexion avec la commande exec
Passons à la commande docker exec
. Comme nous venons de le voir, cela ne sert pas à grand-chose de spécifier la commande /bin/bash
à un conteneur qui sera détaché immédiatement. Ce qui veut dire que nous avons besoin d’un autre moyen pour accéder au shell d’un conteneur en cours d’exécution. Et c’est là où nous allons utiliser la commande exec
.
$ docker run -dit --name shelltest httpd
373a25810b747e6f8198cedd40974cad11d007aea68dd5f889fedbda869e0d9a
$ docker ps
...
$ docker exec -it shelltest /bin/bash
root@373a25810b74:/usr/local/apache2# exit
Voyons ce que cela donne si nous ne fournissons pas le chemin complet vers le shell Bash :
$ docker exec -it shelltest bash root@373a25810b74:/usr/local/apache2# exit
Et avec le shell rudimentaire sh :
$ docker exec -it shelltest sh # exit
Dans ce contexte, une erreur fréquente consiste à oublier les options -it
. Dans ce cas, le shell va s’exécuter et s’arrêter aussitôt.
Exécuter des commandes
Vous vous en doutez probablement, mais la sous-commande exec
ne se limite pas au lancement d’un shell. Elle sait faire bien plus que ça. En principe, elle nous permet d’exécuter toutes les commandes disponibles dans un conteneur.
La commande ci-dessous crée un fichier vide coucou.txt
dans un conteneur en passant par exec
.
$ docker run -dit --name execution httpd
c7bf797bd79176fbc6c4dd99b0a0b27bd6aa3175442df0e8819e7e16cdab07e2
$ docker ps
...
$ docker exec -d execution touch /root/coucou.txt
$ docker exec -it execution bash
root@c7bf797bd791:/usr/local/apache2# ls /root
coucou.txt
root@c7bf797bd791:/usr/local/apache2# exit
exit
Et puisque nous pouvons exécuter n’importe quelle commande disponible dans le conteneur, nous aurions très bien pu faire ceci :
$ docker exec -it execution ls /root coucou.txt
Tout l’intérêt des containers, c’est que ce sont des images extrêmement réduites. Ce ne sont pas des systèmes d’exploitation complets ou des installations complètes de distributions Linux. Ce qui signifie que certaines ou même la plupart des commandes que vous avec l’habitude d’utiliser au quotidien sous Linux peuvent ne pas être disponibles dans un conteneur :
$ docker exec -it execution bash root@c7bf797bd791:/usr/local/apache2# uptime bash: uptime: command not found root@c7bf797bd791:/usr/local/apache2# man bash: man: command not found root@c7bf797bd791:/usr/local/apache2# locate bash: locate: command not found root@c7bf797bd791:/usr/local/apache2# vim bash: vim: command not found root@c7bf797bd791:/usr/local/apache2# vi bash: vi: command not found root@c7bf797bd791:/usr/local/apache2# nano bash: nano: command not found
Si vous voulez qu’une commande soit disponible dans votre conteneur, vous pouvez très bien l’installer. L’image officielle httpd:latest
est basée sur Debian, nous pouvons donc utiliser les gestionnaires de paquets apt-get
ou apt
pour installer un ou plusieurs paquets :
root@c7bf797bd791:/usr/local/apache2# apt update root@c7bf797bd791:/usr/local/apache2# apt install vim root@c7bf797bd791:/usr/local/apache2# vim
L’installation d’un paquet modifie le conteneur en cours d’exécution, mais pas l’image sur laquelle ce conteneur est basé. Si vous voulez qu’un logiciel soit disponible dans les nouveaux conteneurs, il vous faudra recréer l’image en conséquence.
L’absence de la commande ps
dans certains conteneurs peut s’avérer gênante :
root@c7bf797bd791:/usr/local/apache2# ps bash: ps: command not found
Dans ce cas, il vaut mieux utiliser la commande docker top
, qui permet d’afficher les processus en cours à l’intérieur d’un conteneur :
root@c7bf797bd791:/usr/local/apache2# exit exit $ docker top execution UID PID PPID C STIME TTY TIME CMD root 2414 2396 0 09:52 pts/0 00:00:00 httpd -DFOREGROUND bin 2440 2414 0 09:52 pts/0 00:00:00 httpd -DFOREGROUND bin 2441 2414 0 09:52 pts/0 00:00:00 httpd -DFOREGROUND bin 2442 2414 0 09:52 pts/0 00:00:00 httpd -DFOREGROUND
Ici, nous voyons quatre processus httpd
en cours à l’intérieur du conteneur nommé execution
.
Exercice
- Lancez un conteneur basé sur l’image
redis
de manière à vous connecter directement au shell Bash du conteneur. Nommez le conteneurshell_redis
. - Quelle est la version du shell Bash fourni par le conteneur ?
- Quittez le shell du conteneur.
- Vérifiez s’il est bien arrêté.
- Supprimez-le.
- Lancez un autre conteneur
exec_redis
basé sur cette même image. Cette fois-ci, le conteneur devra tourner en arrière-plan. - Vérifiez si le conteneur tourne en arrière-plan comme prévu.
- Connectez-vous au shell Bash du conteneur en état d’exécution.
- Affichez la version du shell Bash.
- Quittez le conteneur.
- Reconnectez-vous sans spécifier le chemin complet vers le shell Bash.
- Quittez le conteneur en utilisant une autre manière que celle que vous venez d’utiliser.
- Vérifiez si le conteneur tourne toujours.
- Reconnectez-vous une dernière fois au conteneur. Cette fois-ci, utilisez le shell rudimentaire
sh
plutôt que Bash. - Quittez le conteneur.
- Arrêtez-le et supprimez-le.
Lire la suite : Gérer les logs
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce blog ? Offrez un café au rédacteur en cliquant sur la tasse.
0 commentaire