Lancer Nginx, PHP et Node.js avec un docker-compose.yml
À la fin de cette leçon vous saurez installer dans un serveur (ou en local) les outils Nginx, PHP et Node.js en passant par Docker.
Ci-dessous un schéma qui illustre comment les choses fonctionneront.
Il faut connaître le fonctionnement de Docker pour bien comprendre cette leçon. Si ce n’est pas le cas, vous pouvez passer par la formation Docker.
Préparer : site PHP et site Node.js
Au commencement de cet exercice, nous allons préparer le terrain. Nous n’allons donc pas pour le moment nous occuper de Docker.
Pour vous y retrouver et afin de bien organiser les choses, je vous invite à vous placer à un endroit au choix dans votre machine. Créez ensuite un dossier /exercice
.
mkdir exercice
Il contiendra tout notre projet.
Créez deux autres dossiers à l’intérieur de celui-ci que nous appellerons respectivement /php
et /nodejs
.
Ils comporteront nos deux sites internet.
cd exercice && mkdir php && mkdir nodejs
Nous rappelons que pour notre exercice, un site sera exécuté sous PHP et l’autre sous Node.js.
À ce stade, voici l’arborescence du projet.
Site internet avec PHP
Nous allons créer un site internet très simple, juste pour le test. Pour ce faire, plaçons-nous dans le dossier /php
. Nous allons créer le fichier index.php
.
cd php && touch index.php
On ouvre ce fichier avec notre éditeur de texte préféré, on y inscrit le code ci-dessous.
<?php
echo "Bonjour, je me sers de PHP.";
Nous allons maintenant tester si le site fonctionne.
Pour faire ce test, il faut que PHP soit installé au préalable sur notre machine locale, car nous allons utiliser la commande php
.
Pour lancer le site en PHP, tapez la commande qui suit. Attention, il faut que le port 8888 soit libre, sinon choisissez un autre port et adaptez les commandes qui suivront.
php -S "localhost:8888"
Ouvrez votre navigateur et tapez dans la barre d’adresse : http://localhost:8888.
Normalement, vous devriez tomber sur le même résultat que celui affiché.
C’est bon pour PHP 😃. Occupons-nous maintenant du site sous Node.js.
Site internet sous Node.js
Les choses se passent différemment sous Node.js.
On va aller dans notre dossier /nodejs
. Si vous êtes encore dans le dossier /php
, il faudra taper la commande suivante.
cd ../nodejs
Initialisons ce projet avec la commande npm init -y
. Un fichier package.json
sera généré.
On va maintenant installer le module express
.
npm install express
Après, nous allons créer un fichier server.js
.
touch server.js
Nous ouvrons ce fichier et l’on insère le code suivant.
const express = require('express');
const app = express();
app.get('/', function(req, res) {
res.send("Bonjour, j'utilise NODEJS.");
});
app.listen(8887);
On lance ensuite le serveur.
node server.js
Et l’on ouvre notre navigateur à l’adresse : http://localhost:8887.
Comme vous l’avez certainement deviné, pour tester notre site Node.js, il faut qu’il soit installé dans notre ordinateur, car nous utilisons la commande node
.
Deux sites prêts
À ce stade, nous avons deux sites internet. Un qui fonctionne sous PHP et l’autre sous Node.js.
Ils serviront pour tester lorsque nous les utiliserons avec Docker.
Car pour le moment ces sites jouent leur rôle, mais « à l’ancienne » et en local. Notre objectif dans cette leçon est de les déployer à partir d’un serveur web qui jouera le rôle de proxy inverse (Nginx) avec des conteneurs Docker.
C’est ce que nous verrons à partir de maintenant.
À l’heure actuelle, nous avons cette arborescence.
Préparer les images Docker
Nous utiliserons des images Docker pour :
- Nginx
- PHP
- Node.js
Pour bien organiser les choses, je vous invite à créer un dossier /images
dans le dossier exercice
.
mkdir images
Après, dans le dossier images
nous allons créer trois autres dossiers qui porteront les noms, nginx, php et node.
cd images && mkdir nginx php node
Dans chacun de ces trois dossiers, nous allons créer un fichier Dockerfile
.
Répéter la commande qui suit dans chacun des dossiers nginx, php et node.
touch Dockerfile
Maintenant, vous devriez avoir l’arborescence suivante.
Remplir les Dockerfiles
Nous utiliserons des images légères qui seront basées sur Alpine Linux.
① Dockerfile : Nginx
Nous remplirons le Dockerfile de Nginx avec le contenu suivant.
FROM nginx:1.19-alpine
RUN apk update && apk add nano bash
En plus de l’image Nginx, nous ajoutons une commande qui nous donnera la possibilité d’utiliser bash et Nano (un éditeur de texte). Ces outils nous seront utiles plus tard.
② Dockerfile : PHP
Pour celui de PHP, nous insérons le texte ci-dessous.
FROM php:7.4.16-fpm-alpine
Un Dockerfile très simple avec PHP-FPM.
③ Dockerfile : Node
FROM node:16.13.2-alpine
WORKDIR /www
EXPOSE 8887
CMD ["node", "server.js"]
Comme la manipulation d’un projet Node.js est différente d’un projet PHP, le Dockerfile contient d’autres informations.
Les instructions de cette image nous permettent de baser notre image sur une image Node.js, de nous positionner dans le dossier /www
et d'exécuter une commande qui nous permettra de lancer notre serveur Node.js.
Instructions du docker-compose.yml
Continuons 😌 ! Placez-vous dans le dossier /exercice
. Et tapez la commande ci-dessous pour créer notre fichier docker-compose.yml
.
touch docker-compose.yml
Ouvrez le fichier nouvellement créé avec un éditeur et commencez par le remplir avec les données suivantes.
version: '3'
services:
nginx:
build: images/nginx/
php:
build: images/php/
node:
build: images/node/
Nous avons ici trois services :
- nginx
- php
- node
Ils sont basés sur des images qui seront générées (ou construite) à partir de leur Dockerfile respectif.
Avant d’exécuter les instructions du docker-compose.yml
, nous allons y ajouter d’autres informations.
version: '3'
services:
nginx:
build: images/nginx/
php:
build: images/php/
node:
build: images/node/
# Volume managé ajouté
volumes:
nginx_conf:
Un volume managé a été créé. Il nous servira à garder en mémoire les fichiers de configuration de Nginx. Nous nous en servirons plus tard.
Continuons à ajouter des informations dans notre docker-compose.yml
.
version: '3'
services:
nginx:
build: images/nginx/
# Volumes ajoutés
volumes:
- nginx_conf:/etc/nginx/
- ./php:/www
php:
build: images/php/
# Volume ajouté
volumes:
- ./php:/www
node:
build: images/node/
# Volume ajouté
volumes:
- ./nodejs:/www
volumes:
nginx_conf:
Des volumes ont été ajoutés.
Dans le service Nginx, nous ajoutons le volume managé que nous avons créé au préalable pour le connecter au dossier de configuration de Nginx dans notre conteneur. Nous avons également mappé le dossier /php
qui contient notre site en PHP avec un dossier de notre conteneur : /www
.
Pour le service php
, nous avons aussi mappé le dossier /php
avec le dossier /www
de ce conteneur.
Et pour Node.js, c’est le dossier avec notre site en Node.js, /nodejs
qui a été connecté au dossier /www
de ce conteneur.
Noter qu’il n’est pas utile de mapper le site en Node.js dans notre conteneur nginx
, contrairement au dossier /php
. Pour la simple et bonne raison que PHP et Node.js ne seront pas gérés de la même façon par Nginx.
Mapper les ports dans le docker-compose.yml
Il nous faut ajouter encore une dernière chose dans notre docker-compose.yml. Cette ligne en plus consistera à mapper le port 80 de notre conteneur avec le port 80 de notre machine locale (ou celui de notre serveur physique).
version: '3'
services:
nginx:
build: images/nginx/
volumes:
- nginx_conf:/etc/nginx/
- ./php:/www
# Port ajouté
ports:
- "80:80"
php:
build: images/php/
volumes:
- ./php:/www
node:
build: images/node/
volumes:
- ./nodejs:/www
volumes:
nginx_conf:
Et voilà 🥵 ! Notre fichier docker-compose.yml
est prêt. Il ne nous reste plus qu’à le lancer et ensuite à configurer Nginx.
Lancer le docker-compose.yml
Pour exécuter notre fichier docker-compose.yml
, tapons la commande suivante (il faut se positionner dans le dossier /exercice
avant).
docker-compose up -d
Ensuite, dans un navigateur tapez http://localhost (ou http://localhost:80).
La belle page par défaut de Nginx apparaît 😎.
C’est très bien, mais ce qui nous serait utile c’est d’afficher nos sites personnels (en PHP et en Node.js).
Pour atteindre cet objectif, il faut modifier un fichier de configuration.
Modification du fichier de configuration du conteneur Nginx
Nous allons nous occuper du fichier de configuration de Nginx qui se trouve dans /etc/nginx/conf.d/default.conf
.
Pour ce faire, listons les conteneurs actifs.
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7019624db605 exercice_nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp exercice_nginx_1
a0e1e20760c3 exercice_node "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 8887/tcp exercice_node_1
b6c0b77080f9 exercice_php "docker-php-entrypoi…" 3 seconds ago Up 2 seconds 9000/tcp exercice_php_1
Nos trois conteneurs (basés sur trois images : Nginx, PHP et Node.js) apparaissent.
Nous allons entrer dans notre conteneur Nginx.
Bien entendu, les id des conteneurs qui apparaîtront dans votre machine ne seront pas comme les miens.
docker exec -it <id> bash
# Dans mon cas : docker exec -it 7019624db605 bash
Nous sommes maintenant dans notre conteneur Nginx et on va se diriger vers le dossier qui contient notre fichier de configuration.
cd /etc/nginx/conf.d/
On utilisera nano
qui est un éditeur de texte pour ouvrir notre fichier.
nano default.conf
Normalement, nano
devrait être présent dans Nginx, car nous avons paramétré notre image de telle sorte que cet éditeur soit présent. Si ce n’est pas le cas, vérifiez le Dockerfile de Nginx.
On tombe sur le fichier de configuration avec énormément d’informations 😳. L'objectif de cette leçon n'est pas d'expliquer comment fonctionne Nginx. Sinon elle serait encore plus longue qu'elle ne l’est actuellement.
Mais on va essayer de simplifier les choses et on n’entrera pas dans le détail du pourquoi du comment.
Fichier default.conf de Nginx
Notre fichier default.conf
étant ouvert, nous pouvons commencer à paramétrer Nginx.
Le mieux c'est de partir de zéro et de supprimer tout le contenu de notre default.conf
.
Rappelons ce que permet de faire ce fichier.
Nginx nous donne la possibilité de récupérer une requête pour ensuite l'orienter à un endroit bien précis. Et bien, default.conf
permet de savoir quoi faire selon le numéro du port ou le nom de domaine qui est utilisé.
Dans ce fichier, un bloc server
est utilisé pour expliquer chaque cas de figure. Et selon nos besoins, nous pouvons créer plusieurs blocs server
.
Remplir le default.conf pour le site PHP
On commence par notre premier server
qui concernera notre site PHP.
server {
# PHP
listen 80;
server_name localhost;
root /www;
index index.php;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Je ne vais pas tout expliquer. Mais je vais mettre en évidence certaines lignes qui sont importantes à comprendre.
-
listen 80;
: Nginx écoute sur le port 80 -
server_name localhost;
: Permet à Nginx de savoir quel est le nom de domaine qui doit pointer sur ce bloc -
root /www;
: Le dossier du conteneur avec le contenu de notre site -
fastcgi_pass php:9000;
: En vulgarisant, cette instruction permet de faire une relation avec le conteneur PHP que nous avons lancé en même temps que celui de Nginx (php
est le nom du service que nous avons choisi lorsque nous avons créé le docker-compose.yml et9000
le port de connexion).
On quitte l'éditeur nano
et on n’oublie pas de sauvegarder notre travail.
Pour quitter nano
, utilisez le raccourci clavier CTRL + X ou si celui-ci ne fonctionne pas, référez-vous aux indications en bas de l'éditeur.
On va maintenant relancer Nginx avec la commande ci-dessous.
/usr/sbin/nginx -s reload
Ensuite, on retourne dans notre navigateur et l’on tape http://localhost.
Et normalement, vous tombez sur la page suivante.
Si c'est le cas, cela signifie que tout a bien fonctionné 🤩. Notre site en PHP fonctionne et l’on passe bien par Nginx et des conteneurs Docker 👍 pour atteindre ce site.
Modifier le default.conf pour le site en Node.js
Nous allons maintenant nous attaquer au site Node.js 😑.
Il y a une différence entre PHP et Node.js dans la configuration du fichier default.conf
.
Cependant, nous ajouterons un bloc server
comme pour PHP. Ci-dessous le fichier avec le bloc server
pour PHP et celui de Node.js.
server {
# PHP
listen 80;
server_name localhost;
root /www;
index index.php;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
server {
# Node.js
listen 81;
server_name localhost;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://node:8887;
}
}
Nous allons expliquer quelques lignes.
-
listen 81;
: Cette fois-ci pour différencier notre site de PHP nous utiliserons un autre port, c'est-à-dire le n°81 -
proxy_pass http://node:8887;
:node
est le nom donné à notre service dans ledocker-compose.yml
pour le conteneur Node.js et8887
est le port choisi dans fichierserver.js
de Node.js.
On enregistre et l’on quitte nano
.
Et l’on relance Nginx.
/usr/sbin/nginx -s reload
Si dans mon navigateur je tape http://localhost (ou http://localhost:80), cela fonctionne bien pour le site en PHP. Mais si je tape http://localhost:81 pour afficher le site en Node.js, cela ne fonctionne pas et c'est normal 😡. Nous allons y remédier tout de suite.
Modifier le docker-compose.yml pour faire fonctionner le site en Node.js
Si vous connaissez bien le fonctionnement de Docker, vous avez peut-être compris pourquoi pour le moment le site en Node.js ne fonctionne pas.
Je vais vous montrer.
Sortons du conteneur Nginx en tapant exit
.
Vous êtes maintenant dans votre machine locale. Placez-vous dans le dossier /exercice
si vous ne l'êtes déjà pas.
Ouvrez le fichier docker-compose.yml
et observez le service nginx
de la sous-partie ports
.
Que constatons-nous 🤔 ?
Que le port 80 du conteneur a bien été mappé avec le port 80 de notre machine, mais pas le port 81.
Il faut donc ajouter la relation !
version: '3'
services:
nginx:
build: images/nginx/
volumes:
- nginx_conf:/etc/nginx/
- ./php:/www
ports:
- "80:80"
# Port 81 mappé
- "81:81"
php:
build: images/php/
volumes:
- ./php:/www
node:
build: images/node/
volumes:
- ./nodejs:/www
volumes:
nginx_conf:
Enregistrez votre docker-compose.yml
.
Retournez à votre terminal ou invite de commande.
Normalement, vous vous trouvez dans le dossier /exercice
et dans celui-ci, il y a le docker-compose.yml
que nous venons de modifier.
Tapez la commande suivante pour relancer les instructions du docker-compose.yml
.
docker-compose up -d
Et enfin 🥵, utilisez votre navigateur pour taper l'adresse http://localhost:81.
Et ça fonctionne bien, on voit notre site sous Node.js 🤩.
Vous pouvez également taper http://localhost:80 pour apercevoir notre site en PHP.