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

Docker-Samenstellen van projecten met identieke servicenamen

Gebruik de servicenaam Docker-Compose alleen als de service zich alleen op het interne netwerk van het Docker-Compose project bevindt.

25 augustus 2023
In Docker
post main image
https://www.pexels.com/@mikael-blomkvist

Als we identieke Docker-Compose projecten hebben met identieke servicenamen, verbonden door een Docker netwerk, moeten we ervoor zorgen dat we de juiste service openen. In een Docker netwerk zijn er twee manieren om een service te benaderen:

  • Op servicenaam
  • Op containernaam

Ik heb meerdere Docker-Compose projecten die bijna identiek zijn, elk project staat in zijn eigen directory en heeft zijn eigen omgeving.

Ik ging ervan uit dat een service in een Docker-Compose project altijd een andere service in hetzelfde Docker-Compose project zou gebruiken wanneer de servicenaam (niet de containernaam) wordt gebruikt. En dat het een fout zou geven als het niet beschikbaar was. Ik had het mis. Wat er feitelijk gebeurt, is dat je de service met dezelfde naam kunt openen in een ander Docker-Compose project.

Zoals altijd draai ik dit op Ubuntu 22.04.

Projectinstelling

We hebben twee mappen met onze (bijna) identieke projecten.

├── my_app1
│   ├── docker-compose.yml
│   └── .env
├── my_app2
│   ├── docker-compose.yml
│   └── .env

De twee 'docker-compose.yml' bestanden zijn identiek. De '.env' bestanden zijn anders, ze bevatten slechts één omgevingsvariabele, de 'COMPOSE_PROJECT_NAME'. Deze variabele wordt niet alleen gebruikt om de containernamen te maken, we gebruiken hem ook binnen onze containers om het Docker-Compose project te identificeren.

We gebruiken hier 'nicolaka/netshoot' Docker image . Het heeft veel nuttige hulpprogramma's, waaronder een goed werkende 'netcat', 'nc', die we gebruiken om luister daemon's te maken.

Hier zijn de bestanden:

# my_app1/.env
COMPOSE_PROJECT_NAME=my_app1

en

# my_app2/.env
COMPOSE_PROJECT_NAME=my_app2

en

# 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

Voordat we beginnen, maken we het externe Docker netwerk aan:

docker network create my_app_network

Enkele controles uitvoeren

Open enkele terminals en start beide projecten door dit commando in elke map uit te voeren:

docker-compose up

Controleer of de volgende containers zijn aangemaakt en draaien:

my_app1_app_1
my_app1_web_1
my_app2_app_1
my_app2_web_1

Voer nu in een andere terminal uit:

docker run -it --network=my_app_network --rm busybox

Open een service in onze containers met behulp van de containernaam:

telnet my_app_1_app_1 80

Het antwoord zal zijn:

Connected to my_app1_app_1
From my_app1 - app:

Dit werkt zoals verwacht. Type wat tekst. Dit zal worden herhaald. Je kunt dit ook controleren in de terminal van het 'my_app1' Docker-Compose project.

De fout genereren

Eerst gaan we naar de 'app' service van het 'my_app1' project:

docker exec -it my_app1_app_1 bash

Laten we nu de service 'web' in hetzelfde Docker-Compose project openen met de servicenaam:

telnet web 81

Het antwoord is:

Connected to web
From my_app1 - web:

Perfect, dit is wat we verwachtten.

Laten we nu de 'web' service in het 'my_app1' project (tijdelijk) laten verdwijnen. We doen dit door het naar beneden te halen.

In een andere terminal gaan we naar de 'my_app1' directory en typen:

docker-compose stop web

Nu openen we opnieuw de 'web' service in hetzelfde project:

telnet web 81

Het antwoord is:

Connected to web
From my_app2 - web:

Uh-oh. Nu openen we de 'web' service in 'my_app2' terwijl we de 'web' service in 'my_app1' wilden openen. Merk op dat er (veel) betere, maar ook veel complexere manieren zijn om dit te simuleren.

Oplossingen

Er zijn hier twee mogelijke oplossingen, afhankelijk van je situatie:

Oplossing 1. Als de 'web' service niet extern hoeft te zijn, verwijderen we deze uit het externe netwerk.

We doen dit voor beide projecten (onthoud dat de 'docker-compose.yml' bestanden identiek zijn):

  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

Haal de containers naar beneden en weer naar boven, en stop de 'web' service van het 'my_app1' project weer.

Als je nu probeert toegang te krijgen tot de 'web' service, zie hierboven:

telnet web 81

zal het antwoord na enige tijd zijn:

telnet: bad address 'web'

Goed. We krijgen een foutmelding als de service niet beschikbaar is.

Oplossing 2. Als de 'web' service ook extern moet zijn, gebruiken we altijd de containernaam van de 'web' service als we ernaar verwijzen, zelfs als we in hetzelfde Docker-Compose project zitten.

Dit is niet echt een mooie oplossing, maar er is geen andere manier. Als de 'app' service toegang wil tot de 'web' service in hetzelfde Docker-Compose project, kunnen we de containernaam construeren met behulp van de 'COMPOSE_PROJECT_NAME' variabele:

container_name = <COMPOSE_PROJECT_NAME>_<service name>_1

Voor de 'web' service in 'my_app1':

web_container_name = my_app1_web_1

Samenvatting

Ik kwam dit tegen toen ik van één naar twee containers ging. Er begonnen vreemde dingen te gebeuren en gegevens werden verwisseld tussen de containers. Nadat ik het probleem had gevonden, simuleerde ik het met de bovenstaande code. Daarna heb ik het opgelost voor mijn project. Les geleerd: Nooit aannemen.

Links / credits

Docker - Change pre-defined environment variables in Docker Compose
https://docs.docker.com/compose/environment-variables/envvars

nicolaka / netshoot
https://github.com/nicolaka/netshoot

Laat een reactie achter

Reageer anoniem of log in om commentaar te geven.

Opmerkingen

Laat een antwoord achter

Antwoord anoniem of log in om te antwoorden.