Aller au contenu principal

Docker : images, layers et isolation kernel expliqués

Comprendre le multi-stage build, les healthchecks et l'isolation kernel via la métaphore des pancakes.
Catégorie

DevOps

Déploiement, CI/CD, conteneurisation et gestion d'infrastructure pour applications PHP et Symfony.

Lecture
5 min
Niveau
Intermédiaire
mars 2 2025
Partager

Docker est souvent mal compris. Est-ce de la virtualisation ? Non. Est-ce un chroot glorifié ? Presque, mais avec des super-pouvoirs comme les namespaces & cgroups.

Mais oublions l'informatique pure un instant. Pour comprendre Docker, il faut savoir cuisiner, et plus précisément, cuisiner des pancakes.

Le monde d'avant

Dans notre boutique de pancakes, il n'y a qu'une seule cuisine commune pour tout le monde, (l'OS Host).

  • Le client A (Symfony) veut des pancakes aux myrtilles (besoin de PHP 8.2).
  • Le client B (une vieille version de WordPress) veut des crêpes au sarrasin (besoin de PHP 7.4).
  • Le client C (une vieille version de Node.js) veut un kebab (besoin de Node 18).

La guerre est déclarée ! Pour cuire la crêpe B, vous devez désinstaller la poêle "PHP 8.2" et visser la poêle "PHP 7.4". Il reste des traces de myrtilles. Le kebab a un goût de sarrasin. Une fuite de mémoire (un cuisinier maladroit) ruine tous les plats.

La solution Docker ? Et si chaque plat était cuisiné dans sa propre mini-cuisine hermétique, blanche, stérile et équipée uniquement du nécessaire ?

L'image : la recette

L'image Docker, c'est la recette plastifiée : elle est immuable. Sur mon site, j'utilise une recette sophistiquée en plusieurs étapes (Multi-Stage Build). Regardons le fichier réel devops/frankenphp/Dockerfile :

Dockerfile
# 1. La Base Commune (La Farine)
FROM dunglas/frankenphp:1-php8.5 AS frankenphp_upstream

# 2. Les Ustensiles (Extensions PHP)
FROM frankenphp_upstream AS frankenphp_base
RUN apt-get update && apt-get install -y --no-install-recommends \
    libmagickwand-dev libwebp-dev ...

Ici, je prépare la pâte mère. Chaque instruction RUN ajoute une couche (layer) invisible. Si je change la farine (l'image de base), tout le monde est affecté. Mais si je change juste le décor (le code source), la pâte n'est pas refaite.

Une particularité de mon Dockerfile est l'utilisation massive de COPY --link :

Dockerfile
COPY --link devops/frankenphp/conf.d/10-app.ini $PHP_INI_DIR/app.conf.d/

Sans --link, Docker devrait revérifier tous les ingrédients précédents. Avec --link, il ajoute cet ingrédient indépendamment, comme une cerise posée à la toute fin car c'est instantané.

Le multi-stage : dev vs prod

Notre Dockerfile se sépare ensuite en deux univers parallèles :

Dockerfile
# Univers DEV : Cuisine Ouverte (On goûte, on modifie)
FROM frankenphp_base AS frankenphp_dev
RUN install-php-extensions xdebug
CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ]

# Univers PROD : Cuisine Fermée (Scellé pour le client)
FROM frankenphp_base AS frankenphp_prod
ENV APP_ENV=prod
COPY --link . ./
RUN composer install --no-dev --classmap-authoritative
  • En Dev (--watch) : Le pancake reste "cru" au centre. On peut rajouter des pépites de chocolat (modifier le code) pendant la cuisson.
  • En Prod : Le pancake est cuit, emballé sous vide (--classmap-authoritative). Il est immuable.

Le Containeur

Le Containeur, c'est le moment où on verse la pâte dans la poêle. C'est l'instanciation de l'Image. Techniquement, Docker prend les layers en lecture seule (la recette) et ajoute une fine couche en écriture (Copy-on-Write) par-dessus.

Si le pancake brûle, on ne gratte pas le noir. On le jette (docker rm) et on recommence une cuisson parfaite (docker run).

L'orchestration : docker compose

Un pancake tout seul, c'est triste. Un petit-déjeuner complet, c'est :

  • Le pancake (PHP, FrankenPHP)
  • Le sirop d'érable (PostgreSQL)
  • Le jus d'orange (Redis)
  • Le toasteur (Meilisearch)

Docker compose est votre serveur. Il dresse toute la table d'un coup. Analysons le compose.yaml :

YAML
services:
    php:
        depends_on:
            database:
                condition: service_healthy # "Attends que le sirop soit chaud !"

Le healthcheck : le chef goûte

YAML
    database:
        healthcheck:
            test: [ "CMD", "pg_isready", "-d", "${POSTGRES_DB:-app_dev}" ]
            interval: 10s

Docker ne se contente pas d'allumer le gaz (lancer le processus). Il goûte (pg_isready) toutes les 10 secondes. Tant que le sirop n'est pas à température, il n'autorise pas le service des pancakes. Fini les crashs au démarrage !

Les volumes : le tupperware magique

YAML
        volumes:
            - database_data:/var/lib/postgresql/data:rw

Rappelez-vous : si je jette mon pancake brûlé (conteneur), je perds tout ce qui est dedans. Pour la base de données, c'est inacceptable.

J'utilise donc un volume (database_data). C'est un tupperware indestructible posé sur une étagère hors de la cuisine isolée. Même si la cuisine explose, le tupperware reste intact.

Le mot de la fin

Docker n'est pas magique. C'est une exploitation brillante du Kernel Linux (namespaces = isolation, cgroups = quotas).

Mais gardez cette image : vos serveurs ne sont plus des animaux de compagnie qu'on soigne quand ils sont malades (Servers as Pets).

  • Un "Pet" a un nom (Gandalf, Zeus). S'il est malade, on passe la nuit à le soigner. Sa mort est une tragédie.

Vos conteneurs sont du bétail (Servers as Cattle).

  • Ils n'ont pas de nom, juste un ID.
  • S'ils sont malades, on ne les soigne pas. On les abat (pardon, on les stoppe) et on en déploie un nouveau immédiatement.

C'est la philosophie du pancake. S'il est râté, on le jette. Pourquoi ?

Parce qu'on a la recette parfaite (Dockerfile) pour en refaire un million d'autres identiques à la seconde près.

Bon appétit !

Poursuivre la lecture

Sélectionné avec soin pour vous.

Sécurité

OWASP ZAP : comment implémenter un audit DAST automatisé avec Symfony et Docker

Passer du SAST au DAST en intégrant OWASP ZAP à votre workflow local via Docker et Castor. Un guide technique pour un audit de sécurité automatisé.

4 min de lecture
DevOps

FrankenPHP en dev c'est bien, en prod c'est encore mieux

Passez FrankenPHP en production ! Comment j'ai déployé sur mon VPS avec un Makefile survitaminé. On couvre le Dockerfile de prod, la CI/CD, et l'astuce de multiplexing SSH pour calmer fail2ban pour de bon.

14 min de lecture
DevOps

Comment FrankenPHP a relégué PHP-FPM et Nginx au stade de reliques

Stop à Nginx + PHP-FPM. Découvrez pourquoi FrankenPHP est la solution moderne pour un setup Docker simple et performant.

13 min de lecture