0Pricing
PHP Academy · Leçon

Conteneuriser une application PHP

Écrivez un Dockerfile PHP prêt pour la production.

Conteneuriser une application PHP est une leçon PHP Academy gratuite sur CoddyKit. Ceci est la leçon 1 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 conteneuriser PHP

Distribuer PHP de manière reproductible signifie figer la version exacte de l'interpréteur, les extensions et les bibliothèques du système d'exploitation avec votre code. Une image Docker donne à chaque environnement — ordinateur portable, intégration continue, production — le même php -v et le même ensemble ext-*.

Dans cette leçon, nous construisons une image prête pour la production : PHP-FPM, uniquement les extensions nécessaires, des configurations ajustées, un utilisateur sans privilèges et une vérification d'état.

Base FPM ou Apache

Les images PHP officielles existent en plusieurs variantes. Pour une application web de production derrière nginx ou traefik, préférez php:8.3-fpm-alpine (petite) ou php:8.3-fpm (Debian, glibc — moins de surprises avec les bibliothèques natives).

  • cli — processus de travail, files d'attente, tâches planifiées
  • fpm — gestionnaire de processus FastCGI, à associer à nginx
  • apache — Apache intégré, pratique mais plus lourd

Figez la version mineure. N'utilisez jamais :latest en production.

# Base image choice in your Dockerfile
FROM php:8.3-fpm-alpine AS base

# Why alpine? ~30MB base vs ~140MB Debian.
# Tradeoff: musl libc, occasional native-extension friction.

Installer les extensions

Dans ces images, n'exécutez jamais apt install php-xxx — utilisez les assistants intégrés docker-php-ext-install, docker-php-ext-configure et pecl. Le script install-php-extensions (mlocati) est le raccourci de fait qui récupère pour vous les bons fichiers d'en-tête de développement.

FROM php:8.3-fpm-alpine

# Grab the helper that resolves build deps automatically
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 \
        pdo_mysql \
        opcache \
        intl \
        zip \
        redis \
        bcmath

Composer dans l'image

Copiez le binaire Composer depuis son image officielle plutôt que d'utiliser curl pour télécharger un installateur. Exécutez composer install avec --no-dev et --optimize-autoloader pour la production, et copiez d'abord uniquement composer.json/composer.lock afin que la couche de dépendances se mette en cache indépendamment des modifications du code source.

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

WORKDIR /app

# Cache-friendly: deps layer invalidates only when lock changes
COPY composer.json composer.lock ./
RUN composer install \
        --no-dev \
        --no-scripts \
        --no-autoloader \
        --prefer-dist

COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative

Ajuster php.ini

L'image de base fournit les modèles php.ini-production et php.ini-development. Activez celui de production, puis déposez vos propres surcharges dans conf.d — ce répertoire est fusionné en dernier, il prévaut donc.

Valeurs de production essentielles : opcache.enable=1, opcache.validate_timestamps=0 (code immuable dans l'image) et une valeur raisonnable pour memory_limit.

# Activate production ini
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Custom overrides win because conf.d loads last
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/zz-app.ini

Le fichier de surcharge d'OPcache

C'est le gain de production le plus important. Avec validate_timestamps=0, PHP ne consulte jamais l'état des fichiers à chaque requête — mais cela signifie que vous MUST reconstruire l'image pour déployer les modifications (c'est exactement ce que nous voulons pour des conteneurs immuables).

; docker/php/zz-app.ini
memory_limit = 256M
expose_php = Off

opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.preload = /app/preload.php
opcache.preload_user = www-data

Exécuter sans privilèges

L'image définit déjà www-data. Exécuter FPM en tant que superutilisateur augmente inutilement la surface d'attaque. Définissez la propriété des chemins accessibles en écriture (cache, journaux) et changez d'utilisateur avec USER avant CMD.

Le processus maître de FPM écoute tout de même sur des ports privilégiés ? Non — FPM écoute sur le port 9000 (non privilégié), donc l'exécution sans privilèges est simple.

# Make runtime-writable dirs owned by the runtime user
RUN chown -R www-data:www-data /app/var /app/storage 2>/dev/null || true

USER www-data

EXPOSE 9000
CMD ["php-fpm"]

Vérifications d'état

Les orchestrateurs ont besoin d'un signal indiquant que FPM est réellement actif, pas seulement que le processus existe. cgi-fcgi peut interroger le point de terminaison FPM /status ou /ping. Activez d'abord pm.status_path et ping.path dans le groupe de processus FPM.

# In www.conf pool config:
;   ping.path = /ping
;   ping.response = pong

# Dockerfile HEALTHCHECK using cgi-fcgi
RUN install-php-extensions @composer >/dev/null 2>&1 || true

HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
  CMD SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET \
      cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1

Assembler le Dockerfile

Voici un Dockerfile de production cohérent à une seule étape. Dans la prochaine leçon, nous le diviserons en plusieurs étapes pour supprimer les outils de construction. Notez l’ordre : dépendances → configuration → code source → chargement automatique → changement d’utilisateur.

FROM php:8.3-fpm-alpine

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 pdo_mysql opcache intl zip redis

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/

COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative && \
    chown -R www-data:www-data /app/var

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

Vérifier la construction

Après la construction, effectuez une vérification rapide de ce qui a effectivement été intégré à l’image : la version de PHP, les extensions chargées et la désactivation de la validation d’OPcache. Un script CLI rapide confirme le contrat d’exécution dont dépend votre application.

<?php
// Run inside the container: php verify.php
echo 'PHP ' . PHP_VERSION . PHP_EOL;

$required = ['pdo_mysql', 'opcache', 'intl', 'zip'];
foreach ($required as $ext) {
    printf("%-12s %s\n", $ext, extension_loaded($ext) ? 'OK' : 'MISSING');
}

var_dump((bool) ini_get('opcache.enable'));
?>

Hygiène du contexte de construction

Un .dockerignore réduit la taille du contexte de construction et empêche les informations sensibles et la surcharge liée à vendor de se retrouver dans l’image et d’invalider le cache. Excluez vendor, VCS, les fichiers env et les outils locaux.

# .dockerignore
.git
.gitignore
vendor/
node_modules/
.env
.env.*
tests/
*.md
docker-compose*.yml
storage/logs/*
var/cache/*

Vérification rapide

Pourquoi définir opcache.validate_timestamps=0 dans une image de production ?

Récapitulatif

Vous avez construit une image PHP-FPM de production : une base 8.3-fpm-alpine épinglée, les seules extensions nécessaires installées via le script d’installation, Composer et les dépendances mises en cache copiés dans leur propre couche, le php.ini de production activé avec une surcharge d’OPcache, le passage à www-data et l’ajout d’une vérification de santé FPM.

Bonnes pratiques essentielles : épingler les versions, mettre en cache la couche des dépendances, s’exécuter sans privilèges root, désactiver la validation des horodatages et conserver un contexte de construction réduit avec .dockerignore.

Questions Fréquemment Posées

La leçon « Conteneuriser une application PHP » est-elle gratuite ?

Oui — le texte complet de « Conteneuriser une application PHP » 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 « Conteneuriser une application PHP » ?

Écrivez un Dockerfile PHP prêt pour la production. 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 1 sur 4.

Combien de temps prend la leçon « Conteneuriser une application PHP » ?

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