dockerdocker-composetraefik

Traefik with service in separate docker-compose file stops working when using multiple networks


As a relative docker and Traefik novice, I am trying to get Traefik with multiple services in separate docker-compose files running. For illustration purposes, the first service A is a simple web service (nginxdemos/hello) with an additional database (postgres).

My traefik/docker-compose.yml is as follows:

version: '3.8'

services:
  traefik:
    image: traefik:v2.10
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080" # Traefik Dashboard
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    networks:
      - web

networks:
  web:
    external: true

The service-A/docker-compose.yml looks as follows:

version: '3.8'

services:
  service-a:
    image: nginxdemos/hello
    environment:
      - DATABASE_URL=postgresql://user:password@service-a-db:5432/dbname
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.service-a.rule=Host(`a.dock.er`)"
      - "traefik.http.services.service-a.loadbalancer.server.port=80"
    networks:
#      - service-a-network
      - web
    ports:
      - 9080:80 # just for testing
#    depends_on:
#      - service-a-db


  service-a-db:
    image: postgres:13
    environment:
      - POSTGRES_DB=dbname
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=password
    networks:
      - service-a-network

networks:
  service-a-network:
    internal: true
  web:
    external: true

With this configuration, the service is accessible through Traefik via 'A.dock.er'.

However, as soon as I add the additional 'service-a-network' network (as well as the 'depends_on' option) to service-a, the service is no longer accessible via Traefik (but still accessible via port 9080).

I am lost, what is causing this. I believe this should be the correct configuration, with separating internal sub-services into their own network and thus having the main service in both the 'public' Traefik network as well as the internal network.

Any help would be greatly appreciated.


Solution

  • When you have a service connected to multiple networks, traefik will see multiple ip addresses for that service...and it will pick a random one when it tries to connect. This won't work if it picks an address on a network to which it is not connected.

    You can tell traefik which network to use by setting the traefik.docker.network label on the service with multiple connections. If we rewrite service-a like this, it will work as expected:

    services:
      service-a:
        image: nginxdemos/hello
        environment:
          - DATABASE_URL=postgresql://user:password@service-a-db:5432/dbname
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.service-a.rule=Host(`a.dock.er`)"
          - "traefik.http.services.service-a.loadbalancer.server.port=80"
          - "traefik.docker.network=web"
        networks:
          - service-a-network
          - web
    

    With that in place:

    $ curl -s http://localhost -H Host:a.dock.er
    <!DOCTYPE html>
    <html>
    <head>
    <title>Hello World</title>
    .
    .
    .