Skip to main content

Comment conteneuriser une application PHP en toute sécurité avec Docker

Écrit par
Headshot of James Olaogun

James Olaogun

feature docker secrets

2 août 2023

0 minutes de lecture

Note de la rédaction : 10 août 2023

Cet article a été mis à jour pour inclure une version plus récente de PHP dans le tutoriel.

Imaginons que vous ayez créé une application PHP, mais que vous souhaitiez la séparer de l’infrastructure qui la prend en charge, tout en conservant une solution légère, portable et suffisamment sécurisée. Vous aimeriez que d’autres développeurs puissent travailler dessus sans avoir à recréer des environnements entiers. En bref, vous voulez conteneuriser votre application, c’est-à-dire la regrouper avec ses dépendances dans des conteneurs faciles à partager entre différents environnements.

La solution de conteneurisation la plus populaire aujourd’hui est Docker, une plateforme open source lancée en 2013. Depuis, cette technologie est largement adoptée dans le développement logiciel pour isoler les applications, créer des composants CI/CD réutilisables et permettre des déploiements rapides.

Ce tutoriel vous explique étape par étape comment conteneuriser en toute sécurité une application PHP, ou plus précisément, la « dockeriser ». Vous utiliserez également Snyk, une plateforme de sécurité destinée aux développeurs qui fournit des outils de sécurité pour les applications modernes afin d’identifier les vulnérabilités et d’automatiser leur correction.

Prérequis et recommandations

Avant de vous lancer dans le tutoriel ci-dessous, prenez un instant pour vérifier que vous disposez des outils suivants :

  • Docker installé sur votre machine. Vous l’utiliserez pour exécuter et gérer le conteneur PHP.

  • Un compte Snyk gratuit. Les outils d’analyse de sécurité de Snyk mettront en évidence les vulnérabilités des conteneurs et vous aideront à les corriger.

  • NPM ou Yarn pour installer et exécuter le Snyk CLI.

  • Une application PHP de base. Ce tutoriel utilise un projet Laravel nouvellement créé.

Une fois que vous êtes sûr de pouvoir satisfaire à ces exigences, prenez connaissance des quelques conseils suivants avant de poursuivre le tutoriel. Ces recommandations vous aideront à dockeriser votre application PHP de manière fluide et sécurisée.

Utilisez une version spécifique de l’image de base

Veillez toujours à utiliser une version précise de l’image Docker lors de la création de votre application. Par exemple, au lieu de récupérer PHP-FPM, vous pouvez préciser la version de l’image et récupérer PHP:8.0-fpm. Notez que l’image de base que vous utiliserez dépendra des exigences de version de votre application.

Ainsi, vous avez la certitude que votre application est basée sur une version connue, testée et stable. Vous savez également que cette version de l’image peut utiliser la même plateforme sous-jacente et les mêmes dépendances dans différents environnements, ce qui peut améliorer la reproductibilité et la cohérence.

N’utilisez pas ADD pour les dépendances distantes

La commande ADD peut télécharger des fichiers depuis des URL quelconques, ce qui risque d’introduire des vulnérabilités de sécurité dans votre application dockerisée. Je vous recommande donc d’éviter la commande `ADD` dans les fichiers Dockerfile pour inclure des dépendances distantes.

Utilisez plutôt la commande COPY pour copier des fichiers depuis le système de fichiers local. La commande COPY garantit que seuls les fichiers nécessaires à l’application sont inclus dans l’image Docker. Là encore, cela contribue à réduire le risque de vulnérabilités.

Utilisez un fichier YAML docker-compose

Docker Compose vous permet de gérer et d’orchestrer vos conteneurs Docker en définissant votre application Docker dans un fichier YAML et en indiquant comment elle doit être créée et exécutée. Voici quelques avantages de Docker Compose :

  • Séparer les composants de l’application. Docker Compose vous permet de répartir les composants de votre application dans différents conteneurs. Cela limite la surface d’attaque de chaque conteneur et réduit le risque de point de défaillance unique.

  • Utiliser des variables d’environnement. Docker Compose vous permet de configurer votre application à l’aide de variables d’environnement, ce qui peut vous aider à gérer en toute sécurité des informations sensibles, comme les mots de passe de base de données.

  • Gérer les connexions réseau. Docker Compose vous permet de gérer les connexions réseau entre vos conteneurs. Vous vous assurez ainsi que vos conteneurs ne peuvent communiquer entre eux que par un canal sécurisé.

Si vous avez installé Docker Desktop pour Windows, Mac ou Linux, Docker Compose est déjà inclus.

Utilisez PHP-FPM, pas mod_php

PHP-FPM et mod_php sont deux solutions permettant d’exécuter des applications PHP sur des serveurs web, mais leur fonctionnement diffère. mod_php est un module Apache qui permet au serveur web Apache de traiter les fichiers PHP, tandis que PHP-FPM est un gestionnaire de processus PHP compatible avec différents serveurs web, notamment NGINX et Apache.

PHP-FPM est généralement considéré comme une solution plus efficace et évolutive pour exécuter des applications PHP, en particulier dans les environnements à fort trafic.

Utilisez une construction en plusieurs étapes

La construction en plusieurs étapes est une technique Docker qui permet de créer des images plus légères et plus sécurisées. En définissant plusieurs étapes dans un fichier Dockerfile, chacune avec ses propres instructions, vous évitez de recréer toute l’image depuis zéro à chaque modification. Vous améliorez ainsi l’efficacité et la vitesse du processus de construction Docker.

Testez toujours la sécurité de votre application dockerisée

Des tests de sécurité réguliers sont essentiels pour garantir et améliorer la sécurité de votre application. Docker fournit un environnement isolé pour l’exécuter, mais cela ne garantit pas sa sécurité. Effectuez régulièrement des contrôles de sécurité afin d’identifier et de corriger les vulnérabilités potentielles avant que des attaquants ne puissent les exploiter.

Cinq étapes pour conteneuriser en toute sécurité votre application PHP

Passons maintenant à la pratique ! Le tutoriel ci-dessous vous guide en cinq étapes pour dockeriser en toute sécurité une application PHP Laravel, en appliquant certains des conseils que nous venons de voir.

1. Configurez le fichier Dockerfile avec Apache

Créez un projet Laravel si vous n’en avez pas déjà un, puis utilisez la commande cd pour accéder au répertoire du nouveau projet Laravel. Dans la commande ci-dessous, par exemple, remplacez {{laravel-application-directory}} par le nom du répertoire de votre application Laravel.

cd {{laravel-application-directory}} 

Créez un fichier nommé Dockerfile à la racine du répertoire de votre application Laravel :

touch Dockerfile

Copiez-collez le code suivant dans le fichier Dockerfile que vous venez de créer :

FROM composer:latest as composer
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --prefer-dist --no-scripts --no-dev --no-autoloader && \
    composer clear-cache
COPY . .
RUN composer dump-autoload --no-scripts --no-dev --optimize

# Depending on the composer you use, you may be required to use a different php version.
FROM php:8.2-apache
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public

# 1. Install production packages and clean up apt cache.
RUN apt-get update && apt-get install -y \
    libbz2-dev \
    libfreetype6-dev \
    libicu-dev \
    libjpeg-dev \
    libmcrypt-dev \
    libpng-dev \
    libonig-dev \
    libzip-dev \
    libreadline-dev \
    sudo \
    zip \
 && rm -rf /var/lib/apt/lists/*

# 2. Apache configs + document root.
RUN echo "ServerName laravel-app.local" >> /etc/apache2/apache2.conf
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

# 3. mod_rewrite for URL rewrite and mod_headers for .htaccess extra headers like Access-Control-Allow-Origin-
RUN a2enmod rewrite headers

# 4. Start with base PHP config, then add extensions.
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

RUN docker-php-ext-install \
    bcmath \
    bz2 \
    calendar \
    iconv \
    intl \
    mbstring \
    opcache \
    pdo_mysql \
    zip

# 5. Copy the application code from the composer stage.
COPY --from=composer /app /var/www/html

# 6. Create a non-root user to run the application.
ARG uid
RUN useradd -G www-data,root -u $uid -d /home/devuser devuser
RUN mkdir -p /home/devuser/.composer && \
    chown -R devuser:devuser /home/devuser

USER devuser
RUN echo "export PATH=$PATH:/var/www/html/vendor/bin" >> /home/devuser/.bashrc

Comme indiqué plus haut, PHP-FPM est la meilleure méthode pour créer une solution évolutive. Ce tutoriel utilise toutefois mod_php, car l’application est de petite taille.

Notez également que le contenu du fichier Dockerfile ci-dessus utilise une construction en plusieurs étapes. La première étape utilise l’image Composer officielle pour installer les dépendances de l’application et créer l’autoloader. La deuxième étape utilise l’image PHP/Apache officielle pour exécuter l’application. Notez que la commande COPY sert à copier les fichiers de compilation Composer depuis le système de fichiers local, et non la commande ADD.

Créez un fichier nommé docker-compose.yml à la racine du répertoire de votre application Laravel :

Touch docker-compose.yml

Copiez-collez le code suivant dans le fichier docker-compose.yml que vous venez de créer :

version: '3'

services:
  snykdemoapp:
    build:
      context: '.'
      args:
        uid: 1000
    container_name: snykdemoapp
    image: snykdemoapp
    ports:
      - 8000:80
    environment:
      - APACHE_RUN_USER=#1000
      - APACHE_RUN_GROUP=#1000
    volumes:
      - .:/var/www/html
    networks:
      app-network:
        aliases:
          - snykdemoapp

networks:
  app-network:
    name: app-network

Dans le code précédent, le service snykdemoapp correspond au conteneur de l’application PHP. La section networks définit également le réseau app-network que Docker Compose utilisera pour les communications.

2. Ajoutez un conteneur de base de données MySQL à docker-compose.yml

Ajoutons un conteneur MySQL à votre fichier docker-compose.yml. Ce conteneur hébergera la base de données de votre application Laravel.

Créez un nouveau service pour votre conteneur MySQL en ajoutant le code suivant comme nouveau service dans le fichier docker-compose.yml créé à la première étape :

app_db:
    image: mysql:5.7
    container_name: app_db
    volumes:
      - ./run/var:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=securerootpassword
      - MYSQL_DATABASE={{database_name}} 
      - MYSQL_USER={{database_user}}
      - MYSQL_PASSWORD={{dbuser_password}}
    networks:
      app-network:
        aliases:
          - app_db

Dans le bloc de code précédent :

  • app_db est le nom du service de base de données créé à partir de l’image MySQL version 5.7. Vous pouvez choisir le nom de votre choix, mais veillez à le modifier également dans les autres services auxquels il est associé.

  • {{database_name}} correspond au nom de base de données de votre choix.

  • {{database_user}} correspond au nom d’utilisateur de base de données de votre choix.

  • {{dbuser_password}} correspond au mot de passe de votre choix pour l’utilisateur de la base de données.

Et voilà : vous avez ajouté un conteneur MySQL à votre configuration Docker.

3. Ajoutez un conteneur PHPMyAdmin à docker-compose.yml

Ajoutons maintenant un conteneur PHPMyAdmin à côté de vos conteneurs Laravel et MySQL, pour les besoins du développement et des tests locaux. PHPMyAdmin est un outil d’administration open source et gratuit pour MySQL et MariaDB. Il fournit une interface web qui vous permet de gérer vos bases de données. Il est recommandé de n’utiliser PHPMyAdmin qu’en développement, et non en production.

Créez un nouveau service pour votre conteneur PHPMyAdmin en ajoutant l’extrait de code ci-dessous comme nouveau service dans le fichier docker-compose.yml.

phpmyadmin:
    image: phpmyadmin/phpmyadmin
    links:
      - app_db
    environment:
      PMA_HOST: app_db
      PMA_PORT: 3306
    ports:
      - '8080:80'
    networks:
      app-network:
        aliases:
          - phpmyadmin

Dans le bloc de code précédent, phpmyadmin est le nom du service PHPMyAdmin créé à partir de l’image phpmyadmin/phpmyadmin. La section environment définit la variable PMA_HOST sur app_db, qui est le nom du service MySQL dans le même fichier docker-compose.yml.

Vous disposez maintenant d’un conteneur PHPMyAdmin configuré pour fonctionner avec vos conteneurs Laravel et MySQL. Gardez à l’esprit que l’image PHPMyAdmin ne doit être utilisée qu’à des fins de développement. Son utilisation en production représente un risque de sécurité pour votre application.

4. Créez et exécutez l’application PHP Laravel avec Docker

Maintenant que votre fichier Dockerfile et votre fichier docker-compose.yml sont configurés, démarrez le service Docker et vérifiez qu’il est bien en cours d’exécution. Vous pouvez ensuite créer et exécuter l’application PHP Laravel à l’aide des commandes suivantes :

  • docker-compose build : crée l’image Docker.

  • docker-compose up -d : démarre les conteneurs.

  • docker ps : vérifie l’état du conteneur.

Si toutes les commandes ci-dessus s’exécutent correctement, ouvrez votre navigateur web et accédez à http://localhost:8000/ pour afficher la page d’accueil de votre application Laravel.

Page d’accueil de Laravel affichant des liens vers la documentation, Laracasts, Laravel News et son écosystème dynamique.

Vous pouvez également accéder à http://localhost:8080/ pour ouvrir l’interface PHPAdmin. Connectez-vous à l’aide des valeurs MYSQL_USER et MYSQL_PASSWORD définies dans votre fichier docker-compose.yml.

Écran d’accueil de phpMyAdmin, avec l’anglais sélectionné et des champs pour saisir le nom d’utilisateur et le mot de passe

5. Testez et sécurisez votre application PHP avec Snyk

Une fois votre application Docker créée et accessible dans votre navigateur, tout comme PHPMyAdmin, l’étape suivante consiste à tester la sécurité de l’application dockerisée. Ce tutoriel utilise Snyk pour tester et vérifier que l’application dockerisée est entièrement sécurisée.

Connectez-vous ou créez un compte Snyk à l’aide de l’un des fournisseurs d’authentification unique (SSO) proposés sur la page. Installez Snyk CL et authentifiez votre ordinateur portable, comme indiqué dans la section consacrée aux prérequis de cet article.

Écran d’inscription à Snyk avec les options GitHub et Google, à côté d’un panneau décrivant l’analyse des vulnérabilités et leur correction.

Une fois Snyk configuré, utilisez Snyk CLI pour évaluer la sécurité de votre application dockerisée. Exécutez la commande suivante à la racine du répertoire de votre application Laravel :

snyk container test {{your-image}} –file=Dockerfile

Dans la ligne précédente, {{your-image}} correspond au nom de l’image que vous souhaitez tester. Vous pouvez utiliser la commande `docker ps` pour obtenir la liste des images Docker de votre application.

Lorsque vous exécutez la commande précédente sur l’image PHP 8.2 de base nommée snykdemoapp dans ce tutoriel, vous obtenez le résultat suivant :

Résultats de l’analyse d’une image de conteneur PHP 8.2, affichant l’état des vulnérabilités de sécurité détectées par Snyk Container.

PHP 8.2 est la dernière version bénéficiant du support à long terme. Même si 69 problèmes de sécurité ont été détectés dans l’image de base de ce conteneur, ils sont tous de faible gravité.

Si vous utilisiez des versions antérieures de PHP dans vos applications de production, comme PHP 7.4, vous découvririez des vulnérabilités de sécurité plus graves et urgentes à corriger. Snyk est alors d’autant plus utile, car la solution vous propose d’autres types d’images présentant moins de vulnérabilités.

La commande snyk container test ne fournit qu’un résultat ponctuel. Il est préférable d’exécuter la commande container monitor pour analyser le conteneur.

snyk container monitor {{your-image}}

La commande container monitor envoie à Snyk les informations sur le test de l’image de votre conteneur. Snyk peut ainsi afficher ces informations dans votre tableau de bord et vous avertir de l’apparition éventuelle de vulnérabilités dans votre image.

Lorsque vous exécutez container monitor sur l’image PHP 7.4 de base nommée snykdemoapp.

Tableau de bord des projets Snyk affichant le manifeste composer.lock d’une image Docker et une liste de 113 dépendances

Comment corriger les vulnérabilités détectées dans votre application PHP

Maintenant que vous avez testé votre conteneur PHP, voici quelques conseils pour corriger les vulnérabilités détectées.

  • Reconstruisez l’image pour bénéficier des dernières mises à jour de sécurité de l’image de base Docker en amont. Vous vous assurerez ainsi que toutes les mises à jour de sécurité sont intégrées à votre application. Après la reconstruction, relancez l’analyse de sécurité afin d’identifier et de corriger les vulnérabilités susceptibles d’être introduites par les dernières mises à jour de sécurité de l’image de base.

  • Consultez l’ évaluation des vulnérabilités fournie par Snyk. Cette liste peut vous renseigner utilement sur les problèmes de sécurité potentiels liés aux dépendances de l’application.

  • Gardez à l’esprit que les vulnérabilités peuvent provenir de diverses sources. Il peut s’agir de l’environnement d’exécution PHP, des outils et des bibliothèques installés dans l’image de base. Il est essentiel de mettre régulièrement à jour et de surveiller tous les composants de la pile applicative afin que les vulnérabilités soient rapidement identifiées et corrigées.

Conclusion

En suivant quelques bonnes pratiques, vous pouvez développer une application moins vulnérable. Si vous avez suivi le tutoriel pas à pas, vous devriez être en mesure de développer en toute sécurité une application PHP conteneurisée avec Docker, en utilisant la plateforme de sécurité Snyk pour détecter et corriger les vulnérabilités.

Vous trouverez sur GitHub tout le code utilisé pour l’application Laravel conteneurisée de ce tutoriel.

La sécurité des conteneurs, pensée pour les développeurs

Snyk détecte et corrige automatiquement les vulnérabilités dans les images de conteneurs et les workloads Kubernetes.

Lire la suite

feature customer snowflake
Article

Sécuriser dès la conception : découvrez l’intégration de Snyk Studio à Snowflake Cortex Code

Snyk Studio s’intègre à Snowflake Cortex Code pour analyser le code généré par l’IA, les dépendances et les conteneurs à la recherche de vulnérabilités, dès le développement.

blog feature pypi spoof
Article

La Snyk AI Security Platform complète, gratuite pour les responsables de projets open source

Les responsables de projets open source croulent sous les signalements de vulnérabilités avérées et ont besoin d’aide pour les prioriser, les corriger et déployer les correctifs plus rapidement. Le Secure Developer Program de Snyk donne aux projets admissibles un accès gratuit à la Snyk AI Security Platform.

feature insights announcement
Blog

Compromission de la chaîne d’approvisionnement Node-gyp : un ver npm à propagation autonome dissimulé dans binding.gyp

Un nouveau ver npm détourne binding.gyp pour déclencher node-gyp lors de l’installation et permettre à des packages malveillants d’exécuter du code sans scripts de cycle de vie. Il vole des identifiants, s’installe durablement sur GitHub et se propage de mainteneur en mainteneur.