Qu'allons nous voir
Nous allons voir comment mettre sur pied avec Docker un environnement de développement Web complet ( LAMP ) en quelques minutes ( si l'on compte uniquement le temps de déploiement, et non la lecture de ce post. ).
Mais surtout , rendre cet environnement facilement configurable pour qu'il réponde à vos attentes.
Au programme, nous aurons donc 3 conteneurs
- Apache 2.4.25, avec prise en charge des "virtualhosts"
- Php 5.6 Fpm, avec les principaux modules mysqli, pdo, gd, xdebug, redis, opcache, json, mcrypt ...
- Mysql 5.6.36
Petit plus, nous aurons à disposition, un fichier de configuration permettant l'utilisation de la fonction mail() de php.
Pour lancer facilement ces conteneurs Docker, nous utiliseront l'outil docker-compose, qui permet en un seul fichier de déclarer notre environnements et bien plus encore.
Pour les plus pressés : Si vous ne souhaitez pas créer les répertoires et fichiers de conf à la main en suivant tout le billet, vous pouvez directement cloner le projet puis lancer ( Après avoir installé Docker sur votre machine évidemment ). Rendez-vous tout en bas de cette page, dans la section Go go go.
Installation de Docker et docker-compose
Franchement, il n'y a rien de compliqué, je ne vais pas détailler spécialement la méthode , juste vous donner les liens pour les différents systèmes.
Après, il suffit de suivre.
Docker CE
Docker-Compose
Bonne nouvelle pour les utilisateurs de Mac & Windows, l'outil est automatiquement installé avec Docker.
Pour les utilisateurs Linux, je conseille la commande pip
sudo pip install docker-compose
Le projet LAMP
Parfait, nous avons tout les outils nécessaires pour atteindre notre objectif.
Commençons par créer un répertoire qui contiendra l’ensemble des fichiers de configuration et le code source de nos futurs projets Web .
mkdir -p dockerlamp/www dockerlamp/docker/apache/vhosts dockerlamp/docker/mysql dockerlamp/docker/php
Voici en résumé ce que ça donne :
dockerlamp ├── docker │ ├── apache │ │ └── vhosts │ ├── mysql │ ├── php └── www
Nous aurons donc les fichiers de configuration dans le répertoire docker/ et le code source sera dans le répertoire www/
docker-compose.yml
Je vais pas tourner autour du pot, je vais tout de suite vous donner le contenu complet du fichier docker-compose.yml, nous verrons ensuite les différents points à compléter.
Créez donc le fichier docker-compose.yml à la racine du répertoire dockerlamp/
# Adopt version 2 syntax: # https://docs.docker.com/compose/compose-file/#/versioning version: '2' volumes: database_data2: driver: local services: ########################### # Setup the Apache container ########################### httpd: container_name: dockerapache_httpd_1 restart: always image: httpd:2.4.25 ports: - 80:80 volumes: - ./docker/apache/httpd.conf:/usr/local/apache2/conf/httpd.conf - ./docker/apache/vhosts/:/usr/local/apache2/conf/vhosts volumes_from: - php ########################### # Setup the PHP container ########################### php: container_name: dockerapache_php_1 restart: always build: ./docker/php/ expose: - 9000 volumes: - ./www/:/usr/local/apache2/htdocs - ./docker/php/ssmtp.conf:/etc/ssmtp/ssmtp.conf:ro - ./docker/php/php-mail.conf:/usr/local/etc/php/conf.d/mail.ini:ro ########################### # Setup the Database (MySQL) container ########################### mysql: container_name: dockerapache_mysql_1 restart: always image: mysql:5.6.36 expose: - 3306 volumes: - database_data2:/var/lib/mysql - ./docker/mysql/conf-mysql.cnf:/etc/mysql/mysql.conf.d/conf-mysql.cnf:ro environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: project MYSQL_USER: project MYSQL_PASSWORD: project
Configuration Apache
Afin de configurer finement le service Apache, nous allons récupérer le fichier httpd.conf et le déposer dans le répertoire dockerlamp/docker/apache/
Voici le lien de téléchargement httpd.conf
La seule modification faite à ce fichier ( comparé à la version d'origine ) est la prise en charge des virtualhosts.
Nous allons par conséquent également récupérer le virtualhost par défaut et le placer dans le répertoire dockerlamp/docker/apache/vhosts/
Voici le lien de téléchargement 000-default.conf
Pour les curieux, si vous éditez le fichier 000-default.conf, vous verrez que l'on utilise le module proxy d'apache pour gérer les sources php . Nous passons ces sources au service nommé "php" sur le port 9000.
Nous en avons terminé avec le service apache . Passons au service php.
Configuration php-fpm
Contrairement au service apache, le conteneur php-fpm doit être modifié, pour ne serait-ce qu'installer les extensions.
Nous allons donc créer un fichier Dockerfile, qui contiendra toutes les instructions pour finaliser notre container .
La bonne pratique
J'aurais pu simplement créer une image du container sur dockerHub et la mettre à disposition, mais pour partager une image modifiée, la bonne pratique consiste à utiliser comme base l'image officielle ( php ), puis d'ajouter explicitement les changements à apporter dans un DockerFile.
Ce qui vous permet d'être certain que l'image finale n'est pas corrompue.
Dockerfile
créez le fichier Dockerfile dans le répertoire dockerlamp/docker/php/, comme précisé dans docker-compose.yml.
FROM php:5.6-fpm # install the PHP extensions we need RUN set -ex; \ \ apt-get update; \ apt-get install -y \ libjpeg-dev \ libpng12-dev \ libmcrypt-dev \ ssmtp \ ; \ rm -rf /var/lib/apt/lists/*; \ \ docker-php-ext-configure gd --with-png-dir=/usr --with-jpeg-dir=/usr; \ docker-php-ext-install gd mysqli opcache pdo_mysql json mcrypt; \ pecl install -o -f xdebug redis \ && rm -rf /tmp/pear \ && echo "extension=redis.so" > /usr/local/etc/php/conf.d/redis.ini \ && echo "zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so" > /usr/local/etc/php/conf.d/xdebug.ini; # TODO consider removing the *-dev deps and only keeping the necessary lib* packages # set recommended PHP.ini settings # see https://secure.php.net/manual/en/opcache.installation.php RUN { \ echo 'opcache.memory_consumption=128'; \ echo 'opcache.interned_strings_buffer=8'; \ echo 'opcache.max_accelerated_files=4000'; \ echo 'opcache.revalidate_freq=2'; \ echo 'opcache.fast_shutdown=1'; \ echo 'opcache.enable_cli=1'; \ } > /usr/local/etc/php/conf.d/opcache-recommended.ini RUN { \ echo '[xdebug]'; \ echo 'xdebug.default_enable = 0'; \ } >> /usr/local/etc/php/conf.d/xdebug.ini RUN { \ echo 'error_reporting = E_ALL'; \ echo 'log_errors = On'; \ echo 'display_errors = Off'; \ } > /usr/local/etc/php/php.ini CMD ["php-fpm"] EXPOSE 9000
php7-fpm : Si vous préférez une autre version de php, il vous suffit de la changer sur la première ligne ( ex : FROM php:7.1.5-fpm ).
Toutes les versions sont listées ici.
fonction mail()
Puisque nous utilisons le service php à l'intérieur d'un container, seul ce service est disponible ( bien qu'il soit possible de lancer plusieurs services dans un même conteneur, cette méthode n'est pas conseillée ), le service sendmail n'est pas disponible.
Pour palier à ce problème, nous allons utiliser ssmtp. Cet utilitaire ne fait que rediriger les mails vers un serveur SMTP externe.
Pour le configurer ( l'activer au sein de php et définir quel serveur SMTP utiliser ), nous allons ajouter deux fichiers dans le répertoire dockerlamp/docker/php/
- php-mail.conf
- ssmtp.conf
php-mail.conf
Ce fichier de configuration ( chargé comme un php.ini supplémentaire ) ne fait que surcharger le chemin de l’exécutable sendmail afin d'utiliser ssmtp.
[mail function] sendmail_path = "/usr/sbin/ssmtp -t"
ssmtp.conf
Ce fichier vous permet de définir quel serveur SMTP utiliser pour envoyer vos mails.
Par exemple, pour utiliser un compte Gmail:
mailhub=smtp.gmail.com:587 [email protected] AuthPass=mypassword FromLineOverride=YES hostname=dockerdev.foo.net UseSTARTTLS=YES
Seules les 3 premières lignes sont à adapter selon votre cas.
Nous en avons terminé avec la configuration de php-fpm. Passons à Mysql
Configuration Mysql
C'est presque le service le plus simple... dans le fichier docker-compose, nous avons défini des variables d'environnements, qui spécifient le mot de passe du compte root, une base de données à créer avec un utilisateur associé (login et mot de passe) .
Par la suite, si vous devez ajouter une nouvelle base de données, deux possibilités .
- Ajouter les informations dans le fichier docker-compose, et relancer le conteneur
- Se connecter en root sur le service mysql et créer manuellement la base de données et son utilisateur .
Nous allons créer le fichier conf-mysql.cnf, dans le répertoire dockerlamp/docker/mysql/ ce fichier est automatiquement monté dans le conteneur Mysql à son démarrage et permet donc de modifier simplement la configuration de mysql .
Par exemple, si l'on souhaite modifier la variable sql_mode
[mysqld] sql_mode = "STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
Note : Vous pouvez laisser ce fichier vide si vous n'en avez pas l'utilité pour le moment. Mais il doit être présent dans le répertoire mysql !
Notre environnement LAMP est maintenant prêt !
Lancer l'environnement LAMP
Puisque nous avons configuré notre environnement via un fichier docker-compose.yml, nous allons évidemment utiliser la commande docker-compose pour le lancer.
Placez-vous à la racine du projet dockerlamp/
docker-compose up -d
Cette commande va construire les volumes, les interfaces réseaux, télécharger les images nécessaires, construire les conteneurs si besoin ( via le Dockerfile ) et enfin ... les exécuter en tache de fond . Oui oui .. tout ça en une seule commande .. le pied!
Le test
Nous allons tester notre stack, apache et php.
Créez deux fichiers dans le répertoire www/
- info.php
- index.html
info.php
<?php echo phpinfo();
index.html
<h1>Hello World</h1>
Enfin ouvrez un navigateur et entrez ces URLs :
Vous devriez normalement voir un magnifique Hello World, et la page d'infos de php !
Un vrai projet
Je ne vais pas vous laisser avec un simple phpinfo() et un Hello World !!
Nous allons aller au bout des choses, en installant par exemple un petit Drupal.
L'objectif est d'installer Drupal et qu'il soit accessible ( sur votre machine ) depuis l'url http://drupal.local/
Le Vhost
Afin de pouvoir utiliser un nom de domaine locale, ( drupal.local ), il faut auparavant renseigner le fichier hosts, pour le déclarer .
Linux et Mac
sudo sh -c "echo '127.0.0.1 drupal.local' >> /etc/hosts"
Windows
Pour Windows vous devez ouvrir le fichier c:\Windows\System32\Drivers\etc\hosts en administrateur avec NotePad et y ajouter la ligne :
127.0.0.1 drupal.local
Maintenant, nous allons créer notre vhost afin qu'Apache sache quoi faire lorsqu'il reçoit les requêtes avec le nom de domaine drupal.local.
Editer le fichier dockerlamp/docker/apache/vhosts/drupal.conf
<VirtualHost *:80> ServerAdmin [email protected] ServerName drupal.local <Directory /> AllowOverride All Require all granted </Directory> DocumentRoot "/usr/local/apache2/htdocs/drupal" <Directory "/usr/local/apache2/htdocs/drupal"> Options Indexes FollowSymLinks AllowOverride All Require all granted </Directory> <FilesMatch \.php$> # 2.4.10+ can proxy to unix socket # SetHandler "proxy:unix:/var/run/php5-fpm.sock|fcgi://localhost/" # Else we can just use a tcp socket: SetHandler "proxy:fcgi://php:9000" </FilesMatch> </VirtualHost>
On a donc déclaré le nom de domaine à Apache, en lui spécifiant de pointer sur le répertoire drupal/
Les sources
Puisque nous avons demandé à Apache de pointer sur le répertoire drupal/, nous allons télécharger les sources de Drupal dans ce répertoire qui lui-même se trouve dans le répertoire dockerlamp/www/
cd www wget https://ftp.drupal.org/files/projects/https://ftp.drupal.org/files/projects/drupal-8.3.2.tar.gz tar xzf drupal-8.3.2.tar.gz mv drupal-8.3.2 drupal mkdir -p drupal/sites/default/files/translations && chmod -R 777 sites/default/files/translations chmod -R 777 drupal/sites/default/files touch drupal/sites/default/settings.php && chmod 777 drupal/sites/default/settings.php
Enfin, pour que le conteneur Apache prenne en considération notre nouveau vhost, nous allons redémarrer notre stack
docker-compose restart
L'installation
Pour l'installation, il suffit de pointer sur notre nom de domaine local et suivre les instructions
http://drupal.local/
Arrivé à l'installation de la base de données, remplissez le formulaire comme ceci ( Base de données déclarée dans le fichier docker-compose.yml ),
- Nom de la base de données : project
- Utilisateur : project
- Mot de passe : project
- Et dans options avancés > Hôte : mysql
Après cette étape, Drupal s'installe tranquillement sur votre environnement
Remplissez les formulaires durant l'installation, vous devriez rapidement arriver sur la page d'accueil de votre Drupal fraîchement installé .
Conclusion
Vous avez à disposition un environnement de développement complet comme démontré avec Drupal.
Pour chaque projet vous devez donc
- Créer un domaine local dans votre fichier hosts
- Créer la configuration du virtualHost pour apache
- Récupérer les sources et les placer dans le répertoire www/
- Relancer la stack LAMP via docker-compose
Voici quelques outils / lignes de commandes pour vous aider à travailler, "debugger".
Vous trouverez ces petits scripts dans le répertoire tools/ du dépôt dockerlamp.
Ces scripts ne représentent qu'une base pour vous aider à travailler, je vous laisse maintenant parcourir la documentation de Docker pour comprendre les différentes commandes / configurations utilisées dans ce billet.
N’hésitez pas à poser des questions si besoin.
Créer un dump d'une base de données
dump_sql.sh
docker exec dockerapache_mysql_1 /usr/bin/mysqldump --databases -uroot -psecret $DATABASE > $DATABASE.sql
Restaurer/Importer une base de donnée depuis un dump sql
restore_sql.sh
cat $DUMP | docker exec -i dockerapache_mysql_1 /usr/bin/mysql -uroot -psecret
Afficher les logs Apache en temps réel ( Pour débugger )
logs.sh
docker logs --tail 100 -f dockerapache_httpd_1
Afficher les ressources utilisées par les conteneurs sur votre machine
stats.sh
docker stats --format "table {{.Container}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}"
Go go go
On clone l'environnement
git clone https://[email protected]/cdesaintleger/dockerlamp.git && cd dockerlamp
On Configure le smtp
cp docker/php/ssmtp.conf.dist docker/php/ssmtp.conf && vim docker/php/ssmtp.conf
On lance la stack
docker-compose up -d