Using traefik v3 with docker compose on an app deployed on 2 different hosts

i work on different Vm's
my first VM contains traefik under this config:

version: '3'
services:
  reverse-proxy:
    image: traefik:v3.0
    command: --log.level=DEBUG --api.insecure=true --providers.swarm=true  --providers.swarm.endpoint=unix:///var/run/docker.sock --providers.swarm.network=overlay_stg_net
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - overlay_stg_net
    deploy:
      placement:
        constraints:
          - node.role == manager

networks:
  overlay_stg_net:
    external: true
    driver: overlay
    attachable: true

then i have 2 VMs containing the docker compose of my application that should be detected by traefic to apply load balancing between them

version: '3'

services:
  nginx:
    image: nginx:1.22-alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./:/code
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.docker.network=overlay_stg_net"
        - "traefik.http.routers.nginx.rule=Host(`stg-eco-drive.docker.localhost`)"
        - "traefik.http.services.nginx.loadbalancer.server.port=8080"
    networks:
      - overlay_stg_net
  php:
    build: .
    volumes:
      - ./:/code
    networks:
      - overlay_stg_net

networks:
  overlay_stg_net:
    external: true
    driver: overlay

traeffik doesnt not detect my apps
at the end of the day i just need a way to apply load balancing on my app while its running on different hosts

Are Traefik and your target services all on nodes within the same Docker Swarm?

Is overlay_stg_net a Docker Swarm overlay network?

Did you use docker stack depoly to run the services from compose file?

Compare to simple Traefik Swarm example.

1 Like

Hello, i made some adaptation according to your configuration.
to recap i have in my first VM as a node manager traefik lunched with docker stack deploy after creating manually an overlay network
docker network create --driver overlay --attachable proxy
docker stack deploy -c docker-compose.yml proxy
here is the docker-compose.yml config:

version: '3'

services:
  traefik:
    image: traefik:v3.1
    hostname: '{{.Node.Hostname}}'
    ports:
      # listen on host ports without ingress network
      - target: 80
        published: 80
        protocol: tcp
        mode: host
      - target: 443
        published: 443
        protocol: tcp
        mode: host
    networks:
      - proxy
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt
      #- /var/log:/var/log
    command:
      - --api.dashboard=true
      - --log.level=INFO
      #- --log.filepath=/var/log/traefik.log
      - --accesslog=true
      #- --accesslog.filepath=/var/log/traefik-access.log
      - --providers.swarm.exposedByDefault=false
      - --providers.swarm.network=proxy
      - --entrypoints.web.address=:80
      - --entrypoints.web.http.redirections.entrypoint.to=websecure
      - --entryPoints.web.http.redirections.entrypoint.scheme=https
      - --entrypoints.websecure.address=:443
      - --entrypoints.websecure.asDefault=true
      - --entrypoints.websecure.http.tls.certresolver=myresolver
      - --certificatesresolvers.myresolver.acme.email=iliassayagh@gmail.com
      - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
      - --certificatesresolvers.myresolver.acme.tlschallenge=true
    deploy:
      mode: global
      placement:
        constraints:
          - node.role==manager
      labels:
        - traefik.enable=true
        - traefik.http.routers.mydashboard.rule=Host(`traefik.example.com`)
        - traefik.http.routers.mydashboard.service=api@internal
        - traefik.http.routers.mydashboard.middlewares=myauth
        - traefik.http.services.mydashboard.loadbalancer.server.port=1337
        - traefik.http.middlewares.myauth.basicauth.users=test:$$apr1$$....$$....

networks:
  proxy:
    name: proxy
    driver: overlay
    external: true
    attachable: true

volumes:
  letsencrypt:
    name: letsencrypt

after inspecting the network in VM1:
docker network inspect proxy

[
    {
        "Name": "proxy",
        "Id": "ei0fizlxzqd3eytmoo62v6mnv",
        "Created": "2024-10-15T09:54:00.930742001+01:00",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.1.0/24",
                    "Gateway": "10.0.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "76616490a15e5ce9eb15e1b920d653c86cd9f3cc088247969a8e1b380e615f4b": {
                "Name": "proxy_traefik.zaho44hgbhqwbor4frhgj8fu2.x0p6yk6ncyq6bkcivfdoekayz",
                "EndpointID": "57658f6f11b742d4bd9102e97d6c23c0ac4ee5d2edcb2b4c7643d31665203964",
                "MacAddress": "02:42:0a:00:01:05",
                "IPv4Address": "10.0.1.5/24",
                "IPv6Address": ""
            },
            "lb-proxy": {
                "Name": "proxy-endpoint",
                "EndpointID": "a0213df168b91a6a663e4314c423c8ebff7f2172137d9e8d8bad99e566879caf",
                "MacAddress": "02:42:0a:00:01:06",
                "IPv4Address": "10.0.1.6/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.driver.overlay.vxlanid_list": "4099"
        },
        "Labels": {},
        "Peers": [
            {
                "Name": "ef7c7445d3c1",
                "IP": "192.168.56.102"
            }
        ]
    }
]

ifconfig

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::a00:27ff:fe76:d4a2  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:76:d4:a2  txqueuelen 1000  (Ethernet)
        RX packets 44758  bytes 57796636 (55.1 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14270  bytes 1076743 (1.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.56.102  netmask 255.255.255.0  broadcast 192.168.56.255
        inet6 fe80::9c1b:1d9f:4edd:34b8  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:6a:5e:da  txqueuelen 1000  (Ethernet)
        RX packets 20974  bytes 2177105 (2.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 15304  bytes 1392729 (1.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

and here is the docker compose file of my application in the second VM as a worker

version: '3'

services:
  nginx:
    image: nginx:1.22-alpine
    hostname: '{{.Node.Hostname}}'
    container_name: stg_instance
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./:/code
    networks:
      - stg_lb_net
      - proxy
    deploy:
      mode: global
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.nginx.rule=Host(`stg-eco-drive.example.com`)"
        - "traefik.http.services.nginx.loadbalancer.server.port=80"
#      - "traefik.http.services.nginx.loadbalancer.server.port=443"
#      - "traefik.http.services.nginx.loadbalancer.server.port=443"
#      - "traefik.http.routers.nginx.entrypoints=websecure"
#      - "traefik.http.routers.nginx.tls=true"
#      - "traefik.http.routers.nginx.tls.certresolver=myresolver"
  php:
    build: .
    volumes:
      - ./:/code
    networks:
#      - proxy
      - stg_lb_net

networks:
  stg_lb_net:
    name: stg_lb_net
    driver: bridge
    external: true
  proxy:
    name: proxy
    driver: overlay
    external: true
#    attachable: true

after inspecting the network in VM2:
docker network inspect proxy

[
    {
        "Name": "proxy",
        "Id": "ei0fizlxzqd3eytmoo62v6mnv",
        "Created": "2024-10-15T09:51:40.435988807+01:00",
        "Scope": "swarm",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.0.1.0/24",
                    "Gateway": "10.0.1.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "ba759cbe217950bdf4c6933c6fefcedcaab271746da175135d705cf362c3cea1": {
                "Name": "stg_instance",
                "EndpointID": "983e1b0096c5846177f915af51b4ca0302f1be30e2497958ad1a5be552897f21",
                "MacAddress": "02:42:0a:00:01:02",
                "IPv4Address": "10.0.1.2/24",
                "IPv6Address": ""
            },
            "lb-proxy": {
                "Name": "proxy-endpoint",
                "EndpointID": "64d979fb17b317f1d9175618a95a6a6f5f7c5b00d9965de0f3ec178769c2b916",
                "MacAddress": "02:42:0a:00:01:03",
                "IPv4Address": "10.0.1.3/24",
                "IPv6Address": ""
            }
        },
        "Options": {
            "com.docker.network.driver.overlay.vxlanid_list": "4099"
        },
        "Labels": {},
        "Peers": [
            {
                "Name": "8f43903457cf",
                "IP": "10.0.2.15"
            },
            {
                "Name": "ef7c7445d3c1",
                "IP": "192.168.56.102"
            }
        ]
    }
]

ifconfig

enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 10.0.2.15  netmask 255.255.255.0  broadcast 10.0.2.255
        inet6 fe80::a00:27ff:fe63:3344  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:63:33:44  txqueuelen 1000  (Ethernet)
        RX packets 60557  bytes 60287627 (57.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 35770  bytes 3005744 (2.8 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.127.3  netmask 255.255.255.0  broadcast 192.168.127.255
        inet6 fe80::9c1b:1d9f:4edd:34b8  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:33:25:ed  txqueuelen 1000  (Ethernet)
        RX packets 4579  bytes 378973 (370.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3378  bytes 685409 (669.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

traefik works well with https and everything but it is still not able to discover my docker app in the second VM.

I have a remark the peers in the overlay network in VM1 doesnt contain the ip adress of the second VM

You created a Docker Swarm with init and joined the worker to the Swarm?

What does docker node ls tell you?

You started the target app also with docker stack deploy?

Note that you can’t use build in compose for Swarm services, you need to reference existing images on Docker Hub or another (privately hosted) repository.

Yes i did create a docker swarm with init in the host that contains traefik, then i joined my secend host "worker" that contains my application with the manager

docker node ls:

ID                            HOSTNAME      STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
oa00zfpqv9j4yqx6b4g2ujh3l     nginx.local   Ready     Active                          27.2.0
l12j8g0tpl4nnbnny6t0aebzr *   traefik       Ready     Active         Leader           27.2.0

I didnt start the app the stack deploy because it gives me this message
docker stack deploy -c docker-compose.yml proxy

Since --detach=false was not specified, tasks will be created in the background.
In a future release, --detach=false will become the default.
this node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again

i changed build option with a docker image

  php:
    image: php:7.4-fpm
    volumes:
      - ./:/code
    networks:
      - stg_lb_net

the problem persists unfortunatly i even changed the docker engine from 27.3.0 to 27.2.0

You deploy all Docker Swarm services on the manager node(s), even if they run on other worker nodes.

Therefore thinks like this will probably not work:

    volumes:
      - ./:/code

Use absolute path and note that it needs to exist on the node. Docker will create a bind mount folder on host, but Docker Swarm will fail.

1 Like

hello i used a linked docker swarm with all nodes as managers and it worked thank you but is it good prectice to do so?

You should have (at least) 3 Docker Swarm managers for failover, in case one node dies. And managers can also handle regular worker node tasks.

1 Like

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.