Afin de réduire les coûts d’hébergement de Scenario-PaintBall, site/forums qui partagent le même serveur que ce blog, nous avons étudié le remplacement de notre vieux Kimsufi 16G à 49€ TTC / mois. En effet, changer de serveur permet (presque) toujours d’avoir un serveur plus récent mais surtout tout aussi voir plus puissant que l’ancien et le tout pour moins cher. Après une rapide étude des solutions du marché, nous avons retenu une Dedibox XC 2016 à 19€20 TTC / mois.
Pour l’occasion j’en ai profité pour refondre complètement l’architecture d’hébergement :
- Utilisation de CentOS 7 à la place de RHEL 6. Pourquoi passer de Red Hat vers CentOS ? Car, bien qu’en tant que contributeur, j’ai toujours des licences gratuites, je dois les faire renouveler tous les ans et ça me prend du temps et de l’énergie… et je suis fainéant.
- Activation de SELinux ! Si j’ai déjà sauté le pas sur mes postes de travail (Fedora) depuis bien longtemps, l’ancien serveur était encore en mode désactivé ! Du coup je pourrais arborer fièrement le T-Shirt « setenforce 1 » et ainsi faire plaisir à Dan.
- Utilisation d’un cache HTTP : Varnish.
- Mise en place d’une stack LAMP full Docker !
Et c’est ce dernier point dont je vais discuter.
Description de la stack LAMP dockérisée
Choix du moteur de stockage
Concernant le choix du moteur de stockage, je ne suis pas parti sur le natif CentOS, à savoir Device Mapper, mais j’ai retenu OverlayFS. J’ai fais ce choix sur les conseils de ce tutoriel et aussi de cette page de la documentation de Docker mais surtout à la lecture de cette phrase :
Many people consider OverlayFS as the future of the Docker storage drive
Gestion de l’envoi des mails et impact sur le réseau
Premier choix qui peut être discuté, j’ai fait le choix de ne pas mettre de container pour envoyer les mails mais d’envoyer les mails directement depuis l’host. En effet, j’ai pour habitude de considérer qu’un serveur doit posséder un MTA, c’est d’ailleurs une recommandation du Red Hat LSB.
Ceci implique donc que j’ai une communication des containers vers l’host. Comme j’ai un firewall (FirewallD) et que je veux sécuriser les choses au maximum, ceci implique une interface de communication avec un nom fixe. C’est à dire que j’exploite l’interface docker0 et non une interface créée par Compose qui serait créé avec un nom imprédictible (brd-hashquelconque). Du coup pour ouvrir les ports :
# On associe l'interface docker0 à une zone de confiance :
firewall-cmd --permanent --zone=trusted --change-interface=docker0
# On ouvre le service pour cette zone
firewall-cmd --permanent --zone=trusted --add-service=smtp
# On recharge :
firewall-cmd --reload
Pour que Compose utilise le réseau par défaut de docker, appelée « bridge » et utilisant l’interface docker0, il suffit de rajouter la ligne suivante dans Compose :
network_mode: "bridge"
Architecture et typologie de containers
Pour le moment Scénario PaintBall et ce blog partagent les mêmes versions de PHP (5.6) et Apache (2.4). J’utilise donc les mêmes images mais chaque infrastructure possède son propre container apache ainsi que son propre container PHP(-FPM). Bien entendu, un container Varnish mutualisé est présent en amont afin de dispatcher les requêtes sur la bonnes stack mais également pour assurer un rôle de cache HTTP. Concernant la base de données, j’ai fait le choix (discutable là encore) d’utiliser le même container pour les 2 stacks, c’est quand même plus simple à administrer, optimiser, backuper, etc….
De plus, j’ai également fait le choix de ne pas porter les applications Web (IPB, Dotrclear, WordPress) au sein des containers mais au sein de volumes. Ceci me permet de pouvoir mettre à jour les applications directement depuis l’host. Ceci me permet également de faire la migration de serveur plus rapidement.
Schéma d’architecture
Dans un mode 100% Dockerisé, j’aurais 1 groupe de container (Apache, PHP, Memcached, MariaDB, etc…) par application. Dans ce même mode, Dotclear (pour prendre cet exemple), serait présent directement dans les containers PHP et Apache et seul le répertoire public serait un volume partagé. Mais ça me prendrait carrément plus de temps (recréation des containers à chaque mise à jour de Dotclear ou d’un plugin) et le ROI serait négatif car je n’ai pas plusieurs environnements (prod, préprod, etc…), on parle ici d’applications personnelles. Bref, voici à quoi ça ressemble :
Pour ce qui est des containers, j’ai fait un mix entre les containers officiels (MariaDB, Memcached) et des containers personnels (Apache 2.4, PHP 5.6).
Mon docker-compose.yml
Pour lancer mes containers, je suis fainéant, je passe par Compose. J’ai récupéré ma config perso, que j’ai un peu retravaillée :
version: '2'
services:
##################################################### Mutualized architecture
famas_varnish:
container_name: famas_varnish
image: million12/varnish
restart: always
mem_limit: 1g
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/volumes/famas/varnish/conf/default.vcl:/etc/varnish/default.vcl:ro
network_mode: "bridge"
ports:
- 80:80
links:
- llaumgui_httpd24:llaumgui
- spb_httpd24:spb
famas_mariadb10:
container_name: famas_mariadb10
image: mariadb:10
restart: always
mem_limit: 4g
env_file:
- .env
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/volumes/famas/mysql:/var/lib/mysql
network_mode: "bridge"
expose:
- 3306
######################################################### spb's architecture
spb_httpd24:
container_name: spb_httpd24
image: llaumgui/centos7-scl-httpd24
build:
context: build/httpd/2.4/
restart: always
mem_limit: 512m
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/volumes/www/spb:/var/www/spb
#- /docker/volumes/www/.htpasswd:/var/www/.htpasswd
#- /docker/volumes/www/challenges:/var/www/challenges
- /docker/volumes/spb/httpd24/conf/vhost.d:/etc/httpd/vhost.d:ro
- /docker/volumes/spb/httpd24/conf/ssl:/etc/httpd/ssl/:ro
- /docker/volumes/spb/httpd24/log/:/var/log/httpd24
network_mode: "bridge"
expose:
- 80
links:
- spb_php56:php
spb_php56:
container_name: spb_php56
image: llaumgui/centos7-scl-php56
build:
context: build/php-fpm/5.6/
restart: always
mem_limit: 2g
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/volumes/www/spb:/var/www/spb
- /docker/volumes/spb/php56/log:/var/log/php-fpm
network_mode: "bridge"
expose:
- 9000
links:
- famas_mariadb10:database
- spb_memcached:memcached
extra_hosts:
- "mail:172.17.0.1"
spb_memcached:
container_name: spb_memcached
image: memcached
mem_limit: 512m
volumes:
- /etc/localtime:/etc/localtime:ro
network_mode: "bridge"
expose:
- 1121
##################################################### llaumgui's architecture
llaumgui_httpd24:
container_name: llaumgui_httpd24
image: llaumgui/centos7-scl-httpd24
build:
context: build/httpd/2.4/
restart: always
mem_limit: 512m
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/volumes/www/llaumgui:/var/www/llaumgui
- /docker/volumes/www/.htpasswd:/var/www/.htpasswd
- /docker/volumes/www/challenges:/var/www/challenges
- /docker/volumes/llaumgui/httpd24/conf/vhost.d:/etc/httpd/vhost.d:ro
- /docker/volumes/llaumgui/httpd24/conf/ssl:/etc/httpd/ssl/:ro
- /docker/volumes/llaumgui/httpd24/log/:/var/log/httpd24
network_mode: "bridge"
ports:
#- 80:80
- 443:443
expose:
- 80
links:
- llaumgui_php56:php
- llaumgui_gitlab:gitlab
llaumgui_php56:
container_name: llaumgui_php56
image: llaumgui/centos7-scl-php56
build:
context: build/php-fpm/5.6/
restart: always
mem_limit: 512m
volumes:
- /etc/localtime:/etc/localtime:ro
- /docker/volumes/www/llaumgui:/var/www/llaumgui
- /docker/volumes/llaumgui/php56/log/:/var/log/php-fpm
network_mode: "bridge"
expose:
- 9000
links:
- famas_mariadb10:database
extra_hosts:
- "mail:172.17.0.1"
Conclusion
La nouvelle architecture est en cours de test sur le blog et si c’est positif SPB devrait bientôt nous rejoindre. J’ai également quelques pistes pour améliorer les performances :
- Réfléchir à l’utilisation d’1 container Postfix.
- Migrer le blog en PHP 7.
Docker pour ma stack LAMP - Guillaume Kulakowski's blog - Guillaume Kulakowski's blog le 30 août 2016
[…] déjà décrit ma précédente stack LAMP sous Docker, mais, à nouveau serveur, nouvelle architecture […]