Docker-compose et le COMPOSE_PROJECT_NAME
Rédigé par uTux 2 commentairesDocker-compose est un outil permettant d'utiliser docker à l'aide d'un simple fichier .yml, facilitant ainsi grandement la vie et les interactions entre les containers d'un même service. Mais il n'est pas exempt de bugs ou de défauts de conception.
Le défaut dont je vais parler concerne le nommage des containers. Prenons par exemple deux projets docker : projet1 et projet2 avec l'arborescence suivante :
.
├── projet1
│ └── src
│ └── docker-compose.yml
└── projet2
└── src
└── docker-compose.yml
Nos docker-compose.yml sont identiques et commandent le lancement d'un simple container nginx :
# projet1/src/docker-compose.yml
version: '3'
services:
nginx:
image:
nginx:latest
Et :
# projet2/src/docker-compose.yml
version: '3'
services:
nginx:
image:
nginx:latest
Voyons ce qui arrive lorsque je démarre mon projet1 :
utux@docker:~/projet1/src$ docker-compose up -d
Creating src_nginx_1 ...
Creating src_nginx_1 ... done
On voit que notre container a été nommé src_nginx_1 suivant la logique suivante : $dossier_$service_$numero. Très bien. Démarrons maintenant le projet2 :
utux@docker:~/projet2/src$ docker-compose up -d
src_nginx_1 is up-to-date
docker-compose dit que le container existe déjà alors que non ! En fait il applique le même raisonnement et veut nommer le container src_nginx_1 aussi alors qu'il existe déjà ! C'est un défaut de conception et c'est problématique car en cas de modification sur l'un des projets, docker-compose va recréer les containers, et donc écraser ceux de l'autre...
Pour palier à ce problème, plusieurs solutions sont possibles :
- Nommer différemment votre dossier de travail. Ce n'est pas toujours possible car on peut avoir un environnement de dev et un environnement de prod avec les mêmes chemins.
- Utiliser l'attribut container_name mais c'est un peu fastidieux car il faut le faire sur tous les services du docker-compose.yml
- Utiliser la variable d'environnement COMPOSE_PROJECT_NAME. Malheureusement on ne peut pas la définir dans le docker-compose.yml malgré les demandes répétées des utilisateurs (ici et là) il faut la mettre dans un fichier .env dans votre projet.
Exemple d'utilisation du COMPOSE_PROJECT_NAME :
.
├── projet1
│ └── src
│ ├── docker-compose.yml
│ └── .env
└── projet2
└── src
├── docker-compose.yml
└── .env
Avec nos fichiers .env :
# projet1/src/.env
COMPOSE_PROJECT_NAME=projet1
Et :
# projet2/src/.env
COMPOSE_PROJECT_NAME=projet2
Démarrons maintenant notre projet1 puis notre projet2 :
utux@docker:~$ cd projet1/src/
utux@docker:~/projet1/src$ docker-compose up -d
Creating network "projet1_default" with the default driver
Creating projet1_nginx_1 ...
Creating projet1_nginx_1 ... done
utux@docker:~/projet1/src$ cd ../../projet2/src/
utux@docker:~/projet2/src$ docker-compose up -d
Creating network "projet2_default" with the default driver
Creating projet2_nginx_1 ...
Creating projet2_nginx_1 ... done
Cette fois les deux projets cohabitent bien et ne se marchent plus sur les pieds. La preuve :
utux@docker:~/projet2/src$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eacabeb7e961 nginx:latest "nginx -g 'daemon ..." 4 seconds ago Up 2 seconds 80/tcp projet2_nginx_1
9477b31d2035 nginx:latest "nginx -g 'daemon ..." 16 seconds ago Up 14 seconds 80/tcp projet1_nginx_1
En conclusion il ne faut pas avoir une confiance aveugle en docker-compose, qui est un outil bien pratique mais manifestement sujet à des défauts de conception. Imaginez ce genre de confusion de nommage, voire d'écrasement de containers en production. Utilisez COMPOSE_PROJECT_NAME et testez vos projets en pré-production avant de déployer sur la prod.