Cet article est la suite de la présentation que j’ai pu faire sur Docker : Comprendre et mettre en place Docker. J’ai eu quelques retours pertinents et je tenais à revenir sur des points qui me semblent importants.

Les networks

Je ne l’avais pas précisé, mais sur Docker il existe un network par défaut. Son nom est bridge et si vous ne changez pas la configuration, tous les containers seront associés à ce réseau. Qu’est-ce que cela change pour nous ? Si vous n’avez pas besoin d’isoler vos containers entre eux, ils pourront tous communiquer ensemble sur ce réseau sans avoir à utiliser les links par exemple. Pour cela, il faudra utiliser soit l’adresse IP du container, soit passer par le nom donné à un container via --name.

Vous pouvez lister vos networks avec la commande suivante :

$ docker network ls

Les dépendances entre containers

Les links ne servent pas qu’à cela pour autant. Au-delà de créer des réseaux privés entre les containers pour faire transiter des informations sensibles, ils permettent de définir un ordre de lancement et des dépendances entre vos containers ainsi que de permettre la création d’alias pour le nom de vos containers.

Par exemple, si votre container s’appelle mysql, mais que pour un autre service vous avez besoin qu’il se nomme database, vous pouvez créer un alias sous la forme --link mysql:database. Si le deuxième argument est le même que le premier, il devient optionnel. Ainsi, dans votre configuration de base de données, vous pourrez alors entrer pour l'host directement : database au lieu de mettre l’adresse IP du container ou mysql.

Pour les dépendances maintenant, dans le cas d’un docker-compose up -d la question ne se pose pas, car tous les containers sont lancés sans condition.

En revanche, si vous avez besoin de lancer un container qui en a besoin d’un autre (je pense à un container PHP, pour lancer des tests, qui aurait besoin d’un container MySQL par exemple), avec la commande docker-compose run ou docker-compose exec, Docker ne pourra pas savoir que le container PHP a besoin de celui de MySQL pour fonctionner. Il lancera alors uniquement le container que vous avez demandé et vos tests échourrons.

links permet de lancer les containers qui sont dépendants entre eux.

Dans le cas où il n’y a pas de links, on remarque qu’aucun autre container n’est lancé. En revanche, docker-compose créer un network pour ne pas utiliser celui par défault et ainsi garder une isolation entre vos projets.

$ docker-compose run --rm blog-server ./vendor/bin/phpunit
Creating network "laravelblog_default" with the default driver
PHPUnit 6.4.4 by Sebastian Bergmann and contributors.
...

Dans le cas où on utilise les links, tous les autres containers dépendants sont également lancés :

$ docker-compose run --rm blog-server ./vendor/bin/phpunit
Creating laravelblog_redis_1 ...
Starting laravelblog_mysql_1 ...
Starting laravelblog_mysql-test_1 ... done
Creating laravelblog_redis_1 ... done
PHPUnit 6.4.4 by Sebastian Bergmann and contributors.
...

Depuis que les networks sont personnalisables, il n’est plus vraiment conseillé d’utiliser les links qui ont été deprecated. En effet, si vous avez besoin d’isoler des containers entre eux, il est préférable d’utiliser un nouveau network en particulier et de gérer les dépendances en utilisant depends_on.

Une version simplifiée de notre ancien docker-compose.yml ressemblerait à cela :

services:
  blog-server:
-    links:
+    depends_on:
      - mysql
      - mysql-test
      - redis

Network personnalisé

Comme on vient de le voir, on peut définir des networks personnalisés, il faut les définir à deux endroits. D’une part, au même niveau que les services pour les créer, on les appelle les top-level networks et dans les services eux-mêmes pour s’en servir, les service-level networks. Même si le groupe networks est défini après celui des services dans votre docker-compose.yml, ils seront créées avant quoi qu’il arrive.

Pour définir un network avec docker-compose :

services:
  blog-server:
    depends_on:
      - mysql

networks:
  backend:
    driver: bridge

Dans cet exemple, on a créé un réseau nommé backend avec le driver bridge, qui est le driver utilisé par défaut sur Docker. Vous pouvez trouver toutes les options disponibles sur la documentation officielle. Je ne vais pas toutes les présenter, je pense qu’il est seulement intéressant de savoir comment cela fonctionne, le reste dépendra de vos besoins.

Un service peut rejoindre un ou plusieurs networks :

services:
  blog-server:
    depends_on:
      - mysql
    networks:
      - backend
      - frontend

networks:
  backend:
    driver: bridge
  frontend:
    driver: bridge

Le nom des networks créés avec docker-compose seront de la forme [projectname]_[networkname] donc dans notre cas ce sera laravelblog_backend. On peut alors inspecter un container avec la commande :

$ docker inspect <container_id>

Vous pouvez également créer des networks avec Docker :

$ docker network create --driver bridge <network_name>

Et pour rejoindre un network lorsqu’on lance un container :

$ docker run --name blog-server -v $(pwd):/application --network <network_name> -d laravel-blog

Dans la section des networks, on remarquera qu’il y en a bien deux avec une IP distinctes pour le même container en fonction du réseau.

Si toutefois, vous n’avez pas besoin de créer un réseau pour des cas particuliers, il est conseillé d’utiliser le réseau par défaut sachant que docker-compose le fait pour vous.

J’ai mis à jour mon docker-compose.yml pour le projet laravel-blog si vous voulez l’exemple complet.

Merci !