Docker Swam 502 bad gateway error

Hey guys :slight_smile: , I have a half working solution - one service works on port 80 but my other service gets a '502 Bad Gateway' caused by: dial tcp 10.1.4.7:3000: connect: connection refused

This is the config:

traefik.toml

[log]
  level = "DEBUG"

[entryPoints]
  [entryPoints.web]
    address = ":80"
  [entryPoints.websecure]
    address = ":443"
  [entryPoints.staging]
    address = ":3000"

[providers]
  [providers.docker]
    endpoint = "unix:///var/run/docker.sock"
    network = "overlord_proxy"
    swarmMode = true
    watch = true
  # Enable the file provider to define routers / middlewares / services in a file
  [providers.file]
    debugLogGeneratedTemplate = true
    directory = "/etc/traefik/dynamic"
    watch = true

[certificatesResolvers]
  [certificatesResolvers.mytlschallenge]
    [certificatesResolvers.mytlschallenge.acme]
      email = "email"
      storage = "/letsencrypt/acme.json"
      tlschallenge = true

dyanmic config:

[http]
  [http.routers]
    [http.routers.whoami]
      entryPoints = ["web"]
      rule = "Host(`MYURL`)"
      service = "whoami"

    [http.routers.whoami-secure]
      entryPoints = ["websecure"]
      rule = "Host(`MYURL`)"
      service = "whoami"
      [http.routers.whoami.tls]
        certResolver = "mytlschallenge"

  [http.services]
    [http.services.whoami]
      enable = true
      [http.services.whoami.loadBalancer]
        [[http.services.whoami.loadBalancer.servers]]
          port = "8000"
          url = "http://whoami:8000"

  [http.middlewares]
    [http.middlewares.httpsredirect.redirectScheme]
      scheme = "https"

and the docker-compose.yml:

version: "3.7"

services:
  proxy:
    image: traefik:v2.0.2
    volumes:
      # connect to docker socket for Traefik to listen to docker events
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/etc/traefik/traefik.toml:/etc/traefik/traefik.toml"
      - "/etc/traefik/dynamic/:/etc/traefik/dynamic/"
      # Store certificates in ./letsencrypt/acme.json
      - "./letsencrypt:/letsencrypt"
    # command:
      #- "--providers.file=true"
      #- "--providers.file.filename=/traefik/traefik.toml"
    networks:
    - proxy
    ports:
      - "443:443"
      - "80:80"
      - "3000:3000"
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager

  whoami:
    image: jwilder/whoami
    networks:
    - proxy
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.whoami.rule=Host(`URL`)"
        - "traefik.http.routers.whoami.entrypoints=websecure"
        - "traefik.http.routers.whoami.service=whoami@file"

networks:
  proxy:
    driver: overlay

And that works! I have another docker-compose which runs another whoami service but I get a 502 bad gateway error (connection refused) when I navigate to MYURL:3000

version: "3.7"

services:
  staging:
    image: jwilder/whoami
    networks:
      - overlord_proxy
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.staging.rule=Host(`MYURL`)"
        - "traefik.http.routers.staging.entrypoints=staging"

        - "traefik.http.services.staging.loadbalancer.server.port=3000"
        - "traefik.http.routers.staging.service=staging@file"

networks:
  overlord_proxy:
    external: true

this is the dynamic config /etc/traefik/dynamic/staging.toml:

[http]
  [http.routers]
    [http.routers.staging]
      entryPoints = ["staging"]
      rule = "Host(`MYURL`)"
      service = "staging"

    [http.routers.staging-secure]
      entryPoints = ["staging"]
      rule = "Host(`MYURL`)"
      service = "staging"
      [http.routers.staging-secure.tls]
        certResolver = "mytlschallenge"

  [http.services]
    [http.services.staging]
      enable = true
      [http.services.staging.loadBalancer]
        [[http.services.staging.loadBalancer.servers]]
          port = "3000"
          url = "http://staging:3000"

  [http.middlewares]
    [http.middlewares.httpsredirect.redirectScheme]
      scheme = "https"

Hey, figured it out... I was using port 3000 but jwilder/whoami exposes port 8000 in its Dockerfile ...doh!

See this thread too for redirecting from 8000

Hope this can help someone

Hello,

The dynamic configuration can be:

  • labels
  • files
  • ...

The dynamic configuration from labels are not merged with dynamic configuration from another source.

https://docs.traefik.io/v2.1/getting-started/configuration-overview/#the-dynamic-configuration

So your dynamic configuration from label is incomplete.

Also, You mixed Traefik v1 and Traefik v2 configuration.

You don't need to use files.

version: "3.7"

services:
  proxy:
    image: traefik:v2.1.4
    volumes:
      # connect to docker socket for Traefik to listen to docker events
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      # Store certificates in ./letsencrypt/acme.json
      - "./letsencrypt:/letsencrypt"
    command:
      - --log.level=DEBUG
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
      - --entryPoints.staging.address=:3000
      - --providers.docker.network=overlord_proxy
      - --providers.docker.swarmMode=true
      - --providers.docker.watch=true
      - --certificatesResolvers.mytlschallenge.acme.email=email
      - --certificatesResolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json
      - --certificatesResolvers.mytlschallenge.acme.tlschallenge=true
    networks:
    - proxy
    ports:
      - "443:443"
      - "80:80"
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager

  whoami:
    image: jwilder/whoami
    networks:
    - proxy
    deploy:
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.staging.rule=Host(`MYURL`)"
        - "traefik.http.routers.staging.entrypoints=staging"
        - "traefik.http.routers.staging.tls.certResolver=mytlschallenge"
        - "traefik.http.services.staging.loadbalancer.server.port=8000"

networks:
  proxy:
    driver: overlay

Recommend read:

1 Like

I could not agree more.
Mixing dynamic configuration from different sources is not possible

Mixing is possible, merging is not possible.

You can use multiple providers (file, docker, ...) but 2 elements (router, service, ...) with the same name will not be merged.

Really appreciate it, I'm confused because I tried to use a dynamic configuration file alone and it wasn't working. So I attached those labels and somehow it's working... I'm struggling to find what the best practice for this would be as I've perused the documentation and forums and most people seem to be using labels. I want to use external files in this case because I'm going to end up with loads and loads of services and I would prefer to have some separation.

Which configuration is from v1 that I am using?

The best practice when you are using Docker is to use labels.

The file provider, to define router and services, is for old infrastructure (VM, ...) I recommend to not using it with a Docker infrastructure.

1 Like

FYI the latest stable version is v2.1.4.

We maintains only one minor version by major version: v2.0 is not maintained

Using Docker with labels is the best practise......However if you need to add certificates (not let's encrypt) the only solution is use the file provider for TLS certs..

# Dynamic configuration

tls:
  certificates:
    - certFile: /path/to/domain.cert
      keyFile: /path/to/domain.key
    - certFile: /path/to/other-domain.cert
      keyFile: /path/to/other-domain.key

Because...

In the above example, we've used the file provider to handle these definitions. It is the only available method to configure the certificates.

I was precise: I'm speaking about routers and services.

Sorry.....you are right.

About routers and services :slight_smile:

Do you know why if I create a custom entrypoint of 3000 it only works if i declare the port on the traefik service? I see you removed it from the example you made for me. E.g.:

services:
  traefik_proxy:
    ports:
      - "443:443"
      - "80:80"
      - "3000:3000"
      - "8000:8000"
      - "8080:8080"
      - "8081:8081"

Also, is it alright to use the same entrypoint for both the normal router and the secure one?

        - "traefik.http.routers.staging.rule=Host(`MYURL`)"
        - "traefik.http.routers.staging.entrypoints=staging"
        - "traefik.http.services.staging.loadbalancer.server.port=8000"
        - "traefik.http.routers.staging-secure.rule=Host(`MYURL`)"
        - "traefik.http.routers.staging-secure.entrypoints=staging"