Multisite avec Docker 1.0
Nginx + PHP-FPM + Database multisite
L'objectif de cet exercice est de lancer 3 groupes de conteneurs contenant à la fois un reverse proxy Nginx, un conteneur en charge de l'interprétation des fichiers PHP et une base de données pour stocker des données.
Un reverse proxy sera également présent pour rediriger les conteneurs vers chacune des stacks.
Pour cela, nous allons utiliser un fichier docker-compose permettant de regrouper les différents sites.
Question
Créez un premier fichier docker-compose composé d'un conteneur Nginx, d'une base de données PostgresSQL et d'un conteneur PHP-FPM.
On utilisera respectivement les images docker nginx, postgres et pichouk/php (qui contient les bibliothèque php postgresql pour fonctionner avec la base de données).
Vous utiliserez des volumes pour monter les fichiers de configuration dans les conteneurs et pour partager les fichiers PHP entre le conteneur Nginx et le conteneur PHP-FPM.
Les conteneurs utiliseront un network appelé backend et le conteneur nginx exposera son port 80 sur le port 80 de votre hôte docker
Indice
Ci-dessous un example de fichier PHP appelant la base de données
./html/index.php
<?php
echo "<h1>Dix commandes très utiles sur Ubuntu</h1></br>";
echo "<ol>";
$connexion = new PDO('pgsql:host=postgresql;port=5432;dbname=prism', 'snowden', 'nsa');
$sql = 'SELECT * FROM commande';
$results = $connexion->prepare($sql);
$results->execute();
while ($row = $results->fetch(PDO::FETCH_ASSOC)){
echo "<li><b>" . $row['com'] . "</b> : ";
echo $row['def'] . "</li>";
}
echo "</ol>";
?>
Indice
Vous devez créer un fichier de configuration Nginx qui va lire un fichier d'index PHP et demander son traitement à votre conteneur PHP
./nginx/site1.conf
server{
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
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;
}
}
Solution
version: '3'
services:
web:
image: nginx:latest
container_name: web
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
- ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
networks:
- backend
php:
image: pichouk/php
container_name: php
volumes:
- ./html:/usr/share/nginx/html
networks:
- backend
postgresql:
image: postgres:10
container_name: postgresql
environment:
POSTGRES_DB: prism
POSTGRES_USER: snowden
POSTGRES_PASSWORD: nsa
volumes:
- ./bdd/data1:/var/lib/postgresql/data
networks:
- backend
networks:
backend:
external: true
Question
Nous allons maintenant passer par un conteneur nginx qui sera en charge de faire reverse proxy vers notre application. Celui-ci se trouvera dans un réseau appelé front
Indice
Là encore nous allons devoir monter un fichier de configuration pour nginx afin de lui indiquer vers quel conteneur il faut rediriger les requêtes provenant d'un nom de domaine.
L'idée est de rediriger toutes les requêtes provenant du nom de domaine monsite1.fr
vers notre conteneur appelé web
.
./nginx/proxy.conf
server {
listen 80;
server_name monsite1.fr;
location / {
proxy_pass http://web:80;
}
}
Indice
Le conteneur proxy doit se trouver dans les deux networks pour être en mesure de rediriger le trafic vers les conteneurs de notre application.
Notre conteneur Nginx applicatif n'a plus besoin d'exposer son port sur l'hôte Docker, c'est le reverse proxy qui va s'en charger.
Solution
version: '3'
services:
proxy:
image: nginx:latest
container_name: proxy
ports:
- "80:80"
volumes:
- ./nginx/proxy.conf:/etc/nginx/conf.d/default.conf
networks:
- front
web:
image: nginx:latest
container_name: web
volumes:
- ./html:/usr/share/nginx/html
- ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
networks:
- front
- backend
php:
image: pichouk/php
container_name: php
volumes:
- ./html:/usr/share/nginx/html
networks:
- backend
postgresql:
image: postgres:10
container_name: postgresql
environment:
POSTGRES_DB: prism
POSTGRES_USER: snowden
POSTGRES_PASSWORD: nsa
volumes:
- ./bdd/data1:/var/lib/postgresql/data
networks:
- backend
networks:
front:
external: true
backend:
external: true
Vous pouvez maintenant visiter le site correspondant à votre nom de domaine. Dans notre cas monsite1.fr et visualiser la même page web que précédemment
Question
Nous allons maintenant ajouter une seconde application. Celle-ci sera elle aussi composée d'un conteneur Nginx, d'un conteneur PHP-FPM et d'une base de données PostgreSQL indépendante.
Créez les fichiers de configuration correspondante et mettez à jour le docker-compose.yml pour prendre en compte ce nouveau site.
Indice
Les conteneurs de cette nouvelle application vont se trouver dans un network séparé de la première application qui sera appelé backend2
Indice
Notre fichier index.php a été mis à jour pour notre nouvelle application. On notera que l'URL de la base de données a été mise à jour pour utiliser une autre base de données que celle de notre première application.
./html2/index.php
echo "<h1>Dix commandes très utiles sur Ubuntu v2</h1></br>";
echo "<ol>";
$connexion = new PDO('pgsql:host=postgresql2;port=5432;dbname=prism', 'snowden', 'nsa');
$sql = 'SELECT * FROM commande';
$results = $connexion->prepare($sql);
$results->execute();
while ($row = $results->fetch(PDO::FETCH_ASSOC)){
echo "<li><b>" . $row['com'] . "</b> : ";
echo $row['def'] . "</li>";
}
echo "</ol>";
Indice
Vous devez créer un fichier de configuration Nginx qui va lire un fichier d'index PHP et demander son traitement à votre conteneur PHP. Cette fois-ci, nous allons changer de serveur PHP en modifiant la ligne fastcgi_pass
./nginx/site2.conf
server{
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php2:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Indice
Nous devons également ajouter une nouvelle entrée à notre reverse proxy. Les clients arrivant avec l'url http://monsite2.fr seront alors redirigés vers notre nouvelle application (hébergée dans le conteneur web2) tout en laissant la première application fonctionner normalement.
server {
listen 80;
server_name monsite1.fr;
location / {
proxy_pass http://web:80;
}
}
server {
listen 80;
server_name monsite2.fr;
location / {
proxy_pass http://web2:80;
}
}
Solution
version: '3'
services:
proxy:
image: nginx:latest
container_name: proxy
ports:
- "80:80"
volumes:
- ./nginx/proxy.conf:/etc/nginx/conf.d/default.conf
networks:
- front
web:
image: nginx:latest
container_name: web
volumes:
- ./html:/usr/share/nginx/html
- ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
networks:
- front
- backend
php:
image: pichouk/php
container_name: php
volumes:
- ./html:/usr/share/nginx/html
networks:
- backend
postgresql:
image: postgres:10
container_name: postgresql
environment:
POSTGRES_DB: prism
POSTGRES_USER: snowden
POSTGRES_PASSWORD: nsa
volumes:
- ./bdd/data1:/var/lib/postgresql/data
networks:
- backend
web2:
image: nginx:latest
container_name: web2
volumes:
- ./html2:/usr/share/nginx/html
- ./nginx/site2.conf:/etc/nginx/conf.d/default.conf
networks:
- front
- backend2
php2:
image: pichouk/php
container_name: php2
volumes:
- ./html2:/usr/share/nginx/html
networks:
- backend2
postgresql2:
image: postgres:10
container_name: postgresql2
environment:
POSTGRES_DB: prism
POSTGRES_USER: snowden
POSTGRES_PASSWORD: nsa
volumes:
- ./bdd/data2:/var/lib/postgresql/data
networks:
- backend2
networks:
front:
external: true
backend:
external: true
backend2:
external: true
Vous pouvez maintenant visiter votre nouvelle application. Dans notre cas, monsite2.fr
Question
De la même manière ajouter une troisième application composée d'un Nginx, d'un PHP-FPM et d'une base de données PostgreSQL.
N'oubliez pas de l'ajouter à votre reverse proxy.
Solution
Ci-dessous l'arborescence finale de notre projet
root@docker:~# tree -L 2
.
├── bdd
│ ├── data1
│ ├── data2
│ └── data3
├── docker-compose.yml
├── html
│ └── index.php
├── html2
│ └── index.php
├── html3
│ └── index.php
└── nginx
├── proxy.conf
├── site1.conf
├── site2.conf
└── site3.conf
8 directories, 8 files
Les fichiers de configurations nginx
# proxy.conf
server {
listen 80;
server_name monsite1.fr;
location / {
proxy_pass http://web:80;
}
}
server {
listen 80;
server_name monsite2.fr;
location / {
proxy_pass http://web2:80;
}
}
server {
listen 80;
server_name monsite2.fr;
location / {
proxy_pass http://web3:80;
}
}
# site1.conf
server{
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
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;
}
}
# site2.conf
server{
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php2:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
# site3.conf
server{
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.php index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass php3:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
Ci-dessous le fichier docker-compose final :
version: '3'
services:
proxy:
image: nginx:latest
container_name: proxy
ports:
- "80:80"
volumes:
- ./nginx/proxy.conf:/etc/nginx/conf.d/default.conf
networks:
- front
web:
image: nginx:latest
container_name: web
volumes:
- ./html:/usr/share/nginx/html
- ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
networks:
- front
- backend
php:
image: pichouk/php
container_name: php
volumes:
- ./html:/usr/share/nginx/html
networks:
- backend
postgresql:
image: postgres:10
container_name: postgresql
environment:
POSTGRES_DB: prism
POSTGRES_USER: snowden
POSTGRES_PASSWORD: nsa
volumes:
- ./bdd/data1:/var/lib/postgresql/data
networks:
- backend
web2:
image: nginx:latest
container_name: web2
volumes:
- ./html2:/usr/share/nginx/html
- ./nginx/site2.conf:/etc/nginx/conf.d/default.conf
networks:
- front
- backend2
php2:
image: pichouk/php
container_name: php2
volumes:
- ./html2:/usr/share/nginx/html
networks:
- backend2
postgresql2:
image: postgres:10
container_name: postgresql2
environment:
POSTGRES_DB: prism
POSTGRES_USER: snowden
POSTGRES_PASSWORD: nsa
volumes:
- ./bdd/data2:/var/lib/postgresql/data
networks:
- backend2
web3:
image: nginx:latest
container_name: web3
volumes:
- ./html3:/usr/share/nginx/html
- ./nginx/site3.conf:/etc/nginx/conf.d/default.conf
networks:
- front
- backend3
php3:
image: pichouk/php
container_name: php3
volumes:
- ./html3:/usr/share/nginx/html
networks:
- backend3
postgresql3:
image: postgres:10
container_name: postgresql3
environment:
POSTGRES_DB: prism
POSTGRES_USER: snowden
POSTGRES_PASSWORD: nsa
volumes:
- ./bdd/data3:/var/lib/postgresql/data
networks:
- backend3
networks:
front:
external: true
backend:
external: true
backend2:
external: true
backend3:
external: true