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

1
<?php
2
    echo "<h1>Dix commandes très utiles sur Ubuntu</h1></br>";
3
    echo "<ol>";
4
    $connexion = new PDO('pgsql:host=postgresql;port=5432;dbname=prism', 'snowden', 'nsa');
5
    $sql = 'SELECT * FROM commande';
6
    $results = $connexion->prepare($sql);
7
    $results->execute();
8
    while ($row = $results->fetch(PDO::FETCH_ASSOC)){
9
        echo "<li><b>" . $row['com'] . "</b> : ";
10
        echo $row['def'] . "</li>";
11
    }
12
    echo "</ol>";
13
?>

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

1
server{
2
        listen 80;
3
4
        server_name _;
5
        root /usr/share/nginx/html;
6
        index index.php index.html;
7
8
        location / {
9
                try_files $uri $uri/ =404;
10
        }
11
12
13
        location ~ \.php$ {
14
          try_files $uri =404;
15
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
16
          fastcgi_pass php:9000;
17
          fastcgi_index index.php;
18
          include fastcgi_params;
19
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
20
          fastcgi_param PATH_INFO $fastcgi_path_info;
21
        }
22
23
}

Solution

1
version: '3'
2
services:
3
  web:
4
    image: nginx:latest
5
    container_name: web
6
    ports:
7
        - "80:80"
8
    volumes:
9
        - ./html:/usr/share/nginx/html
10
        - ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
11
    networks:
12
      - backend
13
14
  php:
15
    image: pichouk/php
16
    container_name: php
17
    volumes:
18
        - ./html:/usr/share/nginx/html
19
    networks:
20
      - backend
21
22
  postgresql:
23
    image: postgres:10
24
    container_name: postgresql
25
    environment:
26
      POSTGRES_DB: prism
27
      POSTGRES_USER: snowden
28
      POSTGRES_PASSWORD: nsa
29
    volumes:
30
      - ./bdd/data1:/var/lib/postgresql/data
31
    networks:
32
      - backend
33
34
networks:
35
  backend:
36
    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

1
server {
2
	listen 80;
3
	server_name monsite1.fr;
4
	location / {
5
        proxy_pass http://web:80;
6
    }
7
}

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

1
version: '3'
2
services:
3
  proxy:
4
    image: nginx:latest
5
    container_name: proxy
6
    ports:
7
        - "80:80"
8
    volumes:
9
        - ./nginx/proxy.conf:/etc/nginx/conf.d/default.conf
10
    networks:
11
      - front
12
13
  web:
14
    image: nginx:latest
15
    container_name: web
16
    volumes:
17
        - ./html:/usr/share/nginx/html
18
        - ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
19
    networks:
20
      - front
21
      - backend
22
23
  php:
24
    image: pichouk/php
25
    container_name: php
26
    volumes:
27
        - ./html:/usr/share/nginx/html
28
    networks:
29
      - backend
30
31
  postgresql:
32
    image: postgres:10
33
    container_name: postgresql
34
    environment:
35
      POSTGRES_DB: prism
36
      POSTGRES_USER: snowden
37
      POSTGRES_PASSWORD: nsa
38
    volumes:
39
      - ./bdd/data1:/var/lib/postgresql/data
40
    networks:
41
      - backend
42
43
networks:
44
  front:
45
    external: true
46
  backend:
47
    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

1
<?php
2
    echo "<h1>Dix commandes très utiles sur Ubuntu v2</h1></br>";
3
    echo "<ol>";
4
    $connexion = new PDO('pgsql:host=postgresql2;port=5432;dbname=prism', 'snowden', 'nsa');
5
    $sql = 'SELECT * FROM commande';
6
    $results = $connexion->prepare($sql);
7
    $results->execute();
8
    while ($row = $results->fetch(PDO::FETCH_ASSOC)){
9
        echo "<li><b>" . $row['com'] . "</b> : ";
10
        echo $row['def'] . "</li>";
11
    }
12
    echo "</ol>";
13
?>

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

1
server{
2
        listen 80;
3
4
        server_name _;
5
        root /usr/share/nginx/html;
6
        index index.php index.html;
7
8
        location / {
9
                try_files $uri $uri/ =404;
10
        }
11
12
13
        location ~ \.php$ {
14
          try_files $uri =404;
15
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
16
          fastcgi_pass php2:9000;
17
          fastcgi_index index.php;
18
          include fastcgi_params;
19
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
20
          fastcgi_param PATH_INFO $fastcgi_path_info;
21
        }
22
23
}

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.

1
server {
2
	listen 80;
3
	server_name monsite1.fr;
4
	location / {
5
        proxy_pass http://web:80;
6
    }
7
}
8
server {
9
	listen 80;
10
	server_name monsite2.fr;
11
	location / {
12
        proxy_pass http://web2:80;
13
    }
14
}

Solution

1
version: '3'
2
services:
3
  proxy:
4
    image: nginx:latest
5
    container_name: proxy
6
    ports:
7
        - "80:80"
8
    volumes:
9
        - ./nginx/proxy.conf:/etc/nginx/conf.d/default.conf
10
    networks:
11
      - front
12
13
  web:
14
    image: nginx:latest
15
    container_name: web
16
    volumes:
17
        - ./html:/usr/share/nginx/html
18
        - ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
19
    networks:
20
      - front
21
      - backend
22
23
  php:
24
    image: pichouk/php
25
    container_name: php
26
    volumes:
27
        - ./html:/usr/share/nginx/html
28
    networks:
29
      - backend
30
31
  postgresql:
32
    image: postgres:10
33
    container_name: postgresql
34
    environment:
35
      POSTGRES_DB: prism
36
      POSTGRES_USER: snowden
37
      POSTGRES_PASSWORD: nsa
38
    volumes:
39
      - ./bdd/data1:/var/lib/postgresql/data
40
    networks:
41
      - backend
42
43
  web2:
44
    image: nginx:latest
45
    container_name: web2
46
    volumes:
47
        - ./html2:/usr/share/nginx/html
48
        - ./nginx/site2.conf:/etc/nginx/conf.d/default.conf
49
    networks:
50
      - front
51
      - backend2
52
53
  php2:
54
    image: pichouk/php
55
    container_name: php2
56
    volumes:
57
        - ./html2:/usr/share/nginx/html
58
    networks:
59
      - backend2
60
61
  postgresql2:
62
    image: postgres:10
63
    container_name: postgresql2
64
    environment:
65
      POSTGRES_DB: prism
66
      POSTGRES_USER: snowden
67
      POSTGRES_PASSWORD: nsa
68
    volumes:
69
      - ./bdd/data2:/var/lib/postgresql/data
70
    networks:
71
      - backend2
72
73
networks:
74
  front:
75
    external: true
76
  backend:
77
    external: true
78
  backend2:
79
    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

1
root@docker:~# tree -L 2
2
.
3
├── bdd
4
│   ├── data1
5
│   ├── data2
6
│   └── data3
7
├── docker-compose.yml
8
├── html
9
│   └── index.php
10
├── html2
11
│   └── index.php
12
├── html3
13
│   └── index.php
14
└── nginx
15
    ├── proxy.conf
16
    ├── site1.conf
17
    ├── site2.conf
18
    └── site3.conf
19
20
8 directories, 8 files

Les fichiers de configurations nginx

1
# proxy.conf
2
server {
3
    listen 80;
4
    server_name monsite1.fr;
5
    location / {
6
        proxy_pass http://web:80;
7
    }
8
}
9
server {
10
    listen 80;
11
    server_name monsite2.fr;
12
    location / {
13
        proxy_pass http://web2:80;
14
    }
15
}
16
server {
17
    listen 80;
18
    server_name monsite2.fr;
19
    location / {
20
        proxy_pass http://web3:80;
21
    }
22
}
1
# site1.conf
2
server{
3
        listen 80;
4
5
        server_name _;
6
        root /usr/share/nginx/html;
7
        index index.php index.html;
8
9
        location / {
10
                try_files $uri $uri/ =404;
11
        }
12
13
14
        location ~ \.php$ {
15
          try_files $uri =404;
16
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
17
          fastcgi_pass php:9000;
18
          fastcgi_index index.php;
19
          include fastcgi_params;
20
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
21
          fastcgi_param PATH_INFO $fastcgi_path_info;
22
        }
23
24
}
1
# site2.conf
2
server{
3
        listen 80;
4
5
        server_name _;
6
        root /usr/share/nginx/html;
7
        index index.php index.html;
8
9
        location / {
10
                try_files $uri $uri/ =404;
11
        }
12
13
14
        location ~ \.php$ {
15
          try_files $uri =404;
16
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
17
          fastcgi_pass php2:9000;
18
          fastcgi_index index.php;
19
          include fastcgi_params;
20
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
21
          fastcgi_param PATH_INFO $fastcgi_path_info;
22
        }
23
24
}
1
# site3.conf
2
server{
3
        listen 80;
4
5
        server_name _;
6
        root /usr/share/nginx/html;
7
        index index.php index.html;
8
9
        location / {
10
                try_files $uri $uri/ =404;
11
        }
12
13
14
        location ~ \.php$ {
15
          try_files $uri =404;
16
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
17
          fastcgi_pass php3:9000;
18
          fastcgi_index index.php;
19
          include fastcgi_params;
20
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
21
          fastcgi_param PATH_INFO $fastcgi_path_info;
22
        }
23
24
}

Ci-dessous le fichier docker-compose final :

1
version: '3'
2
services:
3
  proxy:
4
    image: nginx:latest
5
    container_name: proxy
6
    ports:
7
        - "80:80"
8
    volumes:
9
        - ./nginx/proxy.conf:/etc/nginx/conf.d/default.conf
10
    networks:
11
      - front
12
13
  web:
14
    image: nginx:latest
15
    container_name: web
16
    volumes:
17
        - ./html:/usr/share/nginx/html
18
        - ./nginx/site1.conf:/etc/nginx/conf.d/default.conf
19
    networks:
20
      - front
21
      - backend
22
23
  php:
24
    image: pichouk/php
25
    container_name: php
26
    volumes:
27
        - ./html:/usr/share/nginx/html
28
    networks:
29
      - backend
30
31
  postgresql:
32
    image: postgres:10
33
    container_name: postgresql
34
    environment:
35
      POSTGRES_DB: prism
36
      POSTGRES_USER: snowden
37
      POSTGRES_PASSWORD: nsa
38
    volumes:
39
      - ./bdd/data1:/var/lib/postgresql/data
40
    networks:
41
      - backend
42
43
  web2:
44
    image: nginx:latest
45
    container_name: web2
46
    volumes:
47
        - ./html2:/usr/share/nginx/html
48
        - ./nginx/site2.conf:/etc/nginx/conf.d/default.conf
49
    networks:
50
      - front
51
      - backend2
52
53
  php2:
54
    image: pichouk/php
55
    container_name: php2
56
    volumes:
57
        - ./html2:/usr/share/nginx/html
58
    networks:
59
      - backend2
60
61
  postgresql2:
62
    image: postgres:10
63
    container_name: postgresql2
64
    environment:
65
      POSTGRES_DB: prism
66
      POSTGRES_USER: snowden
67
      POSTGRES_PASSWORD: nsa
68
    volumes:
69
      - ./bdd/data2:/var/lib/postgresql/data
70
    networks:
71
      - backend2
72
73
  web3:
74
    image: nginx:latest
75
    container_name: web3
76
    volumes:
77
        - ./html3:/usr/share/nginx/html
78
        - ./nginx/site3.conf:/etc/nginx/conf.d/default.conf
79
    networks:
80
      - front
81
      - backend3
82
83
  php3:
84
    image: pichouk/php
85
    container_name: php3
86
    volumes:
87
        - ./html3:/usr/share/nginx/html
88
    networks:
89
      - backend3
90
91
  postgresql3:
92
    image: postgres:10
93
    container_name: postgresql3
94
    environment:
95
      POSTGRES_DB: prism
96
      POSTGRES_USER: snowden
97
      POSTGRES_PASSWORD: nsa
98
    volumes:
99
      - ./bdd/data3:/var/lib/postgresql/data
100
    networks:
101
      - backend3
102
103
networks:
104
  front:
105
    external: true
106
  backend:
107
    external: true
108
  backend2:
109
    external: true
110
  backend3:
111
    external: true