Skip to content

Instantly share code, notes, and snippets.

@fvln
Last active April 20, 2019 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fvln/2dcac3823752884eedc164e37be986e8 to your computer and use it in GitHub Desktop.
Save fvln/2dcac3823752884eedc164e37be986e8 to your computer and use it in GitHub Desktop.
Conteneuriser Wordpress avec Docker

Ce fichier décrit la solution au TP Docker avancé, année scolaire 2018-19 Pôle sup de la salle - https://www.polesup-delasalle.fr/formations/nos-formations/securite-informatique-bac3/?parent=/formations-pole-sup-de-la-salle

Création de l'image Nginx

Dans un répertoire nommé bsi-nginx

On part de l'image debian stretch en version slim, dans laquelle on installe le paquet nginx :

FROM debian:stretch-slim

RUN apt update && apt install -y nginx

A ce stade, on peut déjà créer l'image et naviguer dedans grâce à un shell :

root@debian:/home/user/BSI/bsi-nginx# docker build -t bsi/nginx .
Sending build context to Docker daemon  7.168kB
Step 1/2 : FROM debian:stretch-slim
 ---> c08899734c03
Step 2/2 : RUN apt update && apt install -y nginx
 ---> Using cache
 ---> 5d2c1d83d9cd
Successfully built 5d2c1d83d9cd
Successfully tagged bsi/nginx:latest
root@debian:/home/user/BSI/bsi-nginx# docker run -it bsi/nginx
root@2b312cff4e13:/# ls -l /etc/nginx/sites-available/        
total 4
-rw-r--r-- 1 root root 2416 Nov  7 05:40 default
root@2b312cff4e13:/# exit
exit
root@debian:/home/user/BSI/bsi-nginx# 

On va extraire le fichier de configuration du site par défaut, et le modifier en dehors de l'image. Pour cela, il suffit de redémarrer un conteneur en lui imposant la commande cat /etc/nginx/sites-available/default. Ce conteneur se termine dès que la commande cat a fini de s'exécuter.

root@debian:/home/user/BSI/bsi-nginx# docker run -it bsi/nginx cat /etc/nginx/sites-available/default > server.conf
root@debian:/home/user/BSI/bsi-nginx# ls -l default 
-rw-r--r-- 1 root root 2507 avril 20 16:43 default

On le modifie de la manière suivante afin de servir :

  • le répertoire /var/www/html
  • en http et https
  • les scripts PHP étant exécutés sur le serveur fastCGI hébergé par localhost (que nous changerons plus tard), en écoute sur le port 9000.
server {
	listen 80 default_server;
	listen [::]:80 default_server;

	# SSL configuration
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;
	#
	# Self signed certs generated by the ssl-cert package
	# Don't use them in a production server!
	#
	include snippets/snakeoil.conf;

	root /var/www/html;

	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;

	server_name _;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		try_files $uri $uri/ =404;
	}

	# pass PHP scripts to FastCGI server
	location ~ \.php$ {
		include snippets/fastcgi-php.conf;
	#	# With php-cgi (or other tcp sockets):
		fastcgi_pass localhost:9000;
	}
}

On modifie alors le Dockerfile pour copier ce fichier lors du build de l'image, et exécuter nginx comme commande par défaut au démarrage du conteneur :

FROM debian:stretch-slim

RUN apt update && apt install -y nginx

RUN rm /etc/nginx/sites-enabled/default

COPY server.conf /etc/nginx/sites-available/server.conf
RUN ln -s /etc/nginx/sites-available/server.conf /etc/nginx/sites-enabled/server.conf

CMD nginx -g "daemon off; error_log stderr info;"

Après un nouveau build, on peut voir que nginx échoue à démarrer car les certificats ne sont pas créés (et le fichier de config nous expliquait bien qu'il utilisait les fichiers créés par le paquet ssl-cert) :

root@debian:/home/user/BSI/bsi-nginx# docker run -it -p 8000:80 bsi/nginx 
nginx: [emerg] BIO_new_file("/etc/ssl/certs/ssl-cert-snakeoil.pem") failed (SSL: error:02001002:system library:fopen:No such file or directory:fopen('/etc/ssl/certs/ssl-cert-snakeoil.pem','r') error:2006D080:BIO routines:BIO_new_file:no such file)

On adapte le Dockerfile pour ajouter le paquet manquant :

FROM debian:stretch-slim

RUN apt update && apt install -y nginx ssl-cert

RUN rm /etc/nginx/sites-enabled/default

COPY server.conf /etc/nginx/sites-available/server.conf
RUN ln -s /etc/nginx/sites-available/server.conf /etc/nginx/sites-enabled/server.conf

CMD nginx -g "daemon off; error_log stderr info;"

Après avoir relancé un conteneur avec la commande précédente, la page d'accueil de nginx s'affiche correctement lorsqu'on ouvre l'URL http://localhost:8000/ depuis l'hôte. L'image créée apparait dans la liste des images locales du système :

root@debian:/home/user/BSI/bsi-nginx# sudo docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
bsi/nginx           latest              65f34d00cc5c        2 hours ago         129MB

Ajoutons enfin à l'image un fichier de test permettant de tester la bonne exécution des scripts PHP :

FROM debian:stretch-slim

RUN apt update && apt install -y nginx ssl-cert

RUN rm /etc/nginx/sites-enabled/default

COPY server.conf /etc/nginx/sites-available/server.conf
RUN ln -s /etc/nginx/sites-available/server.conf /etc/nginx/sites-enabled/server.conf

RUN echo '<?php phpinfo(); ?>' > /var/www/html/phpinfo.php

CMD nginx -g "daemon off; error_log stderr info;"

Création de l'image PHP-FPM

Dans un répertoire nommé bsi-php

Le fichier Dockerfile suivant permet d'installer le paquet php-fpm et le module MySQL pour php. La commande sed permet de remplacer la directive de configuration :

listen = /run/php/php7.0-fpm.sock

par :

listen = 9000

dans le fichier de configuration /etc/php/7.0/fpm/pool.d/www.conf

FROM debian:stretch-slim

RUN apt update && apt install -y php-fpm php-mysql
RUN sed -i -e 's#listen = /run/php/php7.0-fpm.sock#listen = 9000#' /etc/php/7.0/fpm/pool.d/www.conf
RUN mkdir /run/php

RUN mkdir -p /var/www/html && echo '<?php phpinfo(); ?>' > /var/www/html/phpinfo.php

CMD /usr/sbin/php-fpm7.0 --nodaemonize

Enfin, la commande par défaut permet de démarrer le démon PHP-FPM lorsque le conteneur est créé.

Test de nginx avec PHP

Création d'un réseau interne

Par défaut, différents conteneurs Docker ne peuvent pas se joindre. Nous devons créer un réseau interne pour cela, ici nommé webserver :

root@debian:/home/user/BSI# docker network create webserver
cb2bdbee24279529f31c882b8959cda0c42fae9b0f2b88fa94c3093fba49b11b

Démarrons le conteneur PHP-FPM, connecté au réseau webserver :

root@debian:/home/user/BSI# docker run --network webserver --name php bsi/php

Ce conteneur porte le nom php, ce qui permet aux autre conteneurs accrochés au réseau webserver d'utiliser le serveur DNS interne de Docker pour résoudre son adresse IP. Par exemple ici en utilisant un conteneur debian:stretch :

user@debian:~$ sudo docker run --network webserver debian:stretch ping php
PING php (172.18.0.2) 56(84) bytes of data.
64 bytes from php.webserver (172.18.0.2): icmp_seq=1 ttl=64 time=0.153 ms
64 bytes from php.webserver (172.18.0.2): icmp_seq=2 ttl=64 time=0.254 ms
64 bytes from php.webserver (172.18.0.2): icmp_seq=3 ttl=64 time=0.195 ms
64 bytes from php.webserver (172.18.0.2): icmp_seq=4 ttl=64 time=0.299 ms
64 bytes from php.webserver (172.18.0.2): icmp_seq=5 ttl=64 time=0.178 ms
^C
--- php ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4078ms
rtt min/avg/max/mdev = 0.153/0.215/0.299/0.056 ms

Nous devons donc modifier le fichier bsi-nginx/server.conf pour modifier la direcctive fastcgi_pass ainsi, avant de recréer (docker build) l'image bsi/nginx :

fastcgi_pass php:9000;

Démarrons désormais le conteneur nginx :

root@debian:/home/user/BSI/bsi-nginx# docker run --network webserver -p 8000:80 bsi/nginx

L'URL http://localhost:8000/phpinfo.php affiche désormais le script phpinfo, ce qui permet de vérifier que nginx dialogue correctement avec le conteneur php-fpm.

Important

Lorsque nginx appelle FastCGI pour lui faire exécuter un script PHP, il lui fournit le chemin du script à exécuter, soit dans notre exemple précédent /var/www/html/phpinfo.php. Le conteneur qui exécute PHP-FPM doit donc posséder lui aussi ce script PHP dans son répertoire /var/www/html, sinon le démon PHP-FPM renverra lui-même une erreur HTTP 404.

Utilisation d'une image MariaDB

Pour simplifier cette étape, nous allons utiliser une image MariaDB toute faite, le meilleur choix étant l'image officielle : https://hub.docker.com/_/mariadb

Cette image requiert la variable d'environnement MYSQL_ROOT_PASSWORD pour démarrer, comme décrit dans l'exemple du Docker hub :

$ docker run --name some-mariadb -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mariadb

Démarrage conjoint de tous les conteneurs

Il faut commencer par télécharger le script Wordpress depuis la page https://fr.wordpress.org/download/, puis extraire ces fichiers dans le répertoire wordpress.

Démarrage de PHP-FPM

root@debian:/home/user/BSI/wordpress# docker run --network webserver --name php -v $(pwd)/wordpress:/var/www/html -it bsi/php 

Démarrage de MariaDB

Les varaibles d'environnement permettent de créer une base wordpress et un utilisateur au démarrage de la base de données :

root@debian:/home/user/BSI/bsi-nginx# docker run --name mariadb -e MYSQL_ROOT_PASSWORD=my-secret-pw -e MYSQL_DATABASE=wordpress -e MYSQL_USER=wordpress -e MYSQL_PASSWORD=wordpress --network webserver mariadb

Démarrage du serveur Nginx

root@debian:/home/user/BSI# docker run --network webserver -p 8000:80 -v $(pwd)/wordpress:/var/www/html bsi/nginx

En ouvrant la page http://localhost:8000 sur l'hôte, on peut désormais configurer Wordpress pour qu'il se connecte sur la base utilisant le hostname mariadb, avec l'identifiant wordpress, le mot de passe wordpress et la base wordpress.

Mais que se passe-t-il si un conteneur plante ? Si la base est arrêtée avec la commande docker stop mariadb ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment