docker

Docker PHP / Apache / Magento

Dans le cadre de mon travail, j’ai du m’initier à Docker afin de containeriser un environnement Magento 1 / Magento 2. Le but était d’éviter d’avoir une machine virtuelle par site, mais une seule qui nous permet de gérer tous les projets. L’OS de base est un windows, et ne gère pas les liens symboliques. Vous allez voir que ca peut poser son lot de problèmes !

Qu’est ce que Docker ?

Pour ceux qui sont restés endormie les 10 dernières années 😉 – Docker c’est un peu comme une machine virtuelle mais avec ce qu’on appelle des containers. Les containers présentent un avantage important. Alors que la virtualisation consiste à exécuter de nombreux systèmes d’exploitation sur un seul et même système, les containers se partagent le même noyau de système d’exploitation et isolent les processus de l’application du reste du système. En gros, on gagne en souplesse et en performance.

Build et Dockerfile :

Lorsque vous créer un container, vous avez 2 choix:

  • le mode image: créer un container basé sur une image toute faite, disponible sur le hub docker.
  • le mode build: créer un container personnalisé avec l’installation de vos dépendances. Vous partez aussi d’une image, mais vous en modifiez le comportement. C’est plus souple, mais aussi plus contraignant.

Les container pour un site Magento:

J’ai besoin d’un Apache/PHP, d’un mysql, d’un phpmyadmin, d’un mailcatcher et d’un redis. Pour chaque élément sélectionné, vous devez créer un service dans un fichier qui se nomme docker-compose.yml . Sur chaque service, vous ajoutez des paramètres (user, password, fichiers de config, zone datetime, réseau…). On peut d’aider d’un fichier .env par exemple pour ne pas mettre le mot de passe plusieurs fois. Ce qu’il faut retenir, c’est que souvent, vous allez modifier un fichier, un port qui pointe de votre PC vers le container. La syntaxe est donc:
fichier source:fichier destination ou port source:port destination.
Voici un exemple pour modifier par défaut la conf du site PHP My Admin:
./phpdocker/apache2/003-phpmyadmin.conf:/etc/apache2/sites-enabled/003-phpmyadmin.conf

Un assistant à la création du docker-compose est disponible sur phpdocker.io mais il ne gère que nginx, et pas Apache.

Personnalisation d’apache:

Lorsque vous créer un container Apache, vous avez plusieurs images sources. Suivant celle pour laquelle vous allez opter, vous allez vous retrouver avec des configurations différentes. Apache2 qui s’appelle httpd, des répertoires sites-enable qui n’existent pas… Personnellement, je m’y retrouve avec la conf type Debian, Ubuntu, donc j’ai opté pour l’image php:7.2-apache.

Ensuite, il faut activer toutes les extensions PHP et les programmes dont nous avons besoin. C’est un peu comme installer un serveur vierge, et il faut tout anticiper, sinon vous êtes bon pour vous recréer votre image avec la commande: docker-compose build web avant de pouvoir vous en servir et ça vous prendra quelques minutes.
Au passage, faites attention aux librairies freetype et gd qui ne sont pas faciles à implémenter et qui permettent par exemple de gérer les captcha images sous Magento 2. J’ai aussi ajouter magerun qui permet d’ajouter des fonctions très utiles pour Magento.

Voici mon Dockerfile complet pour Apache:

FROM php:7.2-apache
WORKDIR "/application"

# Fix debconf warnings upon build
ARG DEBIAN_FRONTEND=noninteractive

#Enable Apache modules
RUN a2enmod rewrite && a2enmod expires && a2enmod ssl && a2enmod headers && a2enmod deflate && a2enmod http2 && a2enmod include && a2enmod env && a2enmod proxy_http && a2enmod proxy && service apache2 restart

# Install selected extensions and other stuff
RUN rm /etc/apt/preferences.d/no-debian-php
RUN apt-get update \
    && apt-get -y --no-install-recommends install sendmail iputils-ping stow libfreetype6-dev libjpeg62-turbo-dev vim nano gnupg apt-transport-https wget libssl-dev libpng-dev composer php-memcached php-xml php-mysql php-redis php-sqlite3 php-bz2 php-gd php-bcmath php-soap php-ssh2 php-xmlrpc php-xsl php-intl composer php-pdo-mysql curl php-curl libcurl3-dev libxml2-dev nodejs npm libxslt-dev libzip-dev \
    && apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*

# Install git
RUN apt-get update \
    && apt-get -y install git \
    && apt-get clean; rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/*

#Enable freetype
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/freetype2 --with-png-dir=/usr/include --with-jpeg-dir=/usr/include

#Enable PHP EXT
RUN docker-php-ext-install gd pdo_mysql intl exif fileinfo gettext ftp iconv mbstring pdo simplexml soap sockets xml xmlrpc xsl zip curl bcmath

#Add some conf
RUN echo 'memory_limit = 1G' >> /usr/local/etc/php/conf.d/docker-php-memlimit.ini;

#NPM and YARN
RUN npm install -g npm
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update && apt-get install yarn

#Magerun M1
RUN cd /usr/local/bin/ \
    && wget https://files.magerun.net/n98-magerun.phar \
    && chmod +x ./n98-magerun.phar \
    && ln -sf n98-magerun.phar magerun

#Magerun M2
RUN cd /usr/local/bin/ \
    && wget https://files.magerun.net/n98-magerun2.phar \
    && chmod +x ./n98-magerun2.phar \
    && ln -sf n98-magerun2.phar magerun2

(sauvegardez bien cette conf, car avant d’en avoir une qui marche aussi bien , vous allez passer du temps !)

NPM, Yarn, Gulp et autres soucis de dépendances:

Lorsque vous travaillez sur un répertoire partagé entre votre Windows, et votre OS invité (linux), vous ne pouvez pas avoir de liens symboliques. Et si il y a une application qui travaille avec des liens, c’est bien node ! Pour éviter toutes les problèmes de dépendances, je vous invite donc à utiliser yarn install –ignore-engines –no-bin-links. Ca vous installera tout ce qu’il vous faut sans liens, et sans tenir compte des problèmes de versionning de node. Ensuite à vous de vous faire un petit alias pour appeler gulp par exemple. Type:

alias gogulp='docker exec -i web bash -c "cd /application/monprojet && ./node_modules/gulp/bin/gulp.js"'

Exécuter des commandes sous Docker:

Pour lancer des commandes à un container, soit vous aller dedans avec un bash, soit vous utiliser la syntaxe docker exec. Voici un exemple:

docker exec -i web bash -c "cd /application/monprojet && php bin/magento setup:static-content:deploy -f"


Magento 2 et les problèmes de liens symboliques:

Sur Magento 2, il y a tous les fichier statics qui sont gérés en liens symboliques. Il faut donc désactiver tout ça, et ca passe par 2 actions:
– désactiver le versionning des statics via la commande :
UPDATE core_config_data SET value = ‘0’ WHERE core_config_data.path = ‘dev/static/sign’;
– désactiver les liens dans app/etc/di.xml en modifiant la ligne:
Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink
par
Magento\Framework\App\View\Asset\MaterializationStrategy\Copy

Conclusion:

Sous Magento 1, aucun problème, tout est rapide, la compilation via Gulp et les sass fonctionne nickel. On gagne donc en souplesse. En revanche, sur Magento 2, les temps d’accès sont très mauvais. Par exemple, l’injection de dépendances passe de 45 secondes à 10 minutes ! Je pense que c’est dû à cette histoire de liens symboliques et du coup, ça casse toute la démarche. Au final, je vais surement devoir retester avec l’intégration du noyau Linux (WSL2), et ça pourra peut-être se faire, soit vous basculez votre poste en full linux, et là ça devrait fonctionner.
Voici le lien vers la version WSL 2 qui elle fonctionne nickel 🙂

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.