dockertraefikportainer

Traefik and C# API: Redirect traffic to specific ports


I host a swarm with Traefik, Portainer and some APIs, in this case, a C# API. I am unable to access my URL without the port, even though the traefik tags on API docker-compose are supposedly correct. Thanks in advance for your help!

The Traefik node has following file docker-compose.yaml.

version: "3.7"
services:

## --------------------------- ORION --------------------------- ##

  traefik:
    image: traefik:v2.11.2
    command:
      - "--api.dashboard=true"
      - "--providers.docker.swarmMode=true"
      - "--providers.docker.endpoint=unix:///var/run/docker.sock"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=ConexxoHubNet" ## Nome da rede interna
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.transport.respondingTimeouts.idleTimeout=3600"
      - "--certificatesresolvers.letsencryptresolver.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencryptresolver.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencryptresolver.acme.storage=/etc/traefik/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencryptresolver.acme.email=brunopeixoto@suasvendas.com" ## Email para receber as notificações
      - "--log.level=DEBUG"
      - "--log.format=common"
      - "--log.filePath=/var/log/traefik/traefik.log"
      - "--accesslog=true"
      - "--accesslog.filepath=/var/log/traefik/access-log"
    deploy:
      placement:
        constraints:
          - node.role == manager
      labels:
        - "traefik.enable=true"
        - "traefik.http.middlewares.redirect-https.redirectscheme.scheme=https"
        - "traefik.http.middlewares.redirect-https.redirectscheme.permanent=true"
        - "traefik.http.routers.http-catchall.rule=Host(`{host:.+}`)"
        - "traefik.http.routers.http-catchall.entrypoints=web"
        - "traefik.http.routers.http-catchall.middlewares=redirect-https@docker"
        - "traefik.http.routers.http-catchall.priority=1"
    volumes:
      - "vol_certificates:/etc/traefik/letsencrypt"
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
    ports:
      - target: 80
        published: 80
        mode: host
      - target: 443
        published: 443
        mode: host
    networks:
      - MySwarmNet ## Nome da rede interna

## --------------------------- ORION --------------------------- ##

volumes:
  vol_shared:
    external: true
    name: volume_swarm_shared
  vol_certificates:
    external: true
    name: volume_swarm_certificates

networks:
  MySwarmNet: ## Nome da rede interna
    external: true
    attachable: true
    name: MySwarmNet ## Nome da rede interna

Likewise, the portainer file docker-compose.yaml is below:

version: "3.7"
services:

## --------------------------- ORION --------------------------- ##

  agent:
    image: portainer/agent:latest ## Versão do portainer

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes

    networks:
      - MySwarmNet ## Nome da rede interna

    deploy:
      mode: global
      placement:
        constraints: [node.platform.os == linux]

## --------------------------- ORION --------------------------- ##

  portainer:
    image: portainer/portainer-ce:latest
    command: -H tcp://tasks.agent:9001 --tlsskipverify

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

    networks:
      - MySwarmNet ## Nome da rede interna

    deploy:
      mode: replicated
      replicas: 1
      placement:
        constraints: [node.role == manager]
      labels:
        - "traefik.enable=true"
        - "traefik.http.routers.portainer.rule=Host(`portainer.conexxohub.com.br`)" ## Dominio da aplicação
        - "traefik.http.services.portainer.loadbalancer.server.port=9000"
        - "traefik.http.routers.portainer.tls.certresolver=letsencryptresolver"
        - "traefik.http.routers.portainer.service=portainer"
        - "traefik.docker.network=ConexxoHubNet" ## Nome da rede interna
        - "traefik.http.routers.portainer.entrypoints=websecure"
        - "traefik.http.routers.portainer.priority=1"

## --------------------------- ORION --------------------------- ##

networks:
  MySwarmNet: ## Nome da rede interna
    external: true
    attachable: true

volumes:
  portainer_data:
    external: true
    name: portainer_data

Finally, after I push the API image to Docker Hub, I push the following file docker-compose.yaml on Portainer. The domain here is not functional, which requires a bit of mind stretching. As you can see, the port 8081 is the accessible port. However, when I try to access example.com, the only way to access the endpoints is by URL http://example.com:8081/valid-route. I want to make it also available for https and without the port requirement. What is necessary to do so?

version: '3.3'

services:
  api:
    image: dockerhub-image-name/image-name
    ports:
      - "8081:8080"
    environment:
      - ASPNETCORE_ENVIRONMENT=Production  
    deploy:
        mode: replicated
        replicas: 1
        placement:
          constraints:
            - node.role == manager
        labels:
          - traefik.enable=true
          - traefik.http.routers.api.rule=Host(`example.com`)
          - traefik.http.services.api.loadbalancer.server.port=8081
          - traefik.http.routers.api.service=cadvisor
          - traefik.http.routers.api.tls.certresolver=letsencryptresolver
          - traefik.http.routers.api.entrypoints=websecure
          - traefik.http.routers.api.tls=true
    networks:
      - MySwarmNet

networks:
  MySwarmNet:
    external: true

Solution

  • loadbalancer.server.port=8080 should be set to the Docker container internal port, as Traefik usually connects via the Docker network. So ports: is not relevant in that context.

    I would not use ports: at all for target services, as it makes them available on external ports, potentially circumventing any Traefik security middleware.