Niveau Niveau expert

Docker compose

Tutorieldéveloppement

Publié par le , mis à jour le (48353 lectures)

apache conteneur wordpress virtualisation docker

L'orchestre de vos conteneurs

Ce tuto est une suite à la première prise en main de Docker, qui met en place les notions d'image, de conteneur ainsi que les paramètres pour lancer un conteneur avec docker run...

Docker compose est une syntaxe plus évoluée qui va associer plusieurs conteneurs, ainsi que les paramètres déjà vus dans l'introduction à Docker, pour composer tout un système. Cela apporte cohérence et confort, modularité. Il sera aisé de manipuler plusieurs petits conteneurs plutôt qu'un seul grand "monolithique". L'invocation de tous les conteneurs se fera en une seule commande : docker compose up.

C'est le niveau pro-gamer qui demande d'avoir déjà compris les notions précédentes (ce qu'est une image, un conteneur, quels sont les paramètres principaux).

Docker compose

Comme bien souvent le plus simple pour cerner rapidement le sujet est de se baser sur un exemple concret, et de poursuivre sur notre environnement "LAMP" pour faire tourner WordPress en conservant les paramètres étudiés dans le tutoriel précédent.

Les ingrédients de la recette :

  • Un fichier docker-compose.yml qui va faire appel à
    • Des images prêtes à l'emploi
      • mariadb (ou mysql)
      • phpmyadmin
    • Un fichier Dockerfile pour construire une image sur-mesure
      • php-apache
      • Avec copie d'un fichier Docker-vhost.conf pour injection dans la configuration d'Apache

Visuellement, les conteneurs vont communiquer entre eux par le port 3306 pour accéder à mysql, et nous pourrons nous connecter directement en http sur le port 8080 pour phpmyadmin et 80 pour Apache. Chaque conteneur a son port d'écoute pour éviter les conflits.

Docker compose architecture

Docker-compose.yml

Le fichier docker-compose.yml au format YAML “décrit” tous les docker run possibles avec images, noms, volumes, liens, ports, variables d’environnements, réseaux... Il n'est dès lors plus nécessaire de mémoriser et introduire tous ces paramètres en ligne de commande : ils sont tous inventoriés en liste dans ce fichier unique. Si vous maîtrisez vos images, conteneurs et paramètres d'exécution, vous pouvez facilement rédiger ce fichier.

En reprenant les conteneurs abordés dans le tutoriel précédent, le fichier docker compose équivalent serait alors :

version: '3'

services:
  web:
    image: php7.4-apache:projet
    container_name: projet-php-apache
    ports:
      # local:container
      - "1337:80"
    environment: 
      - APACHE_DOCUMENT_ROOT=/var/www/html
      - COMPOSER_ALLOW_SUPERUSER=1
    volumes:
      # Volume stockant les fichiers web du projet
      - ./:/var/www/html
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      - db
    links:
      # Lien vers le conteneur "db" (déclaré ci-après)
      - db:db

  pma:
    image: phpmyadmin
    container_name: projet-phpmyadmin
    environment:
      # https://docs.phpmyadmin.net/en/latest/setup.html#docker-environment-variables
      PMA_HOST: db
      PMA_PORT: 3306
      UPLOAD_LIMIT: 1024M
    ports:
      - "8080:80"
    links:
      - db:db

  db:
    image: mariadb:latest
    container_name: projet-mysql
    ports:
      - "3306:3306"
    volumes:
      # Volume de la base de données
      - ./db-data:/var/lib/mysql
    environment:
      MYSQL_DATABASE: wordpress
      # MYSQL_ROOT_PASSWORD: XXXXXXXXX
      MYSQL_RANDOM_ROOT_PASSWORD: "yes"
      # MARIADB_RANDOM_ROOT_PASSWORD: "yes"

La nomenclature est extrêmement proche de ce qu'on utilise déjà dans les commandes docker run et très parlante.

  • image : image Docker à utiliser
  • container_name : nom du conteneur qui va apparaître dans la liste (plutôt que de générer un nom au hasard)
  • environment : variables d'environnement à passer au conteneur
  • ports : correspondance des ports ouverts ; il est recommandé de les entourer de quotes " sinon leur valeur pourrait être mal interprétée
  • volumes : volumes à créer entre la machine hôte et le conteneur
  • build : si l'image doit être construite à partir d'un fichier Dockerfile
  • depends_on : si le conteneur dépend d'un autre pour son exécution (ex : une base de données)
  • links : liens entre services (l'un "verra" l'autre dans son réseau avec son nom propre), on peut utiliser service:alias (ici db:db) ou juste service (ici db) puisqu'il s'agit du même nom

La variable d'environnement MYSQL_RANDOM_ROOT_PASSWORD à yes est très importante à noter ici : elle signifie que le serveur MySQL ou MariaDB ne sera pas configuré avec un mot de passe root spécifié dans le fichier, mais avec un mot de passe généré aléatoirement. Il va falloir aller le chercher dans les logs à la ligne GENERATED ROOT PASSWORD: XXXXXX. Notez-le précieusement, car il ne sera plus dévoilé par la suite.

Notez aussi le volume db-data qui fera correspondre les contenus de la base à un dossier local. Cela permettra - sans obligation - de "préserver" les tables sur la machine hôte plutôt que de les "perdre" dans le conteneur s'il se voit détruit.


Dockerfile

Il nous faut également le fichier Dockerfile associé (dans le même dossier) - voir le tutoriel précédent sur Docker pour les explications.

# PHP
FROM php:7.4-apache

# Modules apache
RUN a2enmod headers deflate expires rewrite
EXPOSE 80

# Composer
ENV COMPOSER_ALLOW_SUPERUSER=1
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# RUN composer --version

# Paquets nécessaires à l'installation de WordPress/WordPlate + utiles
RUN apt-get update && apt-get install -y zip unzip vim

# Extensions MySQL pour PHP/WordPress
RUN docker-php-ext-install mysqli pdo pdo_mysql

# Imagick pour WordPress (https://webapplicationconsultant.com/docker/how-to-install-imagick-in-php-docker/)
RUN apt-get install -y libmagickwand-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
RUN printf "\n" | pecl install imagick
RUN docker-php-ext-enable imagick

# Virtualhost
COPY Docker-vhost.conf /etc/apache2/sites-enabled/docker-vhost-wp.conf

# Redémarrage de Apache pour tenir compte des modifications + modules installés
RUN service apache2 restart

# Dossier de travail
WORKDIR /var/www/html/app

Docker-vhost.conf

Et pour finir, il nous faut le fichier Docker-vhost.conf pour Apache qui sera copié par la commande COPY du fichier Dockerfile. Celui-ci nous permet d'injecter dans la configuration du serveur web un Virtual Host faisant pointer le fameux "localhost" vers le dossier de travail /app de notre projet. Cela évite d'avoir à modifier la configuration d'Apache fournie qui pointe par défaut à la racine /var/www/html/.

<VirtualHost *:80>
  ServerName localhost
  ServerAdmin webmaster@localhost
  # Astuce permettant de lier n'importe quelle IP locale (ex : 127.0.0.1, 172.25.0.1 à ce vhost)
  # Pour que browsersync/webpack puissent fonctionner en proxy depuis l'hôte et qu'Apache y réponde
  ServerAlias *
  # Dossier racine web (à adapter selon les besoins, ajouter /public pour WordPlate)
  DocumentRoot /var/www/html/app
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
  <Directory "/var/www/html/app">
    # Permet l'usage de htaccess
    AllowOverride All
  </Directory>
</VirtualHost>

Docker compose up

👉 Une fois ces 3 fichiers prêts dans le même dossier, il suffira d'une seule commande pour construire le tout :

docker compose up -p monsuperprojet

⚠ Selon votre version de Docker et votre système, il faudra éventuellement utiliser la syntaxe docker-compose up et/ou l'installer comme décrit dans la documentation officielle : [https://docs.docker.com/compose/install/](Install Docker Compose).

En ajoutant -d on reprend la main immédiatement dans le shell (mode détaché). Si le nom n'est pas spécifié avec -p, alors le nom du dossier parent sera utilisé.

Résultat dans la liste des containers de Docker Desktop :

Docker compose up

Simple n'est-ce pas (après tout le reste...).

La structure de fichiers générée ressemblera à celle-ci :

Docker arborescence des fichiers

(Le fichier index.html n'est pas présent par défaut, vous pouvez en ajouter un vide pour faire des tests dans ce qui correspond à la racine du serveur web - DocumentRoot)

En profiter

Vous pouvez dès lors adopter 2 méthodes pour installer le CMS : classique et via composer.

WordPress classique

1️⃣ Soit télécharger WordPress, décompresser et copier les fichiers dans le volume établi (à savoir le dossier /app ici).

WordPlate via composer

2️⃣ Soit laisser composer opérer, car il a été prévu dans le fichier Dockerfile. En ouvrant un shell (CLI) dans le conteneur php-apache cela devrait vous mener directement dans /var/www/html/app puis il suffira d'exécuter :

composer create-project --prefer-dist wordplate/wordplate .

⚠ Attention : ne pas oublier le . final pour préciser que l'installation doit se faire dans le dossier courant.

Dans ce cas de figure avec WordPlate, il faudra :

  • modifier le chemin dans Docker-vhost.conf qui deviendra DocumentRoot /var/www/html/app/public et détruire (delete) + relancer (docker compose up) car la racine du site devient alors le dossier "public".
  • modifier le fichier d'environnement app/.env avec les bons paramètres :
DB_HOST=db
DB_NAME=wordplate
DB_USER=root
DB_PASSWORD=XXXXXXXXX
DB_TABLE_PREFIX=wp_

En passant, WordPlate est un wrapper construit autour de WordPress qui permet de le structurer plus proprement et d'utiliser un fichier .env, Laravel Mix pour compiler des fichiers CSS/JS avec webpack, WordPress Packagist pour gérer thèmes et plugins, etc.

Pour finir :

  • Vous connecter au conteneur du serveur web avec le navigateur (ici ce sera http://localhost:1337/) pour exécuter WordPress et les étapes d'installation, en spécifiant les mêmes identifiants de base de données.
  • Vous connecter à phpmyadmin s'il y a besoin (ici ce sera http://localhost:8080/) avec les identifiants root/le mot de passe root généré que vous avez noté avec soin bien sûr.

WordPress installation

✅ Le tour est joué. On peut réutiliser cette recette pour d'autres projets, ou déployer la même en production pour reproduire le même environnement. C'est très agréable plutôt que d'avoir à configurer manuellement ces serveurs et outils sur multiples environnements, avec des versions figées.

Autres commandes docker compose

Compose va permettre également de gérer les conteneurs de manière groupée après leur premier lancement :

  • docker compose stop : pour tout arrêter mais en conservant les conteneurs
  • docker compose start : pour tout (re)démarrer
  • docker compose down (inverse de "up") : pour arrêter et supprimer les conteneurs
  • docker compose rm : pour supprimer les conteneurs arrêtés (ATTENTION à ne pas perdre vos données stockées dans les conteneurs)
  • docker compose run : exécute une commande dans un service (penser à ajouter l'option --service-ports pour activer les ports)
  • ... et bien d'autres commandes utiles (restart, logs...) mentionnées par la documentation CLI Docker compose

Docker Desktop

Avec Docker Desktop, les manipulations sont facilitées, pour chaque conteneur un ensemble d'actions est proposé (start, stop, restart, delete) mais aussi...

L'ouverture dans le navigateur (protocole http) ; on peut également s'en sortir tout seul en observant le port qui est indiqué (visible avec docker container list)

Docker open in browser

L'ouverture d'un shell attaché au conteneur avec CLI, ce qui peut se révéler fort utile pour examiner ce qui s'y passe, changer temporairement la configuration, effectuer des manipulations variées en ligne de commande, lancer des tâches npm, composer, etc.

Docker CLI

Commentaires

Hello,

Je n'arrive pas à installer wp de façon classique (sans composer). Une fois les conteneurs lancés, je vais sur localhost, je tombe sur l'install de wp qui me demande l'identification de la bdd avec le host mais je n'arrive pas à aller plus loin. Il me dit "Erreur lors de la connexion à la base de données". Pourtant j'arrive à me connecter à phpmyadmin.

J'ai l'impression qu'il n'arrive pas à résoudre le host.

Une idée ?

Ah dans le champ "Adresse de la base de données", il faut mettre "db:3306" pour que ça fonctionne.

Quelqu'un a une explication ?

Merci Rodolphe pour ces tutos détaillés, très utiles, j'ai franchi un nouveau palier dans la compréhension de Docker.

Bonjour Radolf,

Tout d'abord merci pour ce tuto !

J'ai réussi à le faire marcher sur une VM ubuntu, par contre là j'essaie sur un Puppy. J'arrive à avoir phpMyAdmin, mais pas le WP sur le 1337...

J'ai ça :

Forbidden

You don't have permission to access this resource.

Apache/2.4.53 (Debian) Server at 127.0.0.1 Port 1337

Alors je ne sais pas si j'ai foiré l'install, ou bien c'est une question de config ou de droits...

Merci

@LastAchille : Ah c'est avec "docker-compose" sur puppy et "docker compose" sur ubuntu... peut-être que ça change des choses...

Commenter

Vous devez être inscrit et identifié pour utiliser cette fonction.

Connectez-vous (déjà inscrit)

Oubli de mot de passe ? Pas de panique, on va le retrouver

Pas encore inscrit ? C'est très simple et gratuit.