Logo IDCI
Drapeau français Drapeau anglais

Création d'un projet Symfony avec Docker

Introduction

Symfony est un framework PHP reconnu pour sa robustesse et sa flexibilité. Lorsqu'on démarre un nouveau projet, il est souvent nécessaire de mettre en place un environnement de développement complet comprenant PHP, un serveur web et différents services complémentaires.

Docker rend possible de standardiser cet environnement en assurant la présence et la bonne version de PHP et autres dépendances logicielles nécessaires, et de garantir que tous les développeurs travaillent avec la même configuration, indépendamment de leur système d'exploitation et autres différences d'environnement possibles.

Dans cet article, nous allons détailler les différentes étapes permettant de créer un projet Symfony en s'appuyant sur une stack Docker. L'objectif est d'obtenir un environnement de développement simple à lancer et facilement maintenable.

Arborescence

Voici l'arborescence que nous allons mettre en place :

project/
├─ .docker/
│  ├─ conf/
│  │  ├─ nginx/
│  │  │  ├─ project.conf
│  │  ├─ php/
│  │  │  ├─ php.ini
│  ├─ docker-compose.yml
│  ├─ Dockerfile
│  ├─ entrypoint.sh
├─ .env

Chaque élément a un rôle précis :

project/.docker/conf/nginx/project.conf : Contient la configuration du serveur Nginx.

project/.docker/conf/php/php.ini : Contient la configuration PHP.

project/.docker/Dockerfile : Définit l'image PHP personnalisée utilisée par les conteneurs de l'application Symfony.

project/.docker/docker-compose.yml : Définit l'ensemble des services Docker que vous utiliserez dans votre projet.

project/.env : Contient les variables d'environnement utilisées par Docker.

Avant de continuer, il vous faudra également installer Docker sur votre machine en suivant la documentation officielle.

Initialisation du cluster Docker Swarm

Avant toute chose, il est nécessaire d'initialiser Docker Swarm sur la machine qui jouera le rôle de manager.

docker swarm init

Une fois la commande exécutée, Docker crée un cluster Swarm local.

Vous pouvez vérifier son état grâce à la commande :

docker node ls

Vous devriez voir apparaître le nœud courant avec le statut Leader.

Préparation du réseau Traefik

Afin de simplifier l'exposition de nos services HTTP et HTTPS, nous allons utiliser Traefik comme reverse proxy. Celui-ci se chargera de router automatiquement les requêtes vers les conteneurs appropriés en fonction du nom de domaine demandé.

Traefik doit être déployé sur votre cluster Docker Swarm avant de pouvoir exposer les applications.

Nous allons également créer le réseau partagé utilisé par Traefik et les différentes stacks applicatives :

docker network create \
    --driver overlay \
    --attachable \
    traefik_reverse_proxy

Vous pouvez vérifier sa création avec :

docker network ls

Le réseau traefik_reverse_proxy doit apparaître dans la liste.

Création du fichier docker-compose.yml

Le fichier principal de notre stack est le fichier docker-compose.yml.

---
version: '3.9'

services:

  php:
    image: demo.idci-consulting.fr/project/php-fpm:dev
    deploy:
      endpoint_mode: vip
    configs:
      - source: php_conf
        target: /usr/local/etc/php/php.ini
    volumes:
      - ../:/var/www/app
      - composer_data:/var/www/.composer
    networks:
      - app

  nginx:
    image: nginx
    deploy:
      endpoint_mode: dnsrr
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=traefik_reverse_proxy"
        - "traefik.http.services.project-nginx.loadbalancer.server.port=80"
        - "traefik.http.routers.project-nginx.entryPoints=web"
        - "traefik.http.routers.project-nginx.rule=Host(`project.docker`) || Host(`www.project.docker`)"
        - "traefik.http.routers.project-nginx-https.entryPoints=websecure"
        - "traefik.http.routers.project-nginx-https.rule=Host(`project.docker`) || Host(`www.project.docker`)"
        - "traefik.http.routers.project-nginx-https.tls=true"
    configs:
      - source: nginx_conf
        target: /etc/nginx/conf.d/default.conf
    volumes:
      - ../:/var/www/app
    networks:
      - traefik_reverse_proxy
      - app

configs:
  nginx_conf:
    file: ./conf/nginx/project.conf
  php_conf:
    file: ./conf/php/php.ini

volumes:
  composer_data:

networks:
  app:
  traefik_reverse_proxy:
    external: true

Quelques informations sur les différentes sections :

services : Liste des conteneurs qui composeront notre environnement.

php : Service chargé d'exécuter l'application Symfony.

nginx : Service qui recevra les requêtes HTTP.

volumes : Permet de conserver les données même après le redémarrage ou la suppression des conteneurs.

Création de l'image PHP

Nous allons créer une image PHP personnalisée adaptée à Symfony.

Créez le fichier docker/php/Dockerfile :

FROM php:8.4-fpm

RUN apt-get update && apt-get install -y \
    git \
    unzip \
    zip \
    libzip-dev \
    libicu-dev \
    libonig-dev

RUN docker-php-ext-install \
    intl \
    zip

COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

Il nous faut ensuite construire l'image, mais avant cela, nous vous conseillons de créer un Makefile, étant donné que vous serez potentiellement amenés à utiliser ces commandes (assez lourdes) plusieurs fois pendant la durée de vie du projet :

source_tag = dev

# IMAGES
.PHONY: build-image
build-image:
	docker build --target=$(source_tag) --build-arg source_tag=$(source_tag) --no-cache --network=host -t docker-registry.idci-consulting.fr/idci-consulting/project/php-fpm:$(source_tag) -f .docker/Dockerfile .

Il nous suffit maintenant d'éxecuter la commande que nous avons créé :

make build-image

Cette image servira de base pour tous les conteneurs PHP du cluster.

Configuration de Nginx

Créez le fichier .docker/conf/nginx/project.conf :

map $http_x_forwarded_proto $fastcgi_https {
   default off;
   http off;
   https on;
}

server {
    root /var/www/app/public;

    access_log /dev/stdout;
    error_log /dev/stderr;

    charset utf-8;

    location / {
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/index.php(/|$) {
        fastcgi_pass php:9000;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS $fastcgi_https;
        fastcgi_buffers 4 256k;
        fastcgi_buffer_size 256k;

        internal;
    }
}

Configuration de PHP

Créez le fichier .docker/conf/nginx/php.ini :

date.timezone = 'Europe/Paris';
short_open_tag = Off;
magic_quotes_gpc = Off;
register_globals = Off;
session.auto_start = Off;
error_reporting = E_ALL;
log_errors = On;
display_errors = On;
error_log = /dev/stderr;
memory_limit = -1;
upload_max_filesize = 10M;
post_max_size = 10M;

Création du projet Symfony

Nous allons constater la puissance de Docker en créant un projet Symfony sans avoir à installer Composer

docker run --rm --interactive --tty --user 1000 --volume $PWD:/app composer:2 create-project symfony/skeleton:"^8.0" project

Cette commande sert à construire l'arborescence des fichiers classique d'un projet Symfony

Déploiement de la stack

Une fois les fichiers créés, nous pouvons déployer l'ensemble des services. Pour se faire, vous pouvez ajouter les commandes suivantes dans votre Makefile, puis éxécuter stack-deploy.

image_name = demo.idci-consulting.fr/project/php-fpm
source_tag = dev
stack_name = project

# IMAGES
.PHONY: build-image
build-image:
	docker build --build-arg source_tag=$(source_tag) --no-cache --network=host -t $(image_name):$(source_tag) -f .docker/Dockerfile .

# STACKS
.PHONY: stack-deploy
stack-deploy:
	docker stack deploy -c .docker/docker-compose.yml ${stack_name}

.PHONY: stack-undeploy
stack-undeploy:
	docker stack rm ${stack_name}

Vous pouvez vérifier le bon déploiement grâce à la commande :

docker service ls
docker stack ls

Vous devriez voir apparaître les services :

  • project_php
  • project_nginx

et la stack :

  • project

Configuration du poste local

Pour permettre à votre machine de résoudre les noms de domaine utilisés par Traefik, ajoutez les entrées suivantes dans votre fichier hosts.

Linux / macOS

sudo nano /etc/hosts

Ajoutez les lignes suivantes :

127.0.0.1 project.docker
127.0.0.1 www.project.docker

Vérification de l'installation

Pour vérifier le fonctionnement de Symfony, ouvrez votre navigateur et accédez à :

http(s)://project.docker

Vous devriez voir apparaître la page d'accueil Symfony comme ci-dessous :

Symfony land page