PHP Academy · Leçon

Compilations multi-étapes et optimisation

Réduisez la taille des images et séparez la compilation de l’exécution.

Leçon 2 sur 413 étapes

Compilations multi-étapes et optimisation est une leçon PHP Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage PHP Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours PHP Academy comprend 4 leçons au total.

Pourquoi plusieurs étapes

Une image à une seule étape emporte Composer, les dépendances de construction, les en-têtes de développement et votre dossier tests/ en production. Les constructions à plusieurs étapes vous permettent de compiler et d’installer dans une étape constructeur volumineuse, puis de ne copier que les artefacts terminés dans une étape d’exécution légère.

Résultat : des images plus petites, une surface d’attaque réduite, des téléchargements plus rapides et aucun compilateur livré en production.

Étapes nommées

Chaque FROM ... AS name démarre une nouvelle étape. Les étapes suivantes peuvent copier des fichiers depuis les précédentes avec COPY --from=name. Seule l’étape finale devient votre image ; les étapes intermédiaires sont supprimées, mais restent mises en cache.

# Stage 1: dependencies
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --prefer-dist --ignore-platform-reqs

# Stage 2: runtime
FROM php:8.3-fpm-alpine AS runtime
WORKDIR /app
COPY --from=vendor /app/vendor ./vendor
COPY . .

Séparer les dépendances de construction

La compilation des extensions nécessite autoconf, gcc et des en-têtes de développement — aucun de ces éléments ne doit se trouver dans l’environnement d’exécution. Utilisez l’installeur dans une étape de construction, puis copiez les fichiers .so compilés et le fichier conf.d ini correspondant dans une étape d’exécution propre.

FROM php:8.3-fpm-alpine AS ext-builder
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions redis igbinary opcache intl

FROM php:8.3-fpm-alpine AS runtime
# Copy compiled extensions + their enable configs
COPY --from=ext-builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
COPY --from=ext-builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/

Ordre de mise en cache des couches

Docker met les couches en cache de haut en bas et invalide tout ce qui se trouve sous une couche modifiée. Classez-les de la couche qui change le moins à celle qui change le plus souvent :

  • Base et extensions (rarement)
  • composer.lock et installation (occasionnellement)
  • Code source de l’application (à chaque validation)
  • Génération du chargement automatique (à chaque validation)

Ainsi, une modification limitée au code réutilise entièrement la couche vendor mise en cache.

# BAD: copying all source before composer install
# busts the vendor layer on every code change
COPY . .
RUN composer install

# GOOD: lock first, then source
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-autoloader
COPY . .
RUN composer dump-autoload --optimize

Montages de cache BuildKit

Avec BuildKit (DOCKER_BUILDKIT=1), vous pouvez monter un cache persistant qui survit aux constructions successives sans se retrouver dans l’image. C’est idéal pour le cache global de Composer, afin que les constructions répétées évitent de retélécharger les paquets.

# syntax=docker/dockerfile:1
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN --mount=type=cache,target=/tmp/composer-cache \
    COMPOSER_CACHE_DIR=/tmp/composer-cache \
    composer install --no-dev --prefer-dist

Mesurer la taille de l’image

Examinez la répartition des couches pour repérer les éléments superflus. docker history indique la taille ajoutée par chaque instruction ; des outils comme dive montrent l’espace gaspillé. L’objectif est d’obtenir une étape d’exécution sans compilateurs, sans Composer et sans dépendances de développement.

# Compare sizes
docker images myapp

# Per-layer contribution
docker history --no-trunc --format '{{.Size}}\t{{.CreatedBy}}' myapp:latest

# Deep inspection of wasted bytes
dive myapp:latest

Alléger l’étape finale

L’étape d’exécution ne doit PAS contenir Composer, le script extension-installer ni votre suite de tests. Copiez vendor et le code source depuis les étapes de construction ; n’exécutez jamais composer dans l’étape finale. Supprimez l’installeur après utilisation si vous devez l’exécuter à cet endroit.

FROM php:8.3-fpm-alpine AS runtime
WORKDIR /app

# bring extensions + vendor in from builders — no Composer here
COPY --from=ext-builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
COPY --from=ext-builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
COPY --from=vendor /app/vendor ./vendor
COPY . .

USER www-data
CMD ["php-fpm"]

Limites de Distroless / Scratch

PHP ne peut pas s’exécuter sur un scratch véritablement vide — il a besoin de libc et de bibliothèques partagées. Le minimum pratique est alpine (musl) ou une version minimale de Debian de type distroless. Alpine est la solution la plus petite, mais faites attention aux bibliothèques natives qui attendent glibc ; si vous rencontrez des erreurs de segmentation avec NSS/ICU, utilisez php:8.3-fpm-bookworm comme solution de repli.

# Smallest practical PHP runtime
FROM php:8.3-fpm-alpine

# If musl causes native-lib issues (e.g., some ICU edge cases),
# the glibc Debian slim variant is the safe fallback:
# FROM php:8.3-fpm-bookworm

Cibler les étapes

Un seul Dockerfile peut servir au développement et à la production grâce à --target. Ajoutez une étape dev au-dessus de l’étape d’exécution qui réinstalle les dépendances de développement de Composer et Xdebug ; construisez --target=runtime pour la production et --target=dev en local.

FROM runtime AS dev
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions xdebug @composer
USER root
RUN composer install   # includes dev deps

# Build prod:  docker build --target runtime -t app:prod .
# Build dev:   docker build --target dev     -t app:dev  .

Réfléchir à la taille des couches

Un modèle mental rapide vous aide à prévoir le comportement du cache. Cet extrait CLI simule l’erreur classique d’une croissance illimitée d’une couche par opposition à une croissance plafonnée, et montre pourquoi il est important d’intégrer le nettoyage au même RUN.

<?php
// Simulate layer sizes (MB) for two strategies
$installSteps = [120, 8, 8, 8];

// Separate RUN per step keeps temp files in layers
$separate = array_sum($installSteps);

// Single RUN with cleanup removes temp files before commit
$combined = max($installSteps); // peak, then cleaned

echo "Separate layers total: {$separate} MB\n";
echo "Combined+cleanup:       {$combined} MB\n";
echo 'Saved: ' . ($separate - $combined) . " MB\n";
?>

Combiner et nettoyer dans un seul RUN

Chaque RUN est une couche ; supprimer des fichiers dans une couche ultérieure ne réduit pas la taille de l’image, car les couches précédentes contiennent toujours les octets. Installez, utilisez et nettoyez au sein d’un seul RUN afin que les fichiers temporaires ne soient jamais intégrés à l’image.

RUN apk add --no-cache --virtual .build-deps $PHPIZE_DEPS && \
    pecl install redis && \
    docker-php-ext-enable redis && \
    apk del .build-deps && \
    rm -rf /tmp/pear /var/cache/apk/*

Vérification rapide

Pourquoi les dépendances de construction doivent-elles être supprimées dans le même RUN que celui où elles ont été installées ?

Récapitulatif

Les constructions à plusieurs étapes empêchent les compilateurs et les dépendances de développement d’entrer en production. Vous avez appris à nommer les étapes et à copier les artefacts avec COPY --from, à ordonner les couches de la moins à la plus volatile pour optimiser la mise en cache, à utiliser les montages de cache BuildKit pour Composer, à mesurer la taille avec docker history/dive, à choisir délibérément entre alpine et glibc, à cibler les étapes de développement et de production et à combiner l’installation et le nettoyage dans un seul RUN.

Gratuit pour commencer

Apprends PHP avec un tuteur IA — gratuit

Écris et exécute du vrai code dans ton navigateur, obtiens de l'aide instantanée d'un tuteur IA disponible 24h/24, et reprends là où tu t'es arrêté sur le web ou dans l'app.

Cours
49
Leçons
195

Questions Fréquemment Posées

La leçon « Compilations multi-étapes et optimisation » est-elle gratuite ?

Oui — le texte complet de « Compilations multi-étapes et optimisation » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours PHP Academy, passe à CoddyKit PRO. Le cours PHP Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Compilations multi-étapes et optimisation » ?

Réduisez la taille des images et séparez la compilation de l’exécution. Tu pratiques PHP Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer PHP Academy ?

Aucune expérience préalable n'est requise. PHP Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Compilations multi-étapes et optimisation » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon PHP Academy ?

Oui. Chaque leçon PHP Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Conteneuriser une application PHP
  2. Compilations multi-étapes et optimisation
  3. Docker Compose pour les environnements locaux
  4. CI/CD avec GitHub Actions
← Retour à PHP Academy