Créer une image docker avec Symfony 4

Lors du précédent chapitre, nous avons commencé à utiliser docker-compose pour pouvoir changer à la volée notre code PHP sans avoir à sans cesse re-construire notre image : https://medium.com/@Gaotian/premi%C3%A8re-utilisation-de-docker-compose-296fe9690e70.

Je vous propose à présent de nous attaquer à quelque chose d’un peu plus imposant qu’un simple fichier php : le code d’une application Symfony 4.

Lors de ce chapitre nous utiliserons un tout nouveau projet et reprendrons le code de zéro.

Pré-requis

  • Composer
  • Docker

Création du projet Symfony

Tout d’abord nous générons le squelette de l’application Symfony.

Nous utilisons composer pour créer le nouveau projet : https://symfony.com/doc/current/best_practices/creating-the-project.html

composer create-project symfony/skeleton docker-symfony

Création de l’image docker

Nous reprenons les étapes vues dans les chapitres précédents:

  • ajout de Dockerfile pour l’image de l’application php
  • ajout de docker-compose.yml
  • ajout d’un Makefile

Pour commencer, nous créons un dossier docker dans lequel nous ajoutons un fichier Dockerfile avec comme contenu :

FROM php:7.3-alpine

COPY . /

CMD
php -S 0.0.0.0:80 app/public/index.php

A priori, rien d’étonnant, puisqu’il s’agit exactement du même code que lors du chapitre précédent.

Pour docker-compose, nous reprenons également le même code, nous changeons simplement le nom de l’image et nous choisissons le port 81 plutôt que 82 par pur caprice. Nous créons ce fichier à la racine de notre application.

version: '3'
services:
app:
build:
context: .
dockerfile: docker/Dockerfile
image: symfony
ports:
- 81:80
volumes:
- .:/app/

Le Makefile est identique à l’exception du port 81 qui remplace là encore le 82. Lui aussi se trouve à la racine du projet.

path = docker

clean:
docker system prune -a -f

build:
cd $(path) && docker build -t symfony .

rebuild: clean build

run:
cd $(path) && docker run --rm -p 81:80 symfony

rerun: rebuild run

compose:
docker-compose up --build -d

Lancement de l’application

Pour lancer l’application, nous utilisons sans surprise notre commande :

make compose

Si nous nous rendons à l’adresse http://0.0.0.0:81/ nous voyons la page d’accueil de Symfony.

Ajout de code Symfony

Nous allons maintenant ajouter notre propre code et une nouvelle page.

Nous créons un contrôleur BaseController.php que nous ajoutons dans le dossier src/Controller

<?php

namespace
App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class BaseController extends AbstractController
{
/**
*
@Route("/", methods={"GET","HEAD"}, name="accueil")
*/
public function getAccueil()
{
return new Response('Bienvenue');
}
}

Nous installons le bundle permettant d’ajout les routes en commentaire du contrôleur:

composer require annotations

En nous rendant sur http://0.0.0.0:81/, nous voyons que nous avons remplacé la base d’accueil par défaut par un texte JSON rudimentaire.

Nous allons maintenant installer Twig :

composer require symfony/twig-bundle

Nous ajoutons une view index.html.twig dans un dossier /templates que nous plaçons à la racine :

<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Symfony avec Docker</title>
</head>
<body>
<h1>Une super page</h1>
<p>Elle est générée par Symfony avec Docker.</p>
</body>
</html>

Nous l’appelons dans le contrôleur :

/**
*
@Route("/", methods={"GET","HEAD"}, name="accueil")
*/
public function getAccueil()
{
return $this->render('index.html.twig');
}

Nous ajoutons une seconde page pour nous assurer que tout fonctionne correctement, d’abord en ajoutant dans le contrôleur en dessous du code précédent :

/**
*
@Route("/apropos/{subject}", methods={"GET","HEAD"}, name="about")
*/
public function getAPropos($subject)
{
return $this->render('apropos.html.twig', [
'subject' => $subject
]);
}

Puis en ajoutant une nouvelle vue dans /templates:

<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Symfony avec Docker</title>
</head>
<body>
<h1>{{ subject }}</h1>
<p>Nous parlons de ce sujet important.</p>
</body>
</html>

Test manuel de notre application

Est-ce que tout fonctionne comme convenu?

Si nous nous rendons sur la page : http://0.0.0.0:81, nous arrivons bel et bien sur notre view index.html.twig.

Si nous nous rendons sur une page à propos, par exemple http://0.0.0.0:81/apropos/equipe, nous nous rendons sur la bonne page avec le paramètre correctement utilisé.

Certes nous n’avons pas de tests automatisés ou de base de données liées mais nous avons une application symfony 4 basique qui fonctionne avec docker-compose.

Et quand nous en changeons le code, le résultat est visible aussitôt après un simple rechargement sans avoir à reconstruire nos images.

Code final

Le code est disponible sur github : https://github.com/gdarquie/symfony-docker