Varnish, NGinx et PHP-FPM sous Docker

Date: 8/10/2014 | Catégories: Blog,Open-source,Systeme,vitualisation | Tags: ,,,,,,,

Suite au précédent article d'introduction sur Docker (que je vous conseille de lire avant de dévorer cet article), je me suis penché sur le problème suivant: comment créer et maintenir une "stack web" de compétition (Varnish + Nginx + PHP-FPM) basée sur cette technologie de virtualisation par conteneurs.

Quel est l'objectif ?

Nous allons donc, dans ce billet, détailler l'installation et la mise à jour d'une infrastructure, basée sur Docker, qui pourra servir à l'hébergement d'un site personnel, d'un blog ou bien du site d'une PME:

  • la base de donnée sera portée par l'implémentation libre de MySQL, c'est à dire MariaDB (nous aborderons cette partie dans un deuxième billet)
  • pour le moteur PHP, j'utilise PHP-FPM
  • pour le serveur Web, je ne jure que par Nginx (léger, bien documenté)
  • afin pour tenir la charge (notamment si vous utilisé un moteur de blog de type WordPress, j'utilise le système de cache Varnish)LEMP (Docker)

Dans le reste de de l'article, on appellera machine hôte, la machine qui hébergera Docker (lire ce billet pour la procédure d'installation de Docker).

Cette dernière peut être un PC portable ou bien un serveur dédié. C'est un des avantages de la virtualisation par conteneurs. Une fois validé sur une machine , on est sûr que le conteneur fonctionnera de manière identique sur une autre installation de Docker. Ainsi pour la rédaction de ce billet, j'ai utiisé mon PC portable sous Ubuntu 14.04 et un (superbe) VPS mis à disposition par les amis de Web4All sous Debian 7 (merci Aurélien !).

Pour respecter la philosophie de la virtualisation par conteneur, chaque brique sera mise dans un conteneur dédié. On aura ainsi 4 conteneurs sur une machine hôte.

Chaque conteneur communiquera avec les autres selon le schéma ci-dessus.

Les données (data base DB, page statique du site et cache) seront stockées sur la machine hôte.

Création des conteneurs

Il y a deux méthodes pour choisie les images qui seront à la base de nos conteneurs.

La première, la plus noble mais la plus longue à mettre en œuvre, est d'écrire soit même les DockersFiles permettant l'installation et l'exécution des logiciels. On garde ainsi le contrôle de notre infrastructure et la possibilité de configurer finement les applications (notamment au niveau des options de compilation). Dans ce cas, et pour respecter les "best practices" de Docker, il faudra, pour chaque conteneur, repartir d'une image de base de type Debian sur laquelle on viendra installer les briques logicielles de notre LEMP.

La seconde, que j'ai choisi dans ce billet (pas parce-que je suis un gros fainéant mais par manque de temps), est de partir des images disponibles sur la registry officielle de Docker. On gagne ainsi en rapidité de mise en place.  Les composants de notre web stack étant très populaires, on trouve des images supportées et maintenues par la communauté Docker (notamment NGinx). Cependant, on constatera une trop grande diversité dans les systèmes de bases (Ubuntu, CentOS...).

Avant de commencer, nous allons créer un répertoire sur la machine hôte qui hébergera les fichiers utiles à notre infrastructure:

Le conteneur NGinx

Pierre angulaire de notre "web stack", le serveur NGinx est très présent sur la "registry" officielle de Docker (plus de 900 images disponibles au moment de l'écriture de ce billet). J'ai choisi d'utiliser l'image officielle proposé par Docker (elle est conçue à partir de cete DockerFile).

On commence par télécharger les images NGinx officielle:

Puis on vérifie que les images sont visibles sur notre machine hôte (NGinx version 1.7.5 au moment de l'écriture de cet article):

On lance le conteneur:

Notre conteneur a le doux nom de webstack_nginx_1, il redirige le port TCP/8080 de notre hôte vers le port TCP/80 du conteneur (port par défaut de NGinx) et il assigne, en lecture seule, le volume /usr/share/nginx/html au répertoire hôte $HOME/data/www (à adapter à votre configuration). Pour résumer, toutes les pages HTML disponible dans le répertoire /home/nicolargo/data/www, seront accessible via le port HTTP/8080 de votre machine locale.

On ajoute une page HTML statique de test et une autre pour le test PHP que l'on utilisera dans le chapitre suivant:

Puis on valide que le serveur NGinx est bien opérationnel:

Ou directement depuis votre navigateur Web préféré:

Sélection_245L'image NGinx utilisée redirige les fichiers de log (access.log et error.log vert la sortie standard). Il est donc possible de visualiser les accès à son serveur Web en "attachant" le terminal de notre hôte à la sortie standard du conteneur:

Note: bien penser à mettre l'option --sig-proxy=true sous peine de stopper le conteneur lors de l'appuie sur ^C. Je vous conseille  de créer un alias dans votre shell.

Le conteneur PHP-FPM

Pour le moteur PHP, il n'existe pas d'image officielle. Mon choix s'est donc porté vers l'utilisation du repository de Jprjr basée sur une installation de PHP-FPM sous ArchLinux avec pas mal d'extensions par défaut (voir la liste dans le DockerFile).

On télécharge la dernière version des images avec:

On obtient bien:

On lance le conteneur:

Le conteneur est configuré par défaut pour écouter sur le port TCP/9000.

Très bien, on doit donc avoir le serveur NGinx et le moteur PHP-FPM qui sont lancés dans deux conteneurs différents. On va vérifier cela avec la commande:

Faire communiquer les deux conteneurs (NGinx & PHP-FPM)

Tout cela est très beau mais les deux conteneurs ne se connaissent pas. Il faut, pour cela, configurer le serveur NGinx pour utiliser le moteur PHP et donc que le conteneur NGinx connaisse l'adresse IP du conteneur PHP-FPM.

Heureusement, Docker propose l'option --link permettant de répondre à ce besoin. Cette option, à utiliser au moment du lancement du conteneur, va créer dynamiquement des entrées dans le fichier host et dans des variables d'environnement du conteneur, permettant ainsi à ce dernier de connaître comment joindre ses congénères.

Par exemple:

Maintenant que l'on sait comment faire communiquer les deux conteneurs, il suffit de configurer NGinx pour rediriger les fichier .PHP vers le moteur PHP-FPM du second conteneur.

Pour cela, plusieurs solutions sont là encore possibles. La plus simple est de surcharger la configuration NGinx par défaut(nginx.conf). Sur notre hôte, nous allons créer le fichier de configuration en question:

Note:

  • "fastcgi_pass webstack_php:9000;" qui utilise donc le hostname présent dans le fichier host
  • "fastcgi_param   SCRIPT_FILENAME    /srv/http$fastcgi_script_name;" qui va permettre à PHP-FPM d'aller chercher les pages PHP dans le même volume que le serveur Nginx mais assigné au répertoire /srv/http du conteneur (c'est la configuration par défaut de notre conteneur PHP-FPM)

Revenons à notre cas. Nous souhaitons que le conteneur NGinx (nommé webstack_nginx_01) connaisse le conteneur PHP (webstack_php_01).

On commence donc par supprimer les deux conteneurs existant:

puis de les recréer avec l'option --link (pour le conteneur NGinx qui va initier la connexion TCP vers le moteur PHP-FPM), la nouvelle configuration de NGinx et les volumes pointant sur notre page HTML et PHP:

On teste:

Sélection_246

Bingo !

A ce stade, nous avons donc deux conteneurs communiquant entre eux pour nous offrir un serveur Web compatible avec le langage PHP.

Le conteneur Varnish en frontal

Si vous suivez ce blog, vous savez tout le bien que je pense de l'utilisation du cache Varnish pour absorber la montée en charge des sites Web (sinon, vous pouvez effectuer une session de rattrapage en lisant ces articles). Nous allons donc créer un nouveau conteneur qui exposera le port TCP/80 et qui mettra en cache les pages construites par le serveur NGinx (qui est en écoute sur le port TCP/8080 si vous avez bien suivi...).

Nous allons utiliser l'image Varnish mise à disposition et maintenue par le contributeur jacksoncage.

On commence par la récupérer:

Puis on vérifie qu'elle est bien disponible sur notre hôte:

Comme il est indiqué dans la documentation de l'image, il faut écrire le fichier de configuration par défaut de Varnish (le fichier default.vcl):

On demande donc à Varnish d'aller directement communiquer avec le conteneur NGinx via l'adresse IP webstack-nginx (rappelez-vous que le hostname est créé dynamiquement par Docker au démarrage du conteneur avec l'option --link) et sur le port TCP 80 (attention, ce n'est pas le port TCP/8080 exposé par Docker sur notre hôte mais celui vraiment utilisé par NGinx dans le conteneur).

A noter que cette configuration est à compléter, notamment si vous voulez héberger un blog sous WordPress (des exemples de fichiers de configuration sont disponibles ici). Attentinon, ces exemples sont pour Varnish 4.0, donc à adapter si la version du conteneur jacksoncage/varnish n'est pas en ligne.

Puis lancer le conteneur avec les options suivantes:

On redirige le port 80 du conteneur vers le port 80 de votre hôte (il ne doit bien sûr pas y avoir de serveur Web déjà en écoute sur ce port) puis on fait le lien entre le conteneur Varnish et le conteneur NGinx.

On vérifie que nos trois conteneurs sont lancés:

Et on teste notre serveur de cache Varnish:

Le "Via: 1.1 varnish" confirme que notre infra commence à avoir de la gueule :).

En aparté, on peut d'ailleurs juger de la puissance de Varnish en lançant un simple bench tout d'abord directement sur le serveur NGinx (donc en baille-passant Varnish):

Puis en faisant le même test en passant par Varnish:

Les chiffres parlent d'eux même...

Gestion des conteneurs

Un simple pull sur les images préalablement téléchargé s'occupera de leurs mises à jour:

Comme l'on reconstruit notre infrastructure à partir de ces images, il suffira ensuite d'arrêter et de relancer les conteneurs:

Note: Il est également possible de créer des images maison (avec commit + tag) et de les relancer. Cette phase peut être utile dans le cadre d'un déploiement d'une infrastructure à une autre.

Orchestration de l'infrastructure

On vient de voir que le lancement d'une infrastructure basée sur Docker peut rapidement devenir compliqué. Les conteneurs doivent être lancés dans un certain ordre, avec des options spécifiques. Il est toujours possible de scripter les commandes du chapitre précédent ou plus simplement d'utiliser un outil d'orchestration.

Vagrant vous vient en tête ? Pourtant, ce n'est pas la solution que nous allons utiliser dans ce billet.

Nous allons nous tourner vers docker-compose (anciennement Fig). C'est un logiciel en ligne de commande permettant de d'écrire son infrastructure Docker à partir d'un fichier de configuration texte au format YAML.

L'installation de Fig se fait via la commande:

Note: pour d'autre méthode d'installation, consultez la documentation sur le site officiel.

Le fichier de configuration Fig correspondant à notre infrastructure est le suivant (à éditer dans le fichier $HOME/data/webstack/docker-compose.yml):

On lance ensuite notre infrastructure en une seule et unique commande:

Tout comme avec la ligne de commande Docker, on peut voir les conteneurs en cours d'exécution:

Les arrêter (sans les supprimer):

Les relancer:

Les supprimer:

Je vous laisse découvrir les autres commandes de docker-compose sur le site officiel de la documentation.

Conclusion

Nous venons de créer les bases d'une infrastructure Web performante, facilement maintenable et évolutive. Il est ainsi facile d'y ajouter d'autres services comme une base de donnée (type MariaDB), un serveur sFTP (pour la mise à jour des pages Web) ou bien encore un outil d'analyse des logs (Varnish et NGinx).

Et de votre coté, avez-vous mis en place une infrastructure Docker pour votre serveur Web ? Si oui comment ?

Partagez votre expérience avec nous !

  • David

    Qu’en est-t’il de Varnish avec la nouvelle règle de Google de favoriser l’HTTPS ?
    Prévois tu de basculer sur une autre solution pour tes « Webstacks » ?
    Très bon article sinon merci beaucoup.

    • Je n’ai pas encore fait de test mais j’avais noté cette solution: https://www.digitalocean.com/community/tutorials/how-to-configure-varnish-cache-4-0-with-ssl-termination-on-ubuntu-14-04

      On garde les avantage de Varnish + HTTPs

      • David

        Je viens de tester et ça fonctionne, je ne suis pas persuadé qu’NGINX en frontal sur le port 443 absorbe aussi bien la charge que Varnish, à tester.
        De plus le proxy_pass en plus ça fait une redirection supplémentaire, pas sur que les performances globales n’y perdent pas un peu.
        Ca répond au besoin mais si dans un futur proche Varnish pouvait gérer cette partie ça serait plus propre.

      • David

        Aie oui c’est même catastrophique avec mes tests via apache bench :
        Nginx direct sur le port 8080 : 875 req/s
        Varnish sur le port 80 et Nginx en backend sur le port 8080 : 2484 req/s
        Nginx sur le port 443 puis Varnish sur port 80 et backend sur port 8080 : 154 req/s

        J’ai peut être une conf à revoir mais pour le moment ce n’est pas top.

      • David

        Hé bien au final c’est bien le SSL le coupable mais c’est logique car il génère plus de travail CPU.
        A optimiser au maximum mais il y aura forcément baisse de performances.

      • Varnish + pound en terminateur SSL, pas de pb de perfs 🙂

  • Frédéric Pégé

    Sans vouloir troller, c’est quand même vachement plus simple avec lxc, non ?
    Et comment tu supervises ta plateforme avec Docker ? Comment installer un composant additionnel (nrpe, glances, collectd, …) et le faire en sorte qu’il démarre automatiquement dans un docker ?
    Non, décidément, je ne comprends pas cet engouement pour Docker. Docker me donne l’image d’une solution d’infra faite pour les devlos. Mais je ne vois vraiment pas comment mettre en place une infra « prod » à base de docker.

    http://kalmanolah.net/blog/docker-vs-lxc-there-can-only-be-one/

    Promis, je ne suis pas un troll. Je cherche à être convaincu.

    • Florian

      Pour la supervision tu as juste à surveiller que le proccess contenant ton ou tes container tourne bien. Pour les logs la brique ELK est parfait pour ça. Voici un très bon exemple https://denibertovic.com/post/docker-and-logstash-smarter-log-management-for-your-containers/
      Faut prendre les container comme des choses jetables. Donc en cas de panne d’un hôte lorsqu’il se rallume peut être refaire un build en récupérant les fichiers de conf. Sinon comme dit dans l’article paramétrer fig et le lancer lorsque la machine boot.
      En effet docker est fait plus pour les devops je pense. Or faire un site web via docker n’est pas une idée absurde, bien au contraire selon moi. Tu développe ton site comme tu le souhaite et op tu envoie ton image sur n’importe qu’elle plateforme, tu es sur qu’elle tournera comme tu le souhaites.

      • Frédéric Pégé

        « Tu développe ton site comme tu le souhaite et op tu envoie ton image sur n’importe qu’elle plateforme, tu es sur qu’elle tournera comme tu le souhaites. »

        La même chose est vraie avec LXC, en plus simple les admins sys gardent la maîtrise sur ce qu’il se passe dans le container.
        Tu peux mettre plusieurs services dans un container LXC. La différence fondamentale est qu’un container LXC boote réellement, pas ceux de docker.

        Il faudra une réelle révolution pour que Docker fasse son trou dans le monde de la production informatique. Je bosse dans l’infrastructure (côté sysops donc), et il est clair que mes clients ne voudront jamais de Docker pour de la prod.

  • Pierre-Henry Muller

    Un élément que je ne comprend pas et qui apparaît chez beaucoup de monde c’est de dire que Varnish est plus puissant pour la mise en cache. Lorsque je reprend ton test apache bench et que je le lance sur un Nginx qui délivre du static voilà ce que j’obtiens sur une VPS qui n’est pas gavées de ram et cpu.

    ab -t 30 -c 5 http://www.boreally.org/
    Finished 50000 requests

    Server Software: nginx
    Server Hostname: http://www.boreally.org
    Server Port: 80

    Document Path: /
    Document Length: 48978 bytes

    Concurrency Level: 5
    Time taken for tests: 9.438 seconds
    Complete requests: 50000
    Failed requests: 0
    Write errors: 0
    Total transferred: 2458950000 bytes
    HTML transferred: 2448900000 bytes
    Requests per second: 5297.56 [#/sec] (mean)
    Time per request: 0.944 [ms] (mean)
    Time per request: 0.189 [ms] (mean, across all concurrent requests)
    Transfer rate: 254422.39 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 0.0 0 1
    Processing: 0 1 0.7 1 47
    Waiting: 0 1 0.7 1 47
    Total: 0 1 0.7 1 47

    Percentage of the requests served within a certain time (ms)
    50% 1
    66% 1
    75% 1
    80% 1
    90% 2
    95% 2
    98% 2
    99% 2
    100% 47 (longest request)

    Pour moi Varnish ne vaut le coup que dans les règles complexes de mise en cache quand il faut faire des vérifications poussées genre si tel cookie est là, que l’internaute vient de tel continent et qu’il est authentifié alors il doit aller sur tel backend avec tel paramètres. En tout cas chez DigDeo on le déploie uniquement dans ce sens.
    Nginx est capable sur une même instance web de faire serveur http avec des règles de cache de pages et de délivrer des statics très rapidement. Et à mon sens on enlève une couche de traitement supplémentaire ce qui simplifie l’architecture ce qui est toujours bon à prendre.

    Pour la partie SSL Nginx le fait assez bien, on peut avoir de meilleures perfs avec des logiciels de terminaisons SSL à part comme Stud par exemple.

    Juste Nginx et ssl avec des algos assez sévères

    ab -t 30 -c 5 https://www.digdeo.fr/ 11:25

    Benchmarking http://www.digdeo.fr (be patient)
    Finished 4574 requests

    Server Software: nginx
    Server Hostname: http://www.digdeo.fr
    Server Port: 443
    SSL/TLS Protocol: TLSv1/SSLv3,ECDHE-RSA-AES256-GCM-SHA384,4096,256

    Document Path: /
    Document Length: 103278 bytes

    Concurrency Level: 5
    Time taken for tests: 30.035 seconds
    Complete requests: 4574
    Failed requests: 0
    Write errors: 0
    Total transferred: 473889270 bytes
    HTML transferred: 472393572 bytes
    Requests per second: 152.29 [#/sec] (mean)
    Time per request: 32.832 [ms] (mean)
    Time per request: 6.566 [ms] (mean, across all concurrent requests)
    Transfer rate: 15408.30 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 10 28 13.8 27 101
    Processing: 1 4 6.0 2 38
    Waiting: 0 3 6.0 1 35
    Total: 11 33 15.2 34 111

    Percentage of the requests served within a certain time (ms)
    50% 34
    66% 40
    75% 44
    80% 48
    90% 52
    95% 55
    98% 61
    99% 65
    100% 111 (longest request)

    Sinon très bon article sur le fonctionnement de Docker, je rejoins un peut Frédéric sur la notion de garder la main et superviser correctement son infra avec ce genre de déploiement mais je suis sur que Docker va s’améliorer. A vrai dire je préfère pour le moment la notion d’instance en auto déploiement façon OpenStack et AWS mais déjà là pas beaucoup de clients sont prêts à faire ce qu’il faut côté application pour gérer cet autodéploiement de ressources.

  • super article et super complet :)) merci mister

  • ImortalPK

    Salut Nico,

    Chouette article/tuto, j’ai voulu le tester sur mon dédié, histoire de le rentabiliser un peu , mais je bloque au lancement du compartiment Nginx ^^ (au début en somme). Voici le message d’erreur que j’ai :

    sh-4.3# docker run –name webstack_nginx_1 -v $HOME/data/webstack/www:/usr/share/nginx/html:ro -p 8080:80 -d nginx
    890fc35a3477d6a7a764300363409ccf8ab89666cf2a05d1d2b6407b8d9de249
    2014/10/23 05:20:09 Error response from daemon: Cannot start container 890fc35a3477d6a7a764300363409ccf8ab89666cf2a05d1d2b6407b8d9de249: fork/exec /var/lib/docker/init/dockerinit-1.2.0: invalid argument

    Je pars pourtant d’une installation fraiche et propre de docker, a jour, et j’ai tout bien suivi.
    Une idée ? ^^

    Merci !!!

    • Yohann THOUVENIN

      La commande à rentrer est seulement :
      docker run –name webstack_nginx_1 -v $HOME/data/webstack/www:/usr/share/nginx/html:ro -p 8080:80 -d nginx

      • ImortalPK

        c’est ce que j’ai fais, les 3 autres lignes étant le retour de la console
        je réssayerai

  • Gabriel Chollet

    Bientôt un conteneur avec Glances ? 🙂

  • Bon va falloir sérieusement se pencher sur les docker… car c’est plus qu’à la mode et les devOps ne courent pas les rues 🙂

    Merci pour ce how-to complet, as usual !

  • alecpo

    Bonjours Nico;
    J’ai testé le serveur Nginx et Php dans les dockers comme expliquées dans ton tuto. Facile car t’as procédure est très bien faite. Pour aller plus loin j’ai installé un WordPress et je me suis aperçu que l’upload de fichier ne fonctionne pas (WordPress dans médias par ex). Ma config de Php par défaut devrait m’autoriser les fichiers de moins de 2 M… As-tu une idée ? 🙂
    Merci,

    EDIT : Il faut seulement retirer le Read Only sur le parametre -v …

  • Salut,

    Je rencontre un problème lorsque je lance les containers, nginx retourne une 403.

    Dans les logs il m’informe que
    2014/11/30 21:53:54 [error] 7#0: *1 directory index of « /usr/share/nginx/html/ » is forbidden, client: 192.168.59.3, server: localhost, request: « GET / HTTP/1.1 », host: « 192.168.59.103 »

    Sans doute un problème de droits… Peux-tu m’indiquer quels sont les droits et les owners sur le dossier www ?

    Merci d’avance 🙂

    • Thierry LER

      Bonjour,

      Je pense avoir le même problème que SelrahcD.

      Ce que j’ai fais : Je suis sous Mac. J’ai installé VirtualBox dans lequel j’ai créé ma VM Linux à l’aide de Vagrant. L’ip de ma VM est 192.168.1.50.

      Je fais
      docker run –name nginx_tuto2 -v $HOME/var/www/tuto2/www:/usr/share/nginx/html:ro -p 8080:80 -d nginx

      (en gros mes fi
      puis
      docker attach –sig-proxy=false nginx_tuto2

      et quand je demande 192.168.1.50:8080 :

      2016/01/10 08:40:58 [error] 8#8: *10 directory index of « /usr/share/nginx/html/ » is forbidden, client: 192.168.1.45, server: localhost, request: « GET / HTTP/1.1 », host: « 192.168.1.50:8080 »

      192.168.1.45 – – [10/Jan/2016:08:40:58 +0000] « GET / HTTP/1.1 » 403 570 « – » « Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36 » « – »

      C’est un peu gênant…

      Mais en relisant tout bien une nième fois, je me suis rendu compte que j’avais mis
      $HOME/var/www/tuto2/www…

      au lieux de
      /var/www/tuto2/www…

      Du coup le message d’erreur disait vrai… Tu as peux être fais la même erreur d’inattention…

  • EvKoh

    Hello, je met à disposition un petit projet, qui regroupe quelques technologies souvent utilisée, donc à voir, à tester et critiquer (de manière constructive) 🙂

    https://github.com/EvKoh/WebStaDOckER

  • némo

    Salut, super article, comme souvent 🙂

    Par contre, il y a une erreur : Il faut mettre –sig-proxy=false à la place de true pour justement que le ctrl+C ne termine pas le containeur.

  • Pour info, fig n’a pas l’air de monter les volumes de docker version 1.4 cf. https://github.com/docker/fig/issues/723

  • Zeuth

    Super tuto.. as tu prévu la suite avec MariaDB ?

    Sinon une petite faute dans ton tuto :
    vi $HOME/data/conf/nginx.conf
    –> vi $HOME/data/webstack/conf/nginx.conf

    • Merci 🙂

      C’est corrigé.

      • Zeuth

        Du coup je continue..
        Dans le chapitre : Le conteneur PHP-FPM

        La première fois que tu lances la commande docker run, le style de code a sauté

  • Zeuth

    Autre point, le container Varnisher que tu nous proposes est en 3.0.5.
    Il ne fonctionnera pas avec le fichier VCL que tu proposes pour WordPress, car il est en version 4

  • Chathushka Perera

    Exactly what I wanted, very good explanation on docker compose, the only tricky part is the file permissions for configs and file location depending on versions and also auto generated container name. Thanks to the author and google translate 😀

  • Christophe DENEUX

    Une autre solution pour gérer l’orchestration et le déploiement des containers Docker est: Roboconf (http://roboconf.net/). Produit open source jeune mais très prometteur.

  • Pingback: Monter un serveur web très performant | Tuto Snatch & Crash()