Docker-compose – Introduction

12 février 2021

Allez hop, démarrons les services

Mise en situation

Lors des laboratoires précédents, nous avons démarré des conteneurs à partir de la ligne de commande, c-a-d, en utilisant le cli de docker.  Nous avons précédé ainsi car les paramètres de configuration étaient simples ou que le nombre de conteneurs pour une application donnée, était réduit.

Dans le cas d’une application multi-services nécessitant un nombre élevé de micro-services, de réseaux personnalisés ou de volumes persistants, l’approche de démarrage manuel de chacun des services  peut devenir une tâche ardue et complexe.

Pour adresser ce type de problème, docker propose le module ‘docker-compose‘.

En utilisant le langage de représentation des données YAML, il est possible de représenter tous les services et paramètre d’un système donné et de démarrer le tout, en une seule ligne commande.

Voici un tableau présentant les analogies entre l’utilisation du cli de docker et de docker-compose :

Par les exemples suivants, nous verrons comment ca fonctionne.


1 – Commençons par décrire un système simple, composé de trois conteneurs de type alpine.

Action 1.0 – Créer un système à partir de trois alpine

# Fichier:     docker-compose.yml
# Auteur:      Alain Boudreault
# Date:        2021.02.13 
# Description: Mise en place d'un système de 3 alpine

version: "3.9"
services:
  srv01:
    image: alpine
    container_name: serveur01 # Optionnel
 
  srv02:
    image: alpine
    container_name: serveur02 # Optionnel
 
  srv03:
    image: alpine
    container_name: serveur03  # Optionnel

Note:  Voici le tableau de  compatibilité des versions https://docs.docker.com/compose/compose-file/compose-file-v3/

Action 1.1 – Démarrer les services

docker-compose up                                 

Creating network "lab01-docker-compose_default" with the default driver
Pulling srv01 (alpine:)...
latest: Pulling from library/alpine
4c0d98bf9879: Pull complete
Digest: sha256:08d6ca16c60fe7490c03d10dc339d9fd8ea67c6466dea8d558526b1330a85930
Status: Downloaded newer image for alpine:latest
Creating serveur02 ... done
Creating serveur01 ... done
Creating serveur03 ... done
Attaching to serveur02, serveur01, serveur03
serveur02 exited with code 0
serveur01 exited with code 0
serveur03 exited with code 0

Observons les lignes sélectionnées.

Équivalent docker run:

docker create network lab01-docker-compose_default
docker run --name serveur01 --network lab01-docker-compose_default alpine
docker run --name serveur02 --network lab01-docker-compose_default alpine
docker run --name serveur03 --network lab01-docker-compose_default alpine

Action 1.2 – docker container ls (-a)

Action 1.3 – Réinitialiser docker:

docker container stop $(docker container ls -aq) 
docker system prune -af --volumes

Action 1.4 – Relancer les services en arrière plan, l’option -d

docker-compose up -d

NOTE: Les conteneurs seront arrêtés quand même.

Action 1.5 – attach et ping entre les services

docker attach serveur01

ping serveur02

CTRL+PQ

Action 2.0 – Ajout d’options supplémentaires – partie 01

Action 2.1 – Réinitialiser docker

Action 2.2 – Modifier le fichier docker-compose.yml pour y ajouter des options

version: "3.9"
services:
  srv01:
    image: alpine
    container_name: serveur01
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    networks: 
      - reseauAlpine
    environment:
      - JESUIS=Le spécialiste de la paresse
#    command: sh      
  srv02:
    image: alpine
    container_name: serveur02
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    networks: 
      - reseauAlpine    
    environment:
      - JESUIS=Celui qui fait du sur place
#    command: top      

networks:
  reseauAlpine:
    name: jeSuisLeReseauAlpine
    driver: bridge

Note: Pour les variables d’environnement, il est possible d’utiliser une des trois syntaxes suivantes:

Exemple 1:

environment:
  MYSQL_ROOT_PASSWORD: donttell. # des paires clef:valeur
  MYSQL_USER: Bob
_______________________________
Exemple 2:

environment:
  - MYSQL_ROOT_PASSWORD=donttell # un tableau de chaines sans ""

_______________________________
Exemple 3:

environment:
  - "MYSQL_ROOT_PASSWORD=donttell" # un tableau de chaines avec ""

Action 2.3 – Relancer les services en arrière plan, l’option -d

Action 2.4 – Explorer le résultat

Action 2.5 – Ajout d’options supplémentaires – partie 02

Action 2.5.1 – Alpine avec un volume, fichier ‘docker-comp01.yml

# Fichier: docker-comp01.yml
version: "3.9"
services:
  srv99:
    image: alpine
    container_name: serveur99

    stdin_open: true # docker run -i
    tty: true        # docker run -t

    volumes: 
    - ./:/420

Action 2.5.2 – Démarrer le système

docker-compose -f docker-comp01.yml up  -d

Action 2.5.3 – Connexion au service alpine

docker exec -it serveur99 /bin/sh

/ ls
/ ls /420
/ touch /420/note.txt

Action 2.6 – Configuration d’un service nginx

version: "3.9"

services:
  serveurweb:
    image: nginx
    container_name: serveurWEB

    volumes:
    - ./templates/site.template:/etc/nginx/templates
    - ./contenuweb:/usr/share/nginx/html:rw

    ports:
    - "8080:80"

    environment:
    - NGINX_HOST=monServeurWeb.com
    - NGINX_PORT=80  # N'est pas utilisée dans cet exemple

Référence nginx


3 – Mise en place d’une application multi-services

Action 3.1 – Renseigner le fichier docker-compose.yml suivant:

version: "3.9"
services:
  maBD:
    image: mariadb
    environment:
        - "MYSQL_ROOT_PASSWORD=root"  
  gestionBDviaAppWeb:
    image: adminer
    ports:
      - "8080:8080"
    depends_on:
      - maBD

Consolidation des exercices précédents

version: "3.9"
services:
  srv01:
    image: alpine
    hostname: serveur01
    container_name: serveur01
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    networks: 
      - reseauAlpine
    environment:
      - JESUIS=Le spécialiste de la paresse
#    command: sh      
  srv02:
    image: alpine
    container_name: serveur02
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    networks: 
      - reseauAlpine    
    environment:
      - JESUIS=Celui qui fait du sur place
    command: top      
  srv99:
    image: alpine
    container_name: serveur99
 
    stdin_open: true # docker run -i
    tty: true        # docker run -t
 
    volumes: 
    - ./:/420

  serveurweb:
    image: nginx
    container_name: serveurWEB
 
    volumes:
    - ./templates/site.template:/etc/nginx/templates
    - ./contenuweb:/usr/share/nginx/html:rw
 
    ports:
    - "8080:80"
 
    environment:
    - NGINX_HOST=monServeurWeb.com
    - NGINX_PORT=80  # N'est pas utilisée dans cet exemple

  maBD:
    image: mariadb
    networks: 
        - reseauAdminer   
    environment:
        - "MYSQL_ROOT_PASSWORD=root"  

  gestionBDviaAppWeb:
    image: adminer
    networks: 
        - reseauAdminer   
    ports:
      - "8081:8080"
    depends_on:
      - maBD

networks:
  reseauAlpine:
    name: jeSuisLeReseauAlpine
    driver: bridge
  reseauAdminer:  
    name: jeSuisLeReseauAdminer
    driver: bridge

4 – Laboratoire 1 

1 – Démarrer, à partir d’un fichier docker-compose, le système de micro-services suivants:

2 – Créer, à partir de phpmyadmin, la base de données ‘wordpress‘.

3 – Vérifier que la BD a été créée sur votre disque local.

Note:  Si le fichier n’est pas nommé docker-compose.yml alors il faut le nommer dans les commandes.

Par exemple,

docker-compose -f docker-labo02.yml up -d
docker-compose -f docker-labo02.yml ps
docker-compose -f docker-labo02.yml top
docker-compose -f docker-labo02.yml logs

# Note: Il faut utiliser le nom du service et non pas celui du conteneur.
docker-compose -f docker-labo02.yml exec cie_db bash

5 – Laboratoire 2

Mettre en place un site wordpress, en utilisant docker-compose, pour la CIE_ABC, en respectant le devis suivant:


6 – Quelques commandes utiles

Action – Valider le fichier: docker-compose config

Action – docker-compose up

Action – docker-compose up -d

docker-compose logs

docker-compose ps

docker-compose stop


7 – Exemple de docker-compose avec un ‘build’

Docker-compose permet la mise en place d’images personnalisées pendant le processus de démarrage d’une application multi-services.

Première étape, renseigner les directives de construction de l’image.

Action 7.1 – Enregistrer, dans un dossier vide, le fichier Dockerfile:

# ###########################################################################
# Fichier:      Dockerfile
# Auteur:       Alain Boudreault
# Date:         2021.03.05
# Description:  Exemple d'un Dockerfile avec,
#
#               1 - Des variables d'environnement,
#               2 - Un invite de commande personnalisé pour tous les 'users',
#               3 - Le démarrage automatique d'une application du conteneur.
# ###########################################################################

FROM debian
LABEL authors="Alain Boudreault <aboudrea@cstj.qc.ca>"
LABEL Atelier="7.1 de http://ve2cuy.com/420-4d4b/index.php/docker-compose-introduction-2/"
ENV UN_MOT_DE_PASSE=tepasserieux
ENV UNE_BASE_DE_DONNEES=db_de_la_ciex
# Definir des variables avec des séquences ANSI pour afficher de la couleur sous BASH
ENV RESET="\[\033[0m" \
    ROUGE="\[\033[0;31m" \
    VERT="\[\033[01;32m" \
    BLEU="\[\033[01;34m" \
    JAUNE="\[\033[0;33m"
# Sympathique petit (prompt) invite en couleur pour tous les utilisateurs    
RUN echo 'export PS1="${VERT}\D{%H:%M:%S} - ${JAUNE}\u@docker${ROUGE}\nDossier: [\W]\n${RESET}\$ "' \
     >> /etc/bash.bashrc    

RUN apt-get update
RUN apt-get install git lynx -y
# Lancer le fureteur au démarrage.  Tester avec http://lite.cnn.com/en
# CMD ["lynx", "http://lite.cnn.com/en"]

Action 7.1b – Bâtir l’image, pour un test intermédiaire.  

Note: Avec docker-compose, il n’est pas nécessaire de bâtir l’image au préalable.

docker build -t perso .

Action 7.2 – Afficher les informations de l’image

docker inspect perso

Note: Remarquer les propriétés AuthorEnv et Labels

"Author": "Alain Boudreault <aboudrea@cstj.qc.ca>",

"Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "UN_MOT_DE_PASSE=tepasserieux",
                "UNE_BASE_DE_DONNEES=db_de_la_ciex",
                "RESET=\\[\\033[0m",
                "ROUGE=\\[\\033[0;31m",
                "VERT=\\[\\033[01;32m",
                "BLEU=\\[\\033[01;34m",
                "JAUNE=\\[\\033[0;33m"
            ],

"Labels": {
                "Atelier": "7.1 de http://ve2cuy.com/420-4d4b/index.php/docker-compose-introduction-2/"
            }

Action 7.3 – Renseigner le fichier docker-compose suivant:

version: '3.3'
# docker-compose build
# docker-compose up --build -d
# OU
# docker-compose up -d

services:
   # Note: pas de caractères majuscules dans le nom du service
   mondebian:
    image: alainboudreault/serveur01  
    container_name: serveur01
    build: .
    restart: always
    stdin_open: true # docker run -i
    tty: true        # docker run -t
    environment:
      - VERSION=action7.1
    networks: 
      - reseau7.1          

   web:
    image: nginx:latest
    ports:
      - "8000:80"
    restart: always
    volumes:
      - ./web:/usr/share/nginx/html/perso
    networks: 
      - reseau7.1      

networks:
  reseau7.1:
    name: jeSuisLeReseau7.1
    driver: bridge

Action 7.4 – Tester l’image perso

docker-compose exec mondebian bash
# Note: pas de -it avec exec car le service roule déjà en mode -it
## Attention, il faut utiliser le nom du service dans les commandes
$ env

Action 7.5 – Arrêter les services et effacer les images et les conteneurs

docker-compose down --rmi all

8 – Laboratoire

Dans un dossier vide ‘labo-08’

Renseigner un fichier docker-compose qui:

Défi supplémentaire pour le service Ubuntu (facultatif):

Le nom de la branche ‘master‘ devrait apparaitre dans l’invite.


9 – Utilisation de variables dans docker-compose.yml

Action 9.1 – Le fichier .env

DB_PORT=3306
DB_ROOT_PASS=password
DB_USER=bob
DB_PASS=password

Action 9.2 –

services:
  db:
    image: mariadb:10.4.13
    ports:
      - ${DB_PORT}:3306
    volumes:
      - ./db_data:/var/lib/mysql
    tmpfs:
      - /tmp/mysql-tmp
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: "${DB_ROOT_PASS}"
      MYSQL_USER: "${DB_USER}"
      MYSQL_PASSWORD: "${DB_PASS}"

Note:  voir la directive depends_on


10 – Configuration avancée d’un nginx

fichier config.site

server {
    listen       ${PORT};
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}

fichier docker-compose.yml

web:
  image: nginx
  volumes:
   - ./site.template:/etc/nginx/conf.d/site.template
  ports:
   - "3000:8080"
  environment:
   - PORT=8080
  command: /bin/sh -c "envsubst < /etc/nginx/conf.d/site.template > /etc/nginx/conf.d/default.conf && exec nginx -g 'daemon off;'"

Docker-compose, les commandes

[wptb id=543]
Document rédigé par Alain Boudreault (c) 2021-23 – version 2023.02.15.01