Gemeinsame Netzwerke zwischen Compose-Stacks - Container aus verschiedenen Projekten verbinden

Gemeinsame Netzwerke zwischen Compose-Stacks - Container aus verschiedenen Projekten verbinden

Wenn zwei separate Compose-Stacks miteinander kommunizieren sollen, braucht man ein externes Netzwerk — das Standard-Netzwerk jedes Projekts ist isoliert.

Das Problem

Jeder Compose-Stack bekommt automatisch ein eigenes Netzwerk (z.B. projektname_default). Container aus Stack A können Container aus Stack B damit nicht per Name erreichen — sie sind netzwerktechnisch voneinander getrennt.

Typisches Szenario: Traefik in Stack A soll Apps in Stack B routen, oder eine App in Stack B soll eine Datenbank in Stack A nutzen.

Lösung: Externes Netzwerk erstellen

docker network create shared-net

Dieses Netzwerk existiert unabhängig von jedem Compose-Stack.

Stack A einrichten (z.B. Traefik)

# docker-compose.yml (Stack A)
services:
  traefik:
    image: traefik:v3.0
    networks:
      - shared-net

networks:
  shared-net:
    external: true    # Netzwerk existiert bereits, wird nicht erstellt

Stack B einrichten (App-Stack)

# docker-compose.yml (Stack B)
services:
  app:
    image: myapp
    networks:
      - shared-net    # Erreichbar für Traefik
      - internal      # Internes Netz für DB-Verbindung

  db:
    image: postgres:16
    networks:
      - internal      # Nur intern, nicht für Traefik sichtbar

networks:
  shared-net:
    external: true    # Dasselbe externe Netzwerk
  internal:           # Wird von Compose erstellt

Container per Namen ansprechen

Im gemeinsamen Netzwerk sind Container über ihren container_name erreichbar — oder über den automatisch vergebenen Namen projektname_servicename_1:

# Stack B
services:
  app:
    container_name: myapp    # Expliziter Name empfohlen
# Von Stack A aus:
curl http://myapp:8080/health

Ohne expliziten container_name lautet der Name stackb_app_1 (Compose-Projektname + Service + Index). Der Projektname entspricht dem Verzeichnisnamen oder kann mit --project-name gesetzt werden.

Naming-Konvention für externe Netzwerke

Für mehrere Projekte auf einem Host empfiehlt sich ein klares Schema:

docker network create traefik-public    # Für alle Dienste hinter Traefik
docker network create monitoring        # Für Prometheus/Grafana
docker network create db-shared         # Für geteilte Datenbanken

Praxisbeispiel: Traefik + App-Stack

# Einmalig auf dem Server
docker network create traefik-public

Traefik-Stack:

services:
  traefik:
    image: traefik:v3.0
    ports: ["80:80", "443:443"]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - traefik-public

networks:
  traefik-public:
    external: true

App-Stack:

services:
  app:
    image: myapp
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`app.example.com`)"
    networks:
      - traefik-public
      - internal

  db:
    image: postgres:16
    networks:
      - internal

networks:
  traefik-public:
    external: true
  internal:

Netzwerke inspizieren

docker network ls                              # Alle Netzwerke anzeigen
docker network inspect shared-net             # Details und verbundene Container
docker network inspect shared-net --format '{{range .Containers}}{{.Name}} {{end}}'

Vorsicht bei shared-net

Je mehr Container im selben Netzwerk, desto mehr können sie sich gegenseitig erreichen. Das gemeinsame Netzwerk sollte nur für Dienste genutzt werden, die wirklich kommunizieren müssen — interne Datenbanken gehören nicht dazu.