Nouveau serveur et stack LAMP propulsée par Docker !

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.

docker.png
 

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 :

Architecture Docker
Architecture Docker

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.

Fil des commentaires de ce billet

2 réactions

  • De llaumgui De llaumgui - 01/09/2016, 15:10 #1

    Pour info, la doc de Docker dit que pour faire tourner OverlayFS il faut un kernel 3.18 minimum mais ça marche avec le 3.10 de RHEL7 (lsmomd retourne bien overlay) qui l'a en preview.

  • De Guillaume Kulakowski De Guillaume Kulakowski - 03/09/2016, 09:22 #2

    Pour information SPB est à présent sur le serveur ;-).

    Je me suis aussi rajouté un Gitlab.

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

Attribution - Partage dans les Mêmes Conditions 4.0 International