angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

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.

25 août 2023
Dans Docker
post main image
https://www.pexels.com/@mikael-blomkvist

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

Laissez un commentaire

Commentez anonymement ou connectez-vous pour commenter.

Commentaires

Laissez une réponse

Répondez de manière anonyme ou connectez-vous pour répondre.