Déployer un site wordpress
Oui c'est un sujet qui court les rues mais j'ai été obligé de suivre 25 tutoriels différents pour arriver à le faire fonctionner. Pourquoi ? Et bien tout simplement car je ne souhaite pas utiliser un hébergement OVH gratuit ou entrée de gamme, je veux la liberté de gestion et de sécurisation et surtout pouvoir facilement absorber les pics de charges.
Wordpress et Docker
Oui, nous allons utiliser Docker dans cette histoire. Cela va permettre de séparer les services, d'avoir une architecture applicative cohérente et de permettre des montées en charges si nécessaire !
Première chose à faire
Installer Docker.
Petit rappel, on part d'un VPS OVH ! Pour installer Docker sur un VPS, je vous renvoi à ce post ou tout y est décrit en détails !
Une fois Docker installé, il faut installer Docker-compose
qui permet de créer des applications multi-containers qui se géreront avec une ligne de commande unique (pratique pour éviter de lancer 20 docker container run
). Pour cela rien de plus simple :
- il faut passer en mode superutilisateur :
sudo -i
- un coup de mise à jour
apt-get update
- un coup de
apt-get install curl
(accepter les modifications qui seront ajoutées à l'OS) - et enfin la commande suivante :
curl -L https://github.com/docker/compose/releases/download/1.13.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
Pour finir, il faut mettre les bons attributs : sudo chmod +x /usr/local/bin/docker-compose
Et voilà, Docker-compose est installée :
root@serveur-2:~# docker-compose -v docker-compose version 1.13.0, build 1719ceb
Bien entendu, il faut que les ports 80 et 443 soient accessible de l'extérieur !!
Maintenant que c'est fait, parlons un peu de ce que nous voulons faire !
Architecture applicative
Vous avez ci-dessus, le schéma de ce que je souhaite avoir.
Mon VPS avec sa distribution Débian, le système de container Docker puis 3 containers (pour commancer) :
- un container pour la base de données (MariaDB)
- un container pour l'application (wordpress) avec le moteur php-fpm
- un container pour gérer les accès clients (Nginx)
Les fichiers seront sur des volumes locaux au VPS (pour le moment aussi).
Seul le container Nginx sera accessible de l'extérieur. Les communications MariaDB-Wordpress et Wordpress-Nginx se feront via un réseau interne mis en place par Docker.
Préparation
Pour arriver à cette architecture, il vaut mieux passer par plusieurs étapes pour bien comprendre ce qu'il se passe.
1ère étape : monter un couple de container Wordpress/MariaDB. Pour cela rien de plus simple un docker-compose.yml
comme celui-ci fait l'affaire :
version: '2' services: mariadb: image: mariadb:latest environment: - MYSQL_ROOT_PASSWORD=votre-mot-de-passe - MYSQL_DATABASE=wordpress wordpress: image: wordpress:latest links: - mariadb:mysql environment: - WORDPRESS_DB_PASSWORD=votre-mot-de-passe ports: - 80:80
Et vous n'avez plus qu'à lancer ces containers avec docker-compose up -d
vous obtenez alors les lignes suivantes lors d'un docker ps
:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9a1e0fef2489 wordpress:latest "docker-entrypoint..." 23 seconds ago Up 22 seconds 0.0.0.0:80->80/tcp demo_wordpress_1 ce8d51b52ddf mariadb:latest "docker-entrypoint..." 42 seconds ago Up 41 seconds 3306/tcp demo_mariadb_1
Vous noterez que les containers prennent un nom particulier : le nom du répertoire, suivi du nom du service défini dans le docker-compose.yml et un numéro (séparés par "_"). On remarque que le container demo_wordpress_1 expose le port 80 sur toutes les IP ! On obtient donc cela lorsque l'on accède à l'ip publique de notre VPS :
Nous n'avons pas spécifier de volumes sur nos containers donc les données ne seront pas persisté (à chaque arret via docker-compose down
et docker-compose up
il faudra réinstaller toutes les données de Wordpress).
Mode de fonctionnement
Le container wordpress (qui ici intègre le serveur web apache avec php 5.6 et wordpress 4.7.4) accède via le réseau interne au container mariadb sur le port 3306. Cette communication n'est pas accessible par un autre moyen qu'un container lié via la commande links
du fichier docker-compose.yml. Les variables d'environnements permettent d'échanger le mot de passe de la base de données. Si on veut mettre à jour php ou wordpress, ou même mariaDB, il suffit de faire :
docker-compose down
puisdocker-compose up -d
mais cela génère une coupuredocker-compose pull
puisdocker-compose up -d
et il n'y a pas de coupure !!
Génial donc, reste que les données ne sont pas persistées (enfin tant que l'on ne supprime pas les containers créés, via la commande docker-compose rm wordpress
ou docker-compose rm mariadb
).
Mise en conformité (données persistente)
Pour un environnement de production autant avoir nos données qui persistent sur le serveur ! C'est mieux !
Pour cela, nous modifions notre fichier docker-compose.yml
avec les instructions suivantes :
- volumes: - ./wp:/var/www/html
Pour le container wordpress et :
- volumes: - ./mariadb:/var/lib/mysql
Pour le container mariadb !
Ainsi nous aurons dans le répertoire courant deux répertoires (à créer au préalable) qui acceuilleront nos données. Nous pourrons y accéder hors des containers (cf. schéma en début de post).
Ajout de Nginx
Pour Nginx, c'est un peu plus compliqué car je souhaite que mon site soit en HTTPS. On ne badine pas avec la sécurité surtout en ce moment !! On commence par créer un répertoire etc
dans le répertoire courant pour accueillir nos certificats let's encrypt et on lance la commande suivante :
sudo docker run -it --rm -p 443:443 -p 80:80 --name letsencrypt \ -v "./etc/letsencrypt:/etc/letsencrypt" \ -v "/var/lib/letsencrypt:/var/lib/letsencrypt" \ quay.io/letsencrypt/letsencrypt:latest auth
Cela va executer un container qui va générer nos certificats. Il est nécessaire d'entrer une adresse mail (après avoir faire le choix 2 pour avoir un serveur web temporaire - pour la vérification du domaine faite par let's encrypt), le nom du domaine et voilà. Nos certificats sont générés.
Pour aller plus loin dans la sécurité, nous allons générés les paramètres Diffie-Hellman via la commande sudo openssl dhparam -out ./nginx/certs/dhparam.pem 4096
. Cela permet d'avoir une sécurité SSL forte.
C'est assez long, suivant la puissance CPU de votre VPS.
Pour ce qui est de la configuration de Nginx, je vous conseille la configuration trouvée sur le blog https://blog.ouvrard.it qui est sur le guist suivant : ici !
Elle est complète et il n'y a qu'à modifier les votre-domaine
par votre nom de domaine !
Maintenant, nous allons changer un peu notre container wordpress, pour utiliser non pas apache, car les fichiers statiques seront gérés par Nginx, mais php-fpm qui est un serveur dédier aux fichiers php et bien plus rapide qu'apache pour cette tâche.
Ne vous en faites pas, grâce à docker c'est assez simple, il suffit de modifier la ligne suivante de notre fichier docker-compose.yml
:
image: wordpress:lastest
par
image: wordpress:4.7.4-php7.0-fpm
Attention aussi à la directive fastcgi_pass wp_db:9000;
du fichier nginx.conf qui doit être changée pour le nom de votre service utilisant l'image wordpress-fpm. Elle devient dans notre cas fastcgi_pass wordpress:9000;
.
Cela nous donne donc le fichier docker-compose.yml
suivant :
version: '2' services: wordpress: image: wordpress:4.7.4-php7.0-fpm links: - mysql volumes: - ./wp:/var/www/html environment: WORDPRESS_DB_NAME: wordpress_db WORDPRESS_DB_PASSWORD: password mysql: image: mariadb restart: always volumes: - /var/mysql:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: password wp_web: image: nginx:latest restart: always ports: - 80:80 - 443:443 links: - wordpress volumes: - ./wp:/var/www/html - ./etc/nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./var/log/nginx:/var/log/nginx - ./etc/letsencrypt:/etc/letsencrypt - ./etc/nginx/certs/dhparam.pem:/etc/nginx/certs/dhparam.pem:ro
Voilà nous avons terminé, il ne reste plus qu'à faire un docker-compose up -d
(le -d permet de lancer les containers en arrière plan). Si vous lancez les containers sans cette option, vous aurez l'affichage des logs en permanent sur le terminal. Autant éviter cela pour passer d'autres commandes en cas de maintenance !
Avec le docker container ps
nous avons donc les containers suivants :
debian@serveur-1:~/demo$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3b7dc6e62b75 nginx:latest "nginx -g 'daemon ..." 2 hours ago Up 2 hours 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp debian_wp_web_1 6c4b1b78220f wordpress:4.7.4-php7.0-fpm "docker-entrypoint..." 2 hours ago Up 2 hours 9000/tcp debian_wordpress_1 98bc586eb4fb mariadb "docker-entrypoint..." 2 hours ago Up 2 hours 3306/tcp debian_mysql_1
A noter que si un se coupe (mariadb par exemple), il sera automatiquement redémarré, idem pour nginx grâce aux directives restart: always
.
Aller plus loin
Pour aller plus loin, un plugin wordpress est à installer : all in one WP migration
qui permet de faire une sauvegarde de toutes les données de votre site. Avec ce plugin et votre docker-compose.yml
votre site peut redémarrer de n'importe ou en quelques secondes (modulo le temps d'upload de la sauvegarde).
Si on test le fonctionnement on s'apppersoit que le serveur répond extrèmement vite (10000 requête avec une concurrence de 1000) :
Requests per second: 1929.76 [#/sec] (mean) Time per request: 518.200 [ms] (mean) Time per request: 0.518 [ms] (mean, across all concurrent requests)
contre
rien, apr_socket_recv: Connection reset by peer (104) impossible de traiter autant de connexion, j'ai donc baisser à 1000 requêtes
Autant dire que j'ai fait un déni de service sur mon second site disposant d'une configuration standard (pour le moment) !!
Requests per second: 230.53 [#/sec] (mean) Time per request: 433.792 [ms] (mean) Time per request: 4.338 [ms] (mean, across all concurrent requests)
Pour un site avec une configuration standard (apache/php/mariadb) !
De même la qualité SSL est au RDV et le resultat de SSL Server Test :
Un sans fautes !!
Encore plus loin
L'autre avantage avec docker est la possiblité d'augmenter le nombre de serveur en fonction de la charge. Il sera maintenant facile de basculer à 2 serveurs wordpress pour gérer les requêtes plus rapidement. Pour cela, docker-compose scale wordpress=2
et le tour est joué ! Bon il faut modifier la configuration nginx pour prendre en compte cela mais je prépare un prochain article sur l'augmentation des performances d'ici peu.
Nous verrons aussi comment gérer un cluster d'hôtes swam
pour avoir plusieurs VPS gérant la charge.
Le monitoring
Avant de nous quitter, on va parler de monitoring. Il existe de nombreuses solutions mais la plus élégante à mon gout est portainer. Simple à installer, il suffit de lancer la ligne de commande suivante : docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
et d'ouvrir le port 9000. Vous arrivez sur une page vous demandant un mot de passe administrateur, puis choisissez le premier choix (gérer l'hôte sur lequel s'execute portainer) et vous avez accès à un dashboard complet de votre système de container :
Avec un monitoring au container (ici nginx lors du test de charge) :
Autant dire qu'il reste de la marge avant d'augmenter la resistance à la charge car 30% en pic pour gérer 10000 requêtes, c'est assez light !
Voilà, à très bientôt pour la version cluster swarm de ce déployement !
Je me suis basé sur les sites suivants pour élaborer ce post :
- https://blog.ouvrard.it/2016/02/22/migrer-mon-wordpress-vers-docker/
- https://hub.docker.com/r/cowfox/docker-wordpress-nginx-fpm-cache-ssl/
- https://banck.net/2015/08/dockerize-and-secure-wordpress/
- https://ejosh.co/de/2015/08/wordpress-and-docker-the-correct-way/
- https://www.nicolashug.com/developpement/docker/docker-proxy-nginx-lets-encrypt-wordpress-rancher-win
- http://www.securityandit.com/network/wordpress-with-nginx-ssl-offloading/
- https://blog.virtualzone.de/2016/08/howto-https-ssl-wordpress-behind-proxy-nginx-haproxy-apache-lighttpd.html
- https://hungred.com/how-to/docker-mariadb-mysql-php-fpm-nginx-reverse-proxy-nginx-wordpress-phpmyadmin-setup/
- http://geekyplatypus.com/tag/docker-compose/
A+
Tony B.