Vous avez installé Docker à l'aide du précédent article et vous avez découvert comment lancer vos premiers conteneurs. Maintenant vous souhaitez sûrement passer à la vitesse supérieure. Le lancement de multiples conteneurs via docker run commence à vous poser quelques problèmes : La gestion des dépendances entre les conteneurs, les volumes, le réseau, etc peuvent devenir dans ces conditions un vrai casse tête.

Un outil pour les contrôler tous

docker-composeest un outil développé en python qui permet d’exécuter des applications multi-conteneurs. Grâce à lui, vous allez pouvoir configurer et démarrer les services de votre application au travers d'un seul et unique fichier.

Prenons l'exemple d'un site wordpress que vous souhaitez lancer sur votre machine. Celui-ci va se composer de 2 conteneurs distincts :

À l'aide d'un fichier YAML nous allons donc pouvoir lancer ces deux conteneurs et les lier.

Mais tout d'abord, installons docker-compose !

Installation

Si vous avez installé Docker sous Windows ou Mac, rien de compliqué puisque l'outil sera déjà présent.

Sous Linux, ce n'est guère plus compliqué :

sudo curl -L "https://github.com/docker/compose/releases/download/1.25.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

On lui donne le droit d'exécution :

sudo chmod +x /usr/local/bin/docker-compose

Pour vérifier que tout fonctionne :

$ sudo docker-compose --version
docker-compose version 1.25.3, build 1110ad01

Exemple

Par défaut, le fichier lu par docker-compose se nomme ... : docker-compose.yml

Dans ce fichier chaque conteneur ( appelé services ) est décrit avec l'ensemble des paramètres qui correspondent aux options que vous auriez pu exécuter avec la commande docker run : image, volume, réseau, etc.

Commençons par un fichier minimaliste :

version: "3.7"
services:

La déclaration de version permet de s'assurer que votre docker-compose et docker engine supporte les fonctionnalités de votre fichier. Ensuite nous déclarons les services ( conteneurs ) dont nous avons besoin :

version: "3.7"
services:
  mysql:
  
  wordpress:

Enfin paramétrons nos services :

version: "3.7"
services:
  mysql:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: myrootpass
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: myuserpass

  wordpress:
    image: wordpress:latest
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: myuser
      WORDPRESS_DB_NAME: mydatabase
      WORDPRESS_DB_PASSWORD: myuserpass
J'aurais bien sûr pu réaliser la même chose avec deux commandes docker run :
sudo docker run --name mysql -e MYSQL_ROOT_PASSWORD=myrootpass \
-e MYSQL_DATABASE=mydatabase -e MYSQL_USER=myuser \
-e MYSQL_PASSWORD=myuserpass -d mysql:5.7

sudo docker run --name mywordpress -e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_USER=myuser -e WORDPRESS_DB_PASSWORD=myuserpass \
-e WORDPRESS_DB_NAME=mydatabase -d wordpress:latest

Ok lançons une première fois notre application :

sudo docker-compose up 

Regardons plus en détail la sortie standard :

Creating network "XXXXXX" with the default driver

Nous n'avons pas déclarer de réseau pour notre application. De base, docker-compose va le créer afin d'isoler nos conteneurs. Je préfère de mon côté le déclarer de façon explicite dans le fichier de configuration afin de pouvoir gérer le nom manuellement. Vous pouvez utiliser ctrl+c sur la précédente commande afin d'arrêter les conteneurs pour éditer le fichier de configuration :

version: "3.7"
services:
  mysql:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: myrootpass
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: myuserpass
    networks:
      - lan

  wordpress:
    image: wordpress:latest
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: myuser
      WORDPRESS_DB_NAME: mydatabase
      WORDPRESS_DB_PASSWORD: myuserpass
    networks:
      - lan

networks:
  mylan:
    name: wordpress_lan

Voilà un fichier qui commence à avoir fier allure ! Que nous manque t-il pour terminer notre installation ?

  • L'accès "front" à WordPress,
  • La persistance des données.

J'aborderai de façon volontaire la persistance des données dans un prochain billet. Nous allons donc terminer aujourd'hui avec l'accès au front de WordPress.

Nous avons isolé nos conteneurs dans un réseau inaccessible depuis l'extérieur sur notre machine. Il faut donc créer un "tunnel" ( Désolé pour les lecteurs expérimentés : oui il s'agit bien d'un NAT, mais ce tutoriel s'adresse avant tout aux débutants ;) ) entre le monde extérieur et notre conteneur. Ce paramétrage va se faire au niveau de notre service "WordPress", qui de base souhaite communiquer sur le port 80 ( cf la documentation de l'image sur le Hub Docker ) :

version: "3.7"
services:
  mysql:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: myrootpass
      MYSQL_DATABASE: mydatabase
      MYSQL_USER: myuser
      MYSQL_PASSWORD: myuserpass
    networks:
      - lan

  wordpress:
    image: wordpress:latest
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: myuser
      WORDPRESS_DB_NAME: mydatabase
      WORDPRESS_DB_PASSWORD: myuserpass
    networks:
      - lan
    ports:
      - 8080:80

networks:
  mylan:
    name: wordpress_lan

Démarrons maintenant notre application :

sudo docker-compose up -d

Voilà notre site est maintenant accessible sur le lien suivant : http://host-ip:8080

Quelques commandes

Voici quelques commandes utiles pour utiliser docker-compose au quotidien :

docker-compose up : démarrer les services contenus dans notre fichier de configuration avec les logs en affichage sur la sortie standard.

docker-compose up -d: démarrer les services mais cette fois-ci en arrière plan.

docker-compose down: stopper les services et supprimer les réseaux déclarés dans le fichier de configuration.

docker-compose down -v: stopper les services, supprimer les réseaux ET les volumes déclarés dans le fichier de configuration.

docker-compose logs wordpress: afficher les logs du conteneur wordpress entre son démarrage et le lancement de cette commande.

docker-compose logs -f wordpress: afficher les logs du conteneur wordpress entre son démarrage et continuer l'affichage sur la sortie standard.

docker-compose logs --tail=X wordpress : afficher les X dernières lignes du log

On peut combiner -f et tail=X :

docker-compose logs -f --tail=5 wordpress

Il existe encore de multiples commandes :

docker-compose start wordpress: Démarrer uniquement le service WordPress de mon fichier de configuration

docker-compose stop wordpress: Arrêter uniquement le service WordPress

docker-compose restart wordpress : Redémarrer le service WordPress

Enfin lancer un shell sur un service en particulier :

docker-compose exec wordpress bash

Conclusion

docker compose est un outil puissant pour faciliter la gestion de vos applications nécessitant plusieurs conteneurs. Il va vous permettre d'organiser vos déploiements multi-conteneurs et en faciliter la maintenance !

Il reste encore de nombreuses choses à voir au sujet de cet outil ( construire son image à chaque démarrage, utilisation des secrets, de buildkit... ) mais nous verrons ça dans d'autres articles !