Comment configurer un environnement Docker pour un projet Symfony qui utilise php-fpm? La réponse dans ce guide... :D

Je me suis mis depuis peu à Docker pour des raisons professionnelles, mais surtout parce que c'est la "grande tendance" ! ^^
Je me suis arraché les cheveux pour comprendre, debogguer et intéragir avec Docker. Mais aujourd'hui, je suis content de pouvoir monter une configuration pour un projet Symfony. xD

Apréhender la stack Docker et son fonctionnement est relativement long. Les articles ci-dessous vous aideront à mieux comprendre cet outil:

Une fois que vous aurez apréhendé le concept Docker, vous pourrez suivre ce guide.

Prérequis

  • PHP 7.2.9 ou supérieur
  • Docker
  • Composer
  • Symfony CLI
  • Connaitre les concepts Docker
  • Système Mac ou Linux (Pour Windows, je vous laisse adapter les commandes ;))

Démarrage

Tout au long de ce guide, le projet demo de Symfony sera utilisé, et je l'ai organisé en trois parties:

  1. Configuration du projet avec un serveur Nginx et PHP-FPM.
  2. Configuration du projet docker avec Mysql et phpMyAdmin.
  3. Migration de la base de données SQLite vers Mysql.

Cet article concerne la première partie uniquement. ;)

Avec la console, exécutez la commande suivante:

composer create-project symfony/symfony-demo symfony-demo
cd symfony-demo

Vérifez que tout fonctionne en lançant la commande suivante:

symfony serve

Lorsque vous vous rendez sur le lien http://127.0.0.1:8000, le projet demo de Symfony s'affiche et utilise la configuration standard de votre machine via l'outil Symfony CLI.

Il faut maintenant configurer un environnement Docker pour le projet, en utilisant Docker Compose.

Structuration

Docker permet de manipuler la "conteunarisation" des images alors que Docker Compose permet de manipuler plusieurs images Docker. C'est ce que nous allons utiliser.

Il faudra créer plusieurs services avec Docker Compose:

  • un pour gérer le projet via php-fpm
  • un pour gérer un serveur NGINX
  • un pour gérer notre base de donnée MySQL (dans la partie 2)
  • un pour gérer notre outil phpMyAdmin (dans la partie 2)

Il faudra donc créer un fichier docker-compose.yml dans le projet, et placer tous les fichiers de configuration dans le dossier docker.

PHP-FPM

Pour utiliser PHP-FPM avec le projet Symfony, il faudra créer une nouvelle image basée sur Alpine où et la configurer spécifiquement.

Pour cela, exécutez les commandes suivantes:

mkdir docker && mkdir docker/php-fpm
subl docker/php-fpm/Dockerfile

subl permet de lancer Sublime Text. Si vous ne l'avez pas, utilisez un autre éditeur de texte, ou celui par défaut vi.

Dans ce fichier, ajoutez les lignes suivantes:

FROM alpine:3.10

RUN apk add --update --no-cache \
    coreutils \
    sqlite \
    php7-fpm \
    php7-apcu \
    php7-ctype \
    php7-curl \
    php7-dom \
    php7-gd \
    php7-iconv \
    php7-imagick \
    php7-json \
    php7-intl \
    php7-mcrypt \
    php7-fileinfo\
    php7-mbstring \
    php7-opcache \
    php7-openssl \
    php7-pdo \
    php7-pdo_mysql \
    php7-pdo_sqlite \
    php7-mysqli \
    php7-xml \
    php7-zlib \
    php7-phar \
    php7-tokenizer \
    php7-session \
    php7-simplexml \
    php7-xdebug \
    php7-zip \
    php7-xmlwriter \
    php7-sqlite3 \
    make \
    curl

RUN echo "$(curl -sS https://composer.github.io/installer.sig) -" > composer-setup.php.sig \
        && curl -sS https://getcomposer.org/installer | tee composer-setup.php | sha384sum -c composer-setup.php.sig \
        && php composer-setup.php && rm composer-setup.php* \
        && chmod +x composer.phar && mv composer.phar /usr/bin/composer

COPY symfony.ini    /etc/php7/conf.d/
COPY symfony.ini    /etc/php7/cli/conf.d/
COPY others.ini      /etc/php7/conf.d/

COPY symfony.pool.conf /etc/php7/php-fpm.d/

CMD ["php-fpm7", "-F"]

WORKDIR /app
EXPOSE 9001

Cette configuration demande à Docker d'utiliser l'image Alpine version 3.10 et d'installer les différents package de php-fpm7. L'outil composer est également installé.
Des fichiers de confs symfony.ini, others.ini et symfony.pool.conf sont aussi injectés au conteneur.
Enfin, php-fpm7 est exécuté sur le port 9001.

Voici le contenu des fichiers de configuration:

docker/php-fpm/symfony.ini:

; Définition du fuseau horaire
date.timezone = UTC

docker/php-fpm/others.ini:

; xDebug
zend_extension=xdebug.so

[Xdebug]
xdebug.remote_enable=true
xdebug.remote_port=5902
xdebug.remote_host=host.docker.internal

; SQLite
sqlite3.defensive = 1

docker/php-fpm/symfony.pool.conf:

[symfony]
listen = 0.0.0.0:9001
pm = dynamic
pm.max_children = 20
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

env[DB_1_ENV_MYSQL_DATABASE] = $DB_1_ENV_MYSQL_DATABASE
env[DB_1_ENV_MYSQL_USER] = $DB_1_ENV_MYSQL_USER
env[DB_1_ENV_MYSQL_PASSWORD] = $DB_1_ENV_MYSQL_PASSWORD

catch_workers_output = yes

Plus d'informations sur les différents paramètres sont disponibles sur le Github du projet.

Nginx

Pour pouvoir traiter les requêtes HTTP, il est nécessaire d'avoir un serveur Web et pour cela, Nginx sera utilisé.
Une image Alpine est là aussi utilisée pour créer le conteneur Nginx.

Exécutez les commandes suivantes:

mkdir docker/nginx
subl docker/nginx/Dockerfile

Ajoutez les lignes:

FROM alpine:3.10

RUN apk add --update --no-cache nginx

COPY nginx.conf /etc/nginx/
COPY symfony.conf /etc/nginx/conf.d/

RUN echo "upstream php-upstream { server php-fpm:9001; }" > /etc/nginx/conf.d/upstream.conf

RUN adduser -D -g '' -G www-data www-data

CMD ["nginx"]

EXPOSE 80
EXPOSE 443

Cette configuration demande à Docker d'utiliser la même image que précédement en y installant nginx.
Les fichiers nginx.conf et symfony.conf sont injectés au conteneur et le fichier upstream.conf est généré.
Dans ce dernier, on demande à Nginx d'écouter le service Docker php-fpm (défini dans docker-compose.yml) sur le port 9001. Vous l'aurez deviné, il s'agit du service php-fpm configuré précédement.
Enfin, Nginx est lancé sur les ports traditionnels 80 et 443.

Voici le contenu des fichiers de configuration:

docker/nginx/nginx.conf

user www-data;
worker_processes 4;
pid /run/nginx.pid;

events {
  worker_connections  2048;
  multi_accept on;
  use epoll;
}

http {
  server_tokens off;
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  keepalive_timeout 15;
  types_hash_max_size 2048;
  include /etc/nginx/mime.types;
  default_type application/octet-stream;
  access_log off;
  error_log off;
  gzip on;
  gzip_disable "msie6";
  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
  open_file_cache max=100;
  client_body_temp_path /tmp 1 2;
  client_body_buffer_size 256k;
  client_body_in_file_only off;
}

daemon off;

docker/nginx/symfony.conf

server {
    server_name localhost;
    root /app/public;

    location / {
        try_files $uri @rewriteapp;
    }

    location @rewriteapp {
        rewrite ^(.*)$ /index.php/$1 last;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass php-upstream;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
    }

    error_log /var/log/nginx/symfony_error.log;
    access_log /var/log/nginx/symfony_access.log;
}

Il est important de retenir ici que l'adresse par défaut localhost est pointée vers le répertoire /app/public qui contient les fichiers publics du projet Symfony.

Docker Compose

Il est maintenant temps de construire le fichier docker-compose.yml.

Exécutez la commande suivante:

subl docker-compose.yml

Ajoutez le contenu suivant:

version: '3.7'
services:
  php-fpm:
    container_name: php-fpm
    build: ./docker/php-fpm
    ports:
      - 9000:9001
    volumes:
      - .:/app/:cached
    networks:
      - site

  nginx:
    container_name: nginx
    build: ./docker/nginx
    ports:
      - "8000:80"
    depends_on:
      - php-fpm
    networks:
      - site
    volumes:
      - .:/app/:cached
networks:
  site:

Cette configuration utilise Docker Compose 3.7 et définit deux services: php-fpm et nginx.
Chaque service construit une image à partir des fichiers précédement créés.
Le service php-fpm expose son port 9001 sur le 9000 (en réalité, il ne sera pas vraiment utilisé) et crée un volume de /app (dans le conteneur) vers le répertoire courant du projet.
Le service nginx expose son port 80 sur 8000 et crée le même volume.

Lancement du projet dans Docker

Tout a été configuré pour pouvoir lancer le projet dans Docker. Pour cela, exécutez la commande suivante:

docker-compose up

Pour sortir du programme aprés lancement, vous devez utiliser l'option -d: docker-compose up -d

Vous pouvez maintenant tester le résultat sur le lien http://localhost:8000.

Symfony Demo

Et la suite

Voici la fin de cette partie. Je vous invite maintenant à lire la partie 2, qui vous apprendra à configurer votre projet avec MySQL et phpMyAdmin.

Je vous dis à plus pour le prochain article. xD


Liens utiles:

Article précédent Article suivant


Ajouter un commentaire