Traefik与C# API:Docker Swarm下无端口HTTPS访问配置问题
问题描述
在Docker Swarm集群中部署了Traefik、Portainer及一个C# API服务,目前仅能通过带端口的URL(如http://example.com:8081/valid-route)访问API,无法直接通过域名example.com实现HTTPS无端口访问。尽管已为API的docker-compose配置了Traefik相关标签,但问题仍未解决,现寻求解决方案以实现API的无端口HTTPS访问。
现有配置
Traefik节点的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
Portainer的docker-compose.yaml
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
C# API的docker-compose.yaml
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
解决方案
核心问题分析
- 网络不一致:Traefik配置中
--providers.docker.network=ConexxoHubNet,但Traefik自身加入的是MySwarmNet,且API服务也在MySwarmNet,导致Traefik无法发现API服务。 - 服务名称错误:API的Traefik标签中
traefik.http.routers.api.service=cadvisor,服务名应为api(与docker-compose中定义的服务名一致)。 - 端口配置错误:
traefik.http.services.api.loadbalancer.server.port应该指向容器内部的8080,而非宿主机映射的8081——Traefik与容器在同一Swarm网络中,直接访问容器端口即可。 - 冗余端口映射:API服务不需要配置
ports映射到宿主机,Traefik会通过Swarm网络代理请求,暴露端口反而可能引发冲突。
修正后的配置
1. 修正Traefik的网络配置
将Traefik的--providers.docker.network改为MySwarmNet,与自身加入的网络一致:
# Traefik command中的对应行修改为 - "--providers.docker.network=MySwarmNet"
2. 修正C# API的docker-compose.yaml
version: '3.3' services: api: image: dockerhub-image-name/image-name 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=8080 - traefik.http.routers.api.service=api - traefik.http.routers.api.tls.certresolver=letsencryptresolver - traefik.http.routers.api.entrypoints=websecure - traefik.http.routers.api.tls=true - traefik.docker.network=MySwarmNet # 明确指定与Traefik一致的网络 networks: - MySwarmNet networks: MySwarmNet: external: true
验证步骤
- 重新部署Traefik:
docker stack deploy -c traefik-compose.yaml traefik - 重新部署API服务:
docker stack deploy -c api-compose.yaml api - 查看Traefik日志确认是否发现API路由:
docker logs <traefik-container-id> - 访问
https://example.com/valid-route验证是否正常访问
内容的提问来源于stack exchange,提问作者Bruno Henrique Peixoto
相关产品推荐
相关产品推荐

