Docker Swarm环境下Traefik代理FastAPI无法外部访问排查与解决
Docker Swarm中FastAPI+Traefik反向代理无法外部访问问题解决
我在Docker Swarm环境下使用Traefik作为反向代理部署FastAPI服务,遇到外部网络无法访问的问题:
- 进入容器内部执行
curl localhost能正常获取响应 - Traefik管理面板中能看到对应路由,但请求无法转发到API服务
- 其他站点均可正常运行
- 初步怀疑是
traefik.http.services.${APP_NAME}.loadbalancer.server.port=80的端口配置有误
初始docker-compose.yml配置
version: '3.8' services: api: image: tiangolo/uvicorn-gunicorn-fastapi:python3.8 networks: - app-network - traefik-public - database-service - search-service deploy: labels: - "traefik.enable=true" - "traefik.constraint-label=traefik-public" - "traefik.docker.network=traefik-public" - "traefik.http.routers.${APP_NAME}-http.rule=Host(`${DOMAIN?Variable not set}`)" - "traefik.http.routers.${APP_NAME}-http.entrypoints=http" - "traefik.http.routers.${APP_NAME}-http.middlewares=https-redirect" - "traefik.http.routers.${APP_NAME}-https.rule=Host(`${DOMAIN?Variable not set}`)" - "traefik.http.routers.${APP_NAME}-https.entrypoints=https" - "traefik.http.routers.${APP_NAME}-https.tls=true" - "traefik.http.routers.${APP_NAME}-https.tls.certresolver=le" - "traefik.http.services.${APP_NAME}.loadbalancer.server.port=80" placement: constraints: - node.labels.pip.node.webservers == true environment: - "DOMAIN=${DOMAIN}" - "APP_NAME=${APP_NAME}" - "APP_FILES=${APP_FILES}" networks: app-network: name: ${APP_NAME}-net external: true database-service: external: true search-service: external: true traefik-public: external: true
排查步骤:自定义Dockerfile
根据FastAPI官方文档创建了自定义Dockerfile,但问题仍未解决:
# FROM python:3.8 # WORKDIR /code # COPY ./requirements.txt /code/requirements.txt # RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt # COPY ./app /code/app # CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
问题解决:更新docker-compose.yml
最终通过调整docker-compose.yml解决问题,更新后的配置如下:
version: '3.8' services: api: image: markparrish/olis:latest networks: - app-network - traefik-public - database-service - search-service deploy: labels: - "traefik.enable=true" - "traefik.constraint-label=traefik-public" - "traefik.docker.network=traefik-public" - "traefik.http.routers.${APP_NAME}-http.rule=Host(`${DOMAIN?Variable not set}`)" # - "traefik.http.routers.${APP_NAME?Variable not set}-http.rule=PathPrefix(`/api`) || PathPrefix(`/docs`) || PathPrefix(`/redoc`)" - "traefik.http.routers.${APP_NAME}-http.entrypoints=http" - "traefik.http.routers.${APP_NAME}-http.middlewares=https-redirect" - "traefik.http.routers.${APP_NAME}-https.rule=Host(`${DOMAIN?Variable not set}`)" - "traefik.http.routers.${APP_NAME}-https.entrypoints=https" - "traefik.http.routers.${APP_NAME}-https.tls=true" - "traefik.http.routers.${APP_NAME}-https.tls.certresolver=le" - "traefik.http.services.${APP_NAME}.loadbalancer.server.port=80" placement: constraints: - node.labels.pip.node.webservers == true networks: app-network: name: ${APP_NAME}-net database-service: external: true search-service: external: true traefik-public: external: true
内容的提问来源于stack exchange,提问作者Mark Parrish
相关产品推荐
相关产品推荐

