Page d'accueil Mes articles

Docker-compose pour faire communiquer nos conteneurs ( 1 / 2 )

Docker-compose est l'outil indispensable à partir du moment où l'on souhaite faire communiquer plusieurs conteneurs les uns avec les autres. Le but ici est de faire communiquer Nginx et php-fpm.

Publié en November 2021.
Dernière mise à jour February 2022.

Lorsque l'on va travailler avec Docker, on va essayer de donner des responsabilités limitées à chacun de nos conteneurs. Typiquement, si on souhaite mettre en place un site web sur Docker, on ne va pas imaginer un conteneur dans lequel on aurait à la fois nginx, php, mariadb... Mais plutôt trois conteneurs qui communiquent ensemble. Et pour cela, au lieu de créer nos conteneurs à la main avec la commande docker run, nous allons utiliser docker-compose.

Si vous êtes sur linux, vous aurez besoin d'installer Docker-Compose. Pour les utilisateurs Mac ou Windows, il est déjà inclût dans votre application Desktop.

Le principe de docker-compose, ça va être de décrire dans un fichier docker-compose.yaml les conteneurs que vous souhaitez avoir ainsi que leurs dépendances.

Si on reprend mon exemple, mon fichier docker-compose.yaml devrait ressembler à quelque chose comme ça

# docker-compose.yaml

# Je définis la version de mon docker-compose ( dernière version au moment où j'écris cet article )
version: '3.8'


services:
    db:
        # Ma première image, mariadb, pour ma base de données
        image: mariadb:10.5.6
        environment:
            # Vu que je suis en dev, je désactive le mot de passe pour plus de simplicité
            MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
        volumes:
            # J'ajoute le volume data sur mon système. En faisant ça, même si je supprime l'intégralité de mes conteneurs et volumes ( avec la commande docker system prune par exemple ), je ne perdrai pas mes données
            - ./data:/var/lib/mysql

    app:
        image: php:7.4.12-fpm-alpine
        depends_on:
            # Je définis une dépendance entre mes conteneurs. PHP a besoin de la base de donnée pour fonctionner
            - db
        volumes:
            # Grace à ce volume, mon conteneur pourra traiter mon code PHP présent dans mon répertoire
            - ./:/var/www/html/

    nginx:
        image: nginx:1.19.3-alpine
        depends_on:
            # Nginx a besoin de PHP pour fonctionner
            - app
        volumes:
            - ./:/usr/share/nginx/html
        ports:
            # Mon serveur web sera accessible sur le port 8080
            - 8080:80

En théorie, j'aimerai que ma stack ressemble à ça. Voyons voir un peu comment tout ça fonctionne.

Pour commencer, je vais créer un répertoire ma_stack dans lequel je vais mettre ce fichier docker-compose.yaml. Je vais également mettre un fichier index.html contenant un simple Hello World.

Ensuite, je démarre ma stack en tapant la commande suivante

❯ docker-compose up -d
Creating network "demo_docker_default" with the default driver
Creating demo_docker_db_1 ... done
Creating demo_docker_app_1 ... done
Creating demo_docker_nginx_1 ... done

Pour m'assurer que tous les conteneurs sont là, je vais lancer la commande suivante

❯ docker-compose ps
       Name                      Command               State          Ports        
-----------------------------------------------------------------------------------
demo_docker_app_1     docker-php-entrypoint php-fpm    Up      9000/tcp            
demo_docker_db_1      docker-entrypoint.sh mysqld      Up      3306/tcp            
demo_docker_nginx_1   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:8080->80/tcp

Je vois que mes trois conteneurs sont up et que seul nginx expose un port sur ma machine physique comme je lui avais demandé dans le docker-compose.yaml.

Si vous souhaitez voir les logs de l'un de ces conteneurs, il est possible d'utiliser la commande logs. Très pratique pour analyser et comprendre un problème.

❯ docker-compose logs -f nginx
Attaching to demo_docker_nginx_1
nginx_1  | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
nginx_1  | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
nginx_1  | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
nginx_1  | 10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf

Dans le répertoire ma_stack, vous devriez voir maintenant un nouveau répertoire data. Il s'agit des données de mariadb disponible sur notre machine physique grâce au montage de volume que nous avons fait dans notre fichier docker-compose.yaml.

Si vous vous rendez sur http://localhost:8080, vous devriez bien voir votre hello world qui correspond à votre fichier index.html.

Cela commence plutôt bien, mais ce qui m'intéresse avant tout c'est de faire communiquer ces trois conteneurs les uns avec les autres. Pour commencer, je vais me rendre dans mon conteneur nginx grâce à la commande exec pour voir si il a accès au conteneur app.

❯ docker-compose exec nginx sh 
/ # ping app
PING app (172.22.0.3): 56 data bytes
64 bytes from 172.22.0.3: seq=0 ttl=64 time=0.103 ms
64 bytes from 172.22.0.3: seq=1 ttl=64 time=0.149 ms
64 bytes from 172.22.0.3: seq=2 ttl=64 time=0.156 ms

C'est le cas ! Il répond bien au ping 😄 Vous pouvez essayer la même manipulation dans votre conteneur app en faisant un ping vers db, cela fonctionnera également.

Notre première mission, ça va être de faire en sorte que nginx fonctionne correctement avec php-fpm. On va modifier un peu notre docker-compose.yaml

...
    app:
        image: php:7.4.12-fpm-alpine
        depends_on:
            - db
        volumes:
            - ./:/srv/app

    nginx:
        image: nginx:1.19.3-alpine
        depends_on:
            - app
        volumes:
            - ./:/srv/app
            - ./docker/nginx/conf.d:/etc/nginx/conf.d
        ports:
            - 8080:80

Ce que j'ai modifié, ce sont seulement les volumes. Au lieu d'envoyer notre code dans le répertoire par défaut html, je décide de l'envoyer sur /srv/app. Le deuxième montage concerne la configuration de nginx ( /etc/nginx/conf.d ). Je vais donc créer le répertoire docker/nginx/conf.d dans lequel je vais mettre le fichier default.conf suivant

server {
    # Je définis la racine de nginx sur /srv/app ( qui correspond au volume sur lequel est mon projet )
    root /srv/app;
    # Le point d'entré, c'est index.php
    index index.php;

    location ~ \.php$ {
        try_files $uri =404;
        # On retrouve ici app qui correspond à notre conteneur php-fpm 
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME /srv/app$fastcgi_script_name;
        include fastcgi_params;
    }
}

Maintenant que l'on a fait ça, on va remplacer notre index.html par un index.php dans lequel on va mettre un simple echo 'Hello World';

On va pouvoir tester tout ça. Dans un premier temps, on va arrêter nos conteneurs et les détruire.

❯ docker-compose down
Stopping demo_docker_nginx_1 ... done
Stopping demo_docker_app_1   ... done
Stopping demo_docker_db_1    ... done
Removing demo_docker_nginx_1 ... done
Removing demo_docker_app_1   ... done
Removing demo_docker_db_1    ... done
Removing network demo_docker_default

Puis, on va redémarrer nos conteneurs avec la commande docker-compose up -d

Une fois que c'est fait, vous devriez voir à nouveau votre Hello World 😄 Pour être certain que notre conteneur app est bien sollicité, on va utiliser la commande suivante

❯ docker-compose logs -f app
Attaching to demo_docker_app_1
app_1    | [02-Nov-2020 14:25:18] NOTICE: fpm is running, pid 1
app_1    | [02-Nov-2020 14:25:18] NOTICE: ready to handle connections
app_1    | 192.168.48.4 -  02/Nov/2020:14:25:20 +0000 "GET /index.php" 200

Victoire ! 🎉 Pour le moment, j'ai donc un conteneur nginx capable de communiquer avec mon conteneur app. La prochaine étape va être de faire la connexion avec la base de données.

Cet article vous a été utile ? Faites le connaître sur les réseaux sociaux Twitter twitter LinkedIn linkedin

Un commentaire ?

codeur
Ou connectez-vous avec GitHub