Exécuter une commande sans démarrer les services liés
Dans cette étape, nous allons apprendre comment exécuter une commande dans un conteneur Docker faisant partie d'une application multi-conteneurs, sans démarrer les autres services liés. Ceci est particulièrement utile pour exécuter des migrations de base de données, des scripts de configuration ou des commandes de débogage dans un service sans avoir à démarrer toute la pile d'applications.
Bien que Docker Compose soit l'outil standard pour gérer des applications multi-conteneurs et dispose de fonctionnalités pour exécuter des commandes ponctuelles sur des services spécifiques, nous allons démontrer ici les concepts sous-jacents de Docker. Comme Docker Compose n'est pas préinstallé dans cet environnement, nous nous concentrerons sur l'utilisation de la commande docker run
avec le réseau.
Simulons un scénario simple avec deux conteneurs : une application web et une base de données. Nous utiliserons une image générique ubuntu
pour représenter notre application web et une image postgres
pour la base de données.
Tout d'abord, téléchargeons l'image postgres
:
docker pull postgres:latest
Vous devriez voir une sortie indiquant que l'image est en cours de téléchargement.
Using default tag: latest
latest: Pulling from library/postgres
...
Status: Downloaded newer image for postgres:latest
docker.io/library/postgres:latest
Maintenant, créons un réseau Docker pour que nos conteneurs puissent communiquer entre eux par nom.
docker network create my-app-network
Vous devriez voir l'ID du réseau affiché.
<network_id>
Ensuite, lançons le conteneur postgres
et connectons-le à notre réseau. Nous définirons également un mot de passe pour l'utilisateur PostgreSQL.
docker run -d --network my-app-network --name my-database -e POSTGRES_PASSWORD=mypassword postgres
Vous devriez voir l'ID du conteneur affiché, indiquant que le conteneur de base de données s'exécute en arrière-plan.
<container_id>
Imaginons maintenant que notre conteneur "application web" doive exécuter une commande interagissant avec la base de données, comme un script de migration. Normalement, si nous utilisions Docker Compose, nous pourrions exécuter une commande sur le service web et Docker Compose gérerait la configuration réseau et les liens.
En utilisant simplement docker run
, si nous lançons le conteneur d'application web et qu'il tente de se connecter à my-database
, il devra généralement être sur le même réseau.
Exécutons une commande dans un conteneur ubuntu
connecté au même réseau, simulant une commande qui pourrait interagir avec la base de données. Nous allons simplement essayer de pinger le conteneur de base de données par son nom (my-database
).
docker run --network my-app-network ubuntu ping -c 4 my-database
Cette commande va :
- Créer un nouveau conteneur à partir de l'image
ubuntu
- Le connecter au réseau
my-app-network
- Exécuter la commande
ping -c 4 my-database
dans le conteneur
Comme le conteneur ubuntu
est sur le même réseau que le conteneur my-database
, il peut résoudre le nom my-database
en l'adresse IP du conteneur de base de données et le pinger.
Vous devriez voir une sortie montrant les requêtes ping et les réponses :
PING my-database (172.18.0.2) 56(84) bytes of data.
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=1 ttl=64 time=0.050 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=2 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=3 ttl=64 time=0.054 ms
64 bytes from my-database.my-app-network (172.18.0.2): icmp_seq=4 ttl=64 time=0.054 ms
--- my-database ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3060ms
rtt min/avg/max/mdev = 0.050/0.053/0.054/0.001 ms
Ceci démontre que vous pouvez exécuter une commande ponctuelle dans un conteneur et lui faire interagir avec d'autres conteneurs sur le même réseau, sans avoir à démarrer le service par défaut du conteneur exécutant la commande (dans ce cas, le conteneur ubuntu
n'a pas de "service" typique). La clé est de connecter le conteneur exécutant la commande au même réseau que les services avec lesquels il doit interagir.
Enfin, nettoyons le conteneur de base de données en cours d'exécution et le réseau.
docker stop my-database
my-database
docker rm my-database
my-database
docker network rm my-app-network
my-app-network