Cover for Une stack Docker pour votre application Symfony

Une stack Docker pour votre application Symfony

[05/07/2016] : màj du docker-compose (suppression conteneur code+alias) + màj schéma + ajout PHPMyAdmin + simplification toolbox.
Un grand merci à tous ceux qui m’ont fait des retours ♥

TL;DR : Répo Github du projet

Une stack Docker pour votre application Symfony

Je développe des applications web depuis quelques temps sur une stack Vagrant que j’ai un peu pimpé. Bosser sur une VM est vraiment plus agréable/malléable qu’un WAMP. Cependant, cette solution si miraculeuse soit-elle a aussi ses inconvénients.

Tout d’abord, le temps d’initialisation de la box est particulièrement long. Deuxième argument, si on se plante on est obligé de tout réinstaller (ex: récemment j’ai oublié de mettre un point avant le slash de cette commande… sudo rm -rf /). Et enfin, si on souhaite instancier plusieurs machines sur une seule, le PC hôte se retrouve rapidement sur les rotules.

one ship with carrying multiples ships

Ce sont donc ces trois points qui m’ont motivé à migrer mon poste de dev sur Docker (et puis si autant de monde en parle, c’est sans doutes que ça vaut le détour !).

Je vais volontairement passer sous silence l’étape de présentation de Docker. Il y a plein d’articles/conférences à ce sujet sur la toile. Voici une conférence que j’ai bien aimé à ce sujet : Docker de “Zéro” à “Héros” par l’excellent Nicolas DE LOOF (qui anime aussi la web série Quoi d’neuf Docker ?).

Un conteneur pour les gouverner tous ?

Lors de mes premières expériences avec Docker, j’étais parti sur un méga-conteneur qui portait PHP, Apache, MySQL… tout ce qui est nécessaire pour faire tourner une application web. Et puis j’ai vite lâché l’affaire car je ne voyais pas la plus-value de cet outil comparé à ma vagrant. one ship with carrying one ship (ma première expérience avec Docker)

1 application (process) = 1 conteneur

A l’occasion du 3e anniversaire de Docker, j’ai vraiment vu l’intérêt de cet outil. Sans doutes, parce que le TP était plus pertinent que bon nombre d’articles sur la toile. Il faut donc lancer un process par conteneur. Le tout se fera avec docker-compose, qui jouera le rôle de chef d’orchestre de tous mes conteneurs.

Voici l’objectif vers lequel je souhaite tendre :

schema

Détail des conteneurs :

  • NGINX : le serveur web ;
  • PHP-FPM : le service qui exécutera le code PHP (PHP7 s’il vous plait !) ;
  • Application : un conteneur qui portera le code symfony ;
  • MySQL : Un SGBDR que l’on ne présente plus ;
  • Redis : Un SGBD clé-valeur avec lequel j’aime bien jouer en ce moment ;
  • ELK : Le trio de choc : Elasticsearch - Logstash - Kibana… parcequ’il y a mieux que les | tail / | grep pour visualiser ses logs !

Nota : Je suis parti du travail de Vincent COMPOSIEUX qui est plutôt propre pour ensuite l’adapter à mes besoins.

Solution

docker-compose.yml
version: '2'
services:
db:
image: mysql
ports:
- 3306:3306
volumes:
- './.data/db:/var/lib/mysql'
environment:
MYSQL_ROOT_PASSWORD: root
redis:
image: redis:alpine
ports:
- 6379:6379
php:
build: php7-fpm
ports:
- 9000:9000
links:
- db:mysqldb
- redis
volumes:
- chemin/vers/votre/app/symfony:/var/www/symfony
- ./logs/symfony:/var/www/symfony/app/logs
nginx:
build: nginx
ports:
- 80:80
links:
- php
volumes_from:
- php
volumes:
- ./logs/nginx/:/var/log/nginx
elk:
image: willdurand/elk
ports:
- 81:80
volumes:
- ./elk/logstash:/etc/logstash
- ./elk/logstash/patterns:/opt/logstash/patterns
volumes_from:
- php
- nginx

La 22 et 23e ligne du fichier (services.php.volumes) indiquent qu’il y a un mapping de volumes. Il vous faudra donc indiquer le chemin (absolu ou relatif) vers l’application Symfony. Le répertoire de logs se construiera tout seul comme un grand.

2 composantes du docker-compose n’étant pas des images, il faut donc construire les Dockerfiles.

Terminal window
# nginx/Dockerfile
FROM debian:jessie
MAINTAINER Maxence POUTORD <maxence.poutord@gmail.com>
RUN apt-get update && apt-get install -y \
nginx
ADD nginx.conf /etc/nginx/
ADD symfony.conf /etc/nginx/sites-available/
RUN ln -s /etc/nginx/sites-available/symfony.conf /etc/nginx/sites-enabled/symfony
RUN rm /etc/nginx/sites-enabled/default
RUN echo "upstream php-upstream { server php:9000; }" > /etc/nginx/conf.d/upstream.conf
RUN usermod -u 1000 www-data
CMD ["nginx"]
EXPOSE 80
EXPOSE 443
Terminal window
# php7-fpm/Dockerfile
FROM php:7.0-fpm
MAINTAINER Maxence POUTORD <maxence.poutord@gmail.com>
RUN apt-get update && apt-get install -y \
git \
unzip
# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
RUN composer --version
# Set timezone
RUN rm /etc/localtime
RUN ln -s /usr/share/zoneinfo/Europe/Paris /etc/localtime
RUN "date"
# Type docker-php-ext-install to see available extensions
RUN docker-php-ext-install pdo pdo_mysql
RUN echo 'alias sf="php app/console"' >> ~/.bashrc
WORKDIR /var/www/symfony

Il faut garder à l’esprit que les images se doivent d’être les plus petites possibles. Il ne faut installer que ce qui est nécessaire (le apt-get clean est implicite sur les debian).
Une fois que tout est prêt, un petit docker-compose build permettra de construire les différentes images. Et un docker-compose up lancera le tout.

Vous pouvez vérifier avec la commande docker-compose ps (tout doit-être à Up) :

Terminal window
$ docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------------------------
dockersymfony_db_1 /entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp
dockersymfony_elk_1 /usr/bin/supervisord -n -c ... Up 0.0.0.0:81->80/tcp
dockersymfony_nginx_1 nginx Up 443/tcp, 0.0.0.0:80->80/tcp
dockersymfony_php_1 php-fpm Up 0.0.0.0:9000->9000/tcp
dockersymfony_redis_1 /entrypoint.sh redis-server Up 0.0.0.0:6379->6379/tcp

Maintenant, vous allez devoir retrouver l’IP associée au conteneur NGINX et modifier votre fichier hosts :

Terminal window
$ docker inspect --format '{{ .NetworkSettings.IPAddress }}' $(docker ps -f name=nginx -q)
# unix seulement (sur Windows, modifier ce fichier C:\Windows\System32\drivers\etc\hosts)
$ sudo echo "171.17.0.1 symfony.dev" >> /etc/hosts

Vous devrez aussi modifier le fichier parameters.yml de votre application :

path/to/sfApp/app/config/parameters.yml
parameters:
redis_host: redis
database_host: mysqldb

Et voilà !

et voila gif

Accédez à votre application sur symfony.dev pour voir votre application et sur symfony.dev:81 pour consulter les logs avec Kibana.

Le code source est sur mon répo GitHub : https://github.com/maxpou/docker-symfony

Et je veux mon PHPMyAdmin moi !

C’est très simple, il suffit d’ajouter ceci à votre fichier docker-compose :

phpmyadmin:
image: phpmyadmin/phpmyadmin
ports:
- '8080:80'
links:
- db

Accédez ensuite à l’interface web via : symfony.dev:8080

Boîte à outils

Voici quelques commandes qui peuvent-être utiles :

Terminal window
# Acceder en bash
$ docker-compose exec php bash
# Composer (ex : composer update)
$ docker-compose exec php composer update
# Commandes Symfony
$ docker-compose exec php php /var/www/symfony/app/console cache:clear
# Commandes Symfony bis (avec un alias = plus simple!)
$ docker-compose exec php bash
$ sf cache:clear
# Commandes MySQL
$ docker-compose exec db mysql -uroot -p"root"
# Commandes Redis
$ docker-compose exec redis redis-cli
# F***ing cache/logs ;)
$ sudo chmod -R 777 symfony/app/cache symfony/app/logs
# Vérifier la consommation de CPU
$ docker stats $(docker inspect -f "{{ .Name }}" $(docker ps -q))
# Supprimer conteneurs
$ docker rm $(docker ps -a -q)

About the author

Maxence Poutord

Hey, I'm Maxence Poutord, a passionate software engineer. In my day-to-day job, I'm working as a senior front-end engineer at Orderfox. When I'm not working, you can find me travelling the world or cooking.

Follow @_maxpou

Recommended posts