Search code examples
dockerssldocker-composedocker-swarmtraefik

Traefik: http, https, ws, wss on same domain (docker swarm)


I'm trying to configure traefik to serve http, https, ws, wss on same domain. Here is my traefik init (docker-compose.yml):

    command:
      - "storeconfig"
      - "--api"
      - "--entrypoints=Name:http Address::80 Redirect.EntryPoint:https"
      - "--entrypoints=Name:https Address::443 TLS"
      - "--entrypoints=Name:ws Address::8081 Redirect.EntryPoint:wss"
      - "--entrypoints=Name:wss Address::8083 TLS"
      - "--defaultentrypoints=http,https"
      - "--acme"
      - "--acme.entryPoint=https"
      - "--acme.httpChallenge.entryPoint=http"
      - "--acme.onHostRule=true"
      - "--acme.onDemand=false"
      - "--acme.email=${EMAIL}"
      - "--acme.storage=etc/traefik/acme/acme.json"
      - "--docker"
      - "--docker.swarmMode"
      - "--docker.watch"

And deploy labels for ws/wss service:

    deploy:
      labels:
        - traefik.enable=true
        - traefik.backend=ws-container-name
        - traefik.frontend.rule=Host:myhost
        - traefik.frontend.entryPoints=ws,wss
        - traefik.docker.network=traefik
        - traefik.port=9001

The result: ws is working, wss is not.

 % wscat -c ws://myhost:8081 
connected (press CTRL+C to quit)
 % wscat -c wss://myhost:8083
error: unable to verify the first certificate

http, https (another container) is working well

Why does traefik do not serve certs for wss?


Solution

  • The solution is to update traefik to version 2

    Config example:

    services:
      traefik:
        image: traefik:v2.0
        command:
          - "--accesslog=true"
          - "--log.level=ERROR"
          - "--api.insecure=true"
          - "--providers.docker"
          - "--providers.docker.swarmMode=true"
          - "--providers.docker.exposedByDefault=false"
          - "--providers.docker.network=traefik"
          - "--providers.docker.watch=true"
          - "--entryPoints.http.address=:80"
          - "--entryPoints.https.address=:443"
          - "--entryPoints.ws.address=:8081"
          - "--entryPoints.wss.address=:8083"
          - "[email protected]"
          - "--certificatesResolvers.dns.acme.storage=/letsencrypt/acme.json"
          # Using DNS challenge is important to support a service without http protocol
          - "--certificatesResolvers.dns.acme.dnsChallenge=true"
          - "--certificatesResolvers.dns.acme.dnsChallenge.provider=godaddy"
          # ...
      http-service:
        # ...
        deploy:
          labels:
            - traefik.enable=true
            # important to tell traefik that swarm is load balancer
            - traefik.docker.lbswarm=true
            # redirect http
            - traefik.http.middlewares.http-redirect.redirectregex.regex=^http://(.*)
            - traefik.http.middlewares.http-redirect.redirectregex.replacement=https://$${1}
            # backend port
            - traefik.http.services.http.loadbalancer.server.port=80
            # http
            - traefik.http.routers.http.middlewares=http-redirect
            - traefik.http.routers.http.rule=Host(`example.com`)
            - traefik.http.routers.http.entrypoints=http
            # https
            - traefik.http.routers.https.rule=Host(`example.com`)
            - traefik.http.routers.https.entrypoints=https
            - traefik.http.routers.https.tls=true
            - traefik.http.routers.https.tls.certresolver=dns
      ws-service:
        # ...
        deploy:
          labels:
            - traefik.enable=true
            - traefik.docker.lbswarm=true
            # backend port
            - traefik.http.services.ws-service.loadbalancer.server.port=9001
            # ws
            - traefik.http.routers.ws-service-ws.rule=Host(`example.com`)
            - traefik.http.routers.ws-service-ws.entrypoints=ws
            # wss
            - traefik.http.routers.ws-service-wss.rule=Host(`example.com`)
            - traefik.http.routers.ws-service-wss.entrypoints=wss
            - traefik.http.routers.ws-service-wss.tls=true
            - traefik.http.routers.ws-service-wss.tls.certresolver=dns