RootsLabs

More than a tool ! GitHub Google+ LinkedIn RSS

Docker, un environnement de développement versionnable

Progi1984 - Commentaires (2)

Docker est un logiciel libre qui permet d’embarquer dans un container virtuel une application. Cela permet ainsi non plus de virtualiser un système mais de virtualiser un processus, et c’est pourquoi on parle parfois de virtualisation légère. Dans notre exemple, nous allons mettre en place Docker ainsi qu’un environnement de développement basé sur Nginx, PHP-fpm et MySQL.

Logo Docker

Pour une explication approfondie de Docker, je vous conseille l’article de Nicolargo : Virtualisation légère avec Docker.

Installation & Configuration de Docker

Sous Windows, l’installation se fait via un installeur standard. Dans mon cas, le seul truc que je n’ai pas coché est Git, car je l’avais déjà installé.
Après installation, on lance une ligne de commande, on se déplace dans dossier et on tape quelques commandes.

  1. On vérifie les machines présentes sur le système :
    c:\wamp\www\myProject>docker-machine ls
    NAME   ACTIVE   DRIVER   STATE   URL   SWARM   DOCKER   ERRORS
    

    Normalement, cela devrait être vide.

  2. On crée la machine par défaut :
    c:\wamp\www\myProject>docker-machine create --driver virtualbox default
    Running pre-create checks...
    Creating machine...
    (default) Copying C:\Users\\.docker\machine\cache\boot2docker.iso to C:\Users\\.docker\machine\machines\default\boot2docker.iso...
    (default) Creating VirtualBox VM...
    (default) Creating SSH key...
    (default) Starting the VM...
    (default) Check network to re-create if needed...
    (default) Waiting for an IP...
    Waiting for machine to be running, this may take a few minutes...
    Detecting operating system of created instance...
    Waiting for SSH to be available...
    Detecting the provisioner...
    Provisioning with boot2docker...
    Copying certs to the local machine directory...
    Copying certs to the remote machine...
    Setting Docker configuration on the remote daemon...
    Checking connection to Docker...
    Docker is up and running!
    To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env default
    
  3. On définit les variables d’environnements :
    c:\wamp\www\myProject>docker-machine env --shell cmd default
    SET DOCKER_TLS_VERIFY=1
    SET DOCKER_HOST=tcp://192.168.99.100:2376
    SET DOCKER_CERT_PATH=C:\Users\\.docker\machine\machines\default
    SET DOCKER_MACHINE_NAME=default
    REM Run this command to configure your shell:
    REM     FOR /f "tokens=*" %i IN ('docker-machine env --shell cmd default') DO %i

    A ce niveau, on copie et exécute dans l’invite de commandes les lignes commençant par « SET ».

    Référence : https://docs.docker.com/machine/reference/env/

Configuration de notre environnement via Docker Compose

Notre environnement sera composé d’un fichier docker-compose.yml.

La base de notre environnement sera :

  • une base de données : MySQL
  • un serveur Web : NGinx
  • et PHP

Un article suivra pour configurer d’autres outils comme SASS, PHPMyAdmin, MailDev ou Sentry.

Configurer MySQL

Dans le fichier YAML, nous allons ajouter ces lignes :

## MySQL
db:
  image: mysql
  restart: always
  ports:
    - "3306:3306"
  environment:
    MYSQL_ROOT_PASSWORD: rootpassword
    MYSQL_DATABASE: myprojet
    MYSQL_USER: user
    MYSQL_PASSWORD: pass

Nous allons utiliser l’image Docker fourni officiellement : https://hub.docker.com/_/mysql/.
Pour pouvoir se connecter au port 3306 de MySQL, il faut définir le port de sortie qui sera le même.
Ensuite, l’image MySQL a des variables d’environnements que l’on peut définir :

  • MYSQL_ROOT_PASSWORD : permet de définir le mot de passe root (obligatoire) ;
  • MYSQL_DATABASE : permet de définir la base de données à créer (facultatif) ;
  • MYSQL_USER : permet de définir l’utilisateur MySQL à créer (facultatif) ;
  • MYSQL_PASSWORD : permet de définir le mot de passe de l’utilisateur MYSQL_USER (facultatif) ;

Configurer Nginx

Après MySQL, nous allons configurer le serveur Web. A la fin du fichier docker-compose.yml, nous allons ajouter ces lignes :

## Server Nginx
web:
  image: nginx
  restart: always
  ports:
    - "80:80"
  volumes:
    - ./:/var/www/local.dev
    - ./.docker/nginx:/etc/nginx/conf.d
  links:
    - php:php

Pareil, nous partons sur l’image officielle fourni par Docker : https://hub.docker.com/_/nginx/.
Pour utiliser le port 80 de Nginx, il faudra que l’on définisse un port de sortie, et qui comme MySQL sera le même.
Nous allons passer aux volumes : ce sont des dossiers un peu spéciaux qui permettent de connecter un lien dans le container vers un dossier soit d’un autre container, soit sur le système hôte.
Nous allons en configurer deux :

  • Dans le container, le dossier « /var/www/local.dev » pointera vers le dossier « ./ », soit la racine de notre projet ;
  • Dans le container, le dossier « /etc/nginx/conf.d » pointera vers le dossier « ./.docker/nginx ».

Précisons que certains containers ont besoin de fichier de configuration ou emplacement de stockage. Dans notre cas, Nginx a besoin d’un fichier de configuration : default.conf qui est censé se trouver dans le dossier « /etc/nginx/conf.d » du container, soit au niveau de notre dossier : « ./.docker/nginx ».

Le fichier default.conf est simple. Je n’irais pas plus dans les détails le concernant si ce n’est le fastcgi_pass : celui pointe vers le port 9000 du container php que l’on lie via le noeud « links ».

server {
    listen 80;
    server_name localhost;
    root /var/www/local.dev/www;
    index index.php index.html index.htm;
    sendfile off;

	location / {
        # try to serve file directly, fallback to front controller
        try_files $uri /index.php$is_args$args;
    }

    # location ~ ^/index\.php(/|$) {
    location ~ ^/(index|index_dev)\.php(/|$) {
        fastcgi_pass    php:9000;

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param HTTPS off;
    }

    # Return 404 for all php files as we do have a front controller
    location ~ \.php$ {
        return 404;
    }
}

Configurer PHP

On a notre serveur Web et une base de données : il ne nous manque plus que PHP pour pouvoir compléter notre environnement.

Pour PHP, nous allons compiler nous-même PHP afin de pouvoir utiliser les extensions que l’on souhaite.

Modifions tout d’abord le fichier docker-compose.yml :

## PHP
php:
  build: .docker/php
  restart: always
  volumes:
    - ./:/var/www/local.dev
    - ./.docker/php/ini:/usr/local/etc/php
  links:
    - db:db

Contrairement aux deux autres containers, nous n’allons pas passer par une image mais un build. Le noeud build a besoin du chemin, relatif à l’emplacement du fichier docker-compose.yml, du dossier où se trouvera le fichier Dockerfile pour builder le container.

Les volumes liés sont :

  • Dans le container, le dossier « /var/www/local.dev » pointera vers le dossier « ./ », soit la racine de notre projet ;
  • Dans le container, le fichier « /usr/local/etc/php » pointera vers le fichier « ./.docker/php/ini »

Le container lié est cette fois le container « db » pour que le container « php » puisse faire une requête MySQL vers celui-ci.

Il nous reste deux fichiers à définir : le fichier Dockerfile pour générer le container PHP, et le fichier php.ini (à placer dans le dossier « ./.docker/php/ini/ ») qui contiendra la configuration de PHP.

Le fichier Dockerfile de PHP est le suivant :

## On se base sur le container officiel PHP en version 5.6-fpm
FROM php:5.6-fpm

## On met à jour, on installe les pré-requis et on installe les extensions PHP
RUN apt-get update && apt-get install -y \
        libfreetype6-dev \
        libjpeg62-turbo-dev \
        libmcrypt-dev \
        libpng12-dev \
        libsqlite3-dev \
        libssl-dev \
        libcurl3-dev \
        libxml2-dev \
        libzzip-dev \
    && docker-php-ext-install iconv json mcrypt mbstring mysql mysqli pdo_mysql pdo_sqlite phar curl ftp hash session simplexml tokenizer xml xmlrpc zip \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install gd

## On installe XDebug et on crée le fichier de configuration
RUN pecl install xdebug \
    && touch $PHP_INI_DIR/conf.d/xdebug.ini \
    && echo 'zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so' >> $PHP_INI_DIR/conf.d/xdebug.ini \
    && echo 'xdebug.remote_enable=1' >> $PHP_INI_DIR/conf.d/xdebug.ini \
    && echo 'xdebug.remote_connect_back=1' >> $PHP_INI_DIR/conf.d/xdebug.ini \
    && echo 'xdebug.var_display_max_depth=10' >> $PHP_INI_DIR/conf.d/xdebug.ini \
    && echo 'xdebug.cli_color=1' >> $PHP_INI_DIR/conf.d/xdebug.ini \
    && echo 'xdebug.show_local_vars=1' >> $PHP_INI_DIR/conf.d/xdebug.ini

## On définit le dossier de travail	
WORKDIR /var/www

## On build PHP en mode FPM
CMD ["php-fpm"]

Avant de lancer notre serveur, nous allons générer notre container PHP. Pour cela, on lance la commande :

c:\wamp\www\myProject>docker-compose build php

Je ne vous affiche pas le log car avec la génération de PHP, cela prend un nombre conséquent de lignes.

Le fichier php.ini est le suivant :

display_errors=1
error_reporting=E_ALL
;upload_max_filesize = 200M
;post_max_size = 40M

Configurer le partage avec Boot2Docker

Attention, ce chapitre est pour les utilisateurs de Windows.

On va configurer le partage entre le système hôte (votre ordinateur) et Boot2Docker.
Pour cela, il faut ajouter un partage au niveau de la machine virtuelle de Boot2Docker :

c:\wamp\www\myProject>"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" sharedfolder add "default" --name "c/wamp" --hostpath "C:\wamp"

Via cette ligne de commande, on ajoute un dossier partagé à la machine virtuelle nommé « default » sous le nom « c/wamp » du dossier « C:\wamp » présent sur le système hôte.

Autoriser les ports de Boot2Docker

Attention, ce chapitre est pour les utilisateurs de Windows.

On va faire de la translation de ports en mappant le port 80 de la VM vers le port 80 sur le réseau local.

c:\wamp\www\myProject>"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm "default" --natpf1 "web,tcp,,80,,80"

Via cette ligne de commande, on redirige le port 80 vers le port 80 de la VM.
Il faut le faire pour chaque port venant de nos containers que l’on sort sur le réseau.

Utiliser notre environnement de développement

Maintenant que tout est configuré dans notre fichier docker-compose.yml, on va lancer notre environnement.

Pour les utilisateurs de Windows, on vérifie que Boot2Docker est lancé et sinon on le lance.

c:\wamp\www\myProject>docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL   SWARM   DOCKER    ERRORS
default   -        virtualbox   Stopped                 Unknown

c:\wamp\www\myProject>docker-machine start default
Starting "default"...
(default) Check network to re-create if needed...
(default) Waiting for an IP...
Machine "default" was started.
Waiting for SSH to be available...
Detecting the provisioner...
Started machines may have new IP addresses. You may need to re-run the `docker-machine env` command.

c:\wamp\www\myProject>docker-machine ls
NAME      ACTIVE   DRIVER       STATE     URL                         SWARM   DOCKER    ERRORS
default   -        virtualbox   Running   tcp://192.168.99.100:2376           v1.10.0

On lance la commande suivante pour enregistrer les variables d’environnement :

c:\wamp\www\myProject>FOR /f "tokens=*" %i IN ('docker-machine env --shell cmd default') DO %i

On se connecte en SSH à Boot2Docker pour activer le partage de dossiers :

c:\wamp\www\Github\myProject>docker-machine ssh
                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/
 _                 _   ____     _            _
| |__   ___   ___ | |_|___ \ __| | ___   ___| | _____ _ __
| '_ \ / _ \ / _ \| __| __) / _` |/ _ \ / __| |/ / _ \ '__|
| |_) | (_) | (_) | |_ / __/ (_| | (_) | (__|   <  __/ |
|_.__/ \___/ \___/ \__|_____\__,_|\___/ \___|_|\_\___|_|
Boot2Docker version 1.10.0, build master : b09ed60 - Thu Feb  4 20:16:08 UTC 2016
Docker version 1.10.0, build 590d5108
docker@default:~$ sudo su
root@default:/home/docker# mount -t vboxsf -o uid=1000,gid=50 "c/wamp" /c/wamp
root@default:/home/docker# exit
docker@default:~$ exit

Ou en plus court :

c:\wamp\www\Github\myProject>docker-machine ssh default "sudo mount -t vboxsf -o uid=1000,gid=50 \"c/wamp\" /c/wamp"

On récupère l’IP de Boot2Docker :

c:\wamp\www\myProject>docker-machine ip
192.168.99.100

Après cela, il ne manque plus qu’à lancer la machine :

c:\wamp\www\myProject>docker-compose up

Et d’aller dans votre navigateur pour tester l’IP :
Résultat final de Docker Compose

Conclusion

Les plus perspicaces d’entre vous auront remarqué le mot « versionnable » d’entre vous. Grâce au fait que notre environnement de développement n’est basé que sur des fichiers avec principalement le fichier docker-compose.yml, tout devient versionnable et vous pouvez ainsi votre les évolutions de votre environnement pour tester des outils et revenir en arrière.
Le seul souci qui me reste à traiter reste le fait de voir à chaque démarrage de Boot2Docker de de voir gèrer les variables d’environnement et monter le point de montage. Mais peut-être que Docker nous aidera dans une prochaine version, ou qu’un des lecteurs a une solution à me proposer. N’étant pas un expert Docker, je reste ouvert à tous commentaires.

Commentaires

1. Quoi de neuf Docker ? - Le blog de Jean-Mich, le 3 mars 2016 à 13:50

[…] RootsLabs nous donne un exemple assez complet d’utilisation. […]

2. RootsLabs » Docker: utiliser SASS, PHPMyAdmin, MailDev et Sentry, le 14 mars 2016 à 10:00

[…] mon précédent article, j’ai mis en place un environnement de développement basé sur des containers Docker avec Nginx, PHP-fpm et MySQL. Dans cet article, nous allons mettre en place différents containers Docker pour installer les […]

Ajouter un commentaire

Commentaire :