Docker-Composer des projets avec des noms de services identiques
Utilisez le nom du service Docker-Compose uniquement si le service se trouve uniquement sur le réseau interne du projet Docker-Compose.
![post main image](/static/blog/posts/media/images/blog-post-39ba77e6035e4c55a022075617544a2b-5843-docker-compose-projects-with-identical-service-names.jpg)
Si nous avons des projets Docker-Compose identiques avec des noms de service identiques, reliés par un réseau Docker , nous devons nous assurer que nous accédons au bon service. Sur un réseau Docker , il y a deux façons d'accéder à un service :
- Par le nom du service
- Par le nom du conteneur
J'ai plusieurs projets Docker-Compose qui sont presque identiques, chaque projet est dans son propre répertoire et a son propre environnement.
J'ai supposé qu'un service à l'intérieur d'un projet Docker-Compose utiliserait toujours un autre service à l'intérieur du même projet Docker-Compose en utilisant le nom du service (et non le nom du conteneur). Et qu'il produirait une erreur s'il n'était pas disponible. Je me suis trompé. Ce qui se passe en fait, c'est que vous pouvez accéder au service avec le même nom dans un autre projet Docker-Compose.
Comme toujours, j'utilise Ubuntu 22.04.
Configuration du projet
Nous avons deux répertoires avec nos projets (presque) identiques.
├── my_app1
│ ├── docker-compose.yml
│ └── .env
├── my_app2
│ ├── docker-compose.yml
│ └── .env
Les deux fichiers 'docker-compose.yml' sont identiques. Les fichiers '.env' sont différents, ils ne contiennent qu'une seule variable d'environnement, la 'COMPOSE_PROJECT_NAME'. Cette variable n'est pas seulement utilisée pour créer les noms des conteneurs, nous l'utilisons également à l'intérieur de nos conteneurs pour identifier le projet Docker-Compose.
Nous utilisons ici le 'nicolaka/netshoot' Docker image . Il contient de nombreux utilitaires utiles, y compris un 'netcat' fonctionnel, 'nc', que nous utilisons pour créer des daemons d'écoute.
Voici les fichiers :
# my_app1/.env
COMPOSE_PROJECT_NAME=my_app1
et
# my_app2/.env
COMPOSE_PROJECT_NAME=my_app2
et
# docker-compose.yml
version: '3.7'
x-service_defaults: &service_defaults
env_file:
- ./.env
restart: always
services:
app:
<< : *service_defaults
image: nicolaka/netshoot
command: bash -c "echo \"From ${COMPOSE_PROJECT_NAME} - app:\" | /usr/bin/nc -l 80"
networks:
- internal_network
- app_network
web:
<< : *service_defaults
image: nicolaka/netshoot
command: bash -c "echo \"From ${COMPOSE_PROJECT_NAME} - web:\" | /usr/bin/nc -l 81"
networks:
- internal_network
- app_network
networks:
internal_network:
app_network:
external:
name: my_app_network
Avant de commencer, nous créons le réseau externe Docker :
docker network create my_app_network
Quelques vérifications
Ouvrez des terminaux et démarrez les deux projets en exécutant cette commande dans chaque répertoire :
docker-compose up
Vérifiez que les conteneurs suivants ont été créés et fonctionnent :
my_app1_app_1
my_app1_web_1
my_app2_app_1
my_app2_web_1
Maintenant, dans un autre terminal, exécutez :
docker run -it --network=my_app_network --rm busybox
Accédez à un service dans nos conteneurs en utilisant le nom du conteneur :
telnet my_app_1_app_1 80
La réponse sera la suivante :
Connected to my_app1_app_1
From my_app1 - app:
Cela fonctionne comme prévu. Tapez du texte. Ce texte sera répercuté. Vous pouvez également le vérifier dans le terminal du projet 'my_app1' Docker-Compose.
Génération de l'erreur
Nous entrons d'abord dans le service 'app' du projet 'my_app1' :
docker exec -it my_app1_app_1 bash
Accédons maintenant au service 'web' du même projet Docker-Compose, en utilisant le nom du service :
telnet web 81
La réponse est la suivante :
Connected to web
From my_app1 - web:
Parfait, c'est ce que nous attendions.
Faisons maintenant disparaître (temporairement) le service 'web' du projet 'my_app1' . Pour ce faire, nous le supprimons.
Dans un autre terminal, nous allons dans le répertoire 'my_app1' et nous tapons :
docker-compose stop web
Nous accédons maintenant au service 'web' dans le même projet :
telnet web 81
La réponse est la suivante :
Connected to web
From my_app2 - web:
La réponse est la suivante : "Uh-oh. Nous accédons maintenant au service 'web' dans 'my_app2' alors que nous voulions accéder au service 'web' dans 'my_app1'. Notez qu'il existe de (bien) meilleures façons de simuler cela, mais aussi beaucoup plus complexes.
Solutions
Il existe deux solutions possibles, en fonction de votre situation :
Solution 1. Si le service 'web' n'a pas besoin d'être externe, nous le supprimons du réseau externe
Nous faisons cela pour les deux projets (rappelez-vous que les fichiers 'docker-compose.yml' sont identiques) :
web:
<< : *service_defaults
image: nicolaka/netshoot
command: bash -c "echo \"From ${COMPOSE_PROJECT_NAME} - web:\" | /usr/bin/nc -l 81"
networks:
- internal_network
#- app_network
Démontez les conteneurs, puis remontez-les, et arrêtez à nouveau le service 'web' du projet 'my_app1' .
Maintenant, si vous essayez d'accéder au service 'web' , voir ci-dessus :
telnet web 81
la réponse sera, après un certain temps :
telnet: bad address 'web'
Bon. Nous obtenons un message d'erreur lorsque le service n'est pas disponible.
Solution 2. Si le service 'web' doit également être externe, nous utilisons toujours le nom du conteneur du service 'web' lorsque nous y faisons référence, même si nous sommes dans le même projet Docker-Compose.
Ce n'est pas vraiment une bonne solution, mais il n'y en a pas d'autre. Si le service 'app' veut accéder au service 'web' dans le même projet Docker-Compose, nous pouvons construire le nom du conteneur en utilisant la variable 'COMPOSE_PROJECT_NAME' :
container_name = <COMPOSE_PROJECT_NAME>_<service name>_1
Pour le service 'web' dans 'my_app1' :
web_container_name = my_app1_web_1
Résumé
J'ai rencontré ce problème en passant d'un conteneur à deux conteneurs. Des choses étranges ont commencé à se produire et des données ont été mélangées entre les conteneurs. Après avoir localisé le problème, je l'ai simulé avec le code ci-dessus. J'ai ensuite corrigé le problème pour mon projet. Leçon apprise : Ne jamais supposer.
Liens / crédits
Docker - Change pre-defined environment variables in Docker Compose
https://docs.docker.com/compose/environment-variables/envvars
nicolaka / netshoot
https://github.com/nicolaka/netshoot
En savoir plus...
Docker Docker-compose
Récent
- Masquer les clés primaires de la base de données UUID de votre application web
- Don't Repeat Yourself (DRY) avec Jinja2
- SQLAlchemy, PostgreSQL, nombre maximal de lignes par user
- Afficher les valeurs des filtres dynamiques SQLAlchemy
- Transfert de données sécurisé grâce au cryptage à Public Key et à pyNaCl
- rqlite : une alternative à haute disponibilité et dist distribuée SQLite
Les plus consultés
- Utilisation des Python's pyOpenSSL pour vérifier les certificats SSL téléchargés d'un hôte
- Utiliser UUIDs au lieu de Integer Autoincrement Primary Keys avec SQLAlchemy et MariaDb
- Connexion à un service sur un hôte Docker à partir d'un conteneur Docker
- Utiliser PyInstaller et Cython pour créer un exécutable Python
- SQLAlchemy : Utilisation de Cascade Deletes pour supprimer des objets connexes
- Flask RESTful API validation des paramètres de la requête avec les schémas Marshmallow