Traefik2作为Nginx反向代理部署Django生产环境遇Bad Gateway错误
Django + Nginx + Traefik2 部署Bad Gateway问题排查
问题背景
已完成一个基础功能的Django应用,本地运行正常,计划部署到已有Traefik2作为反向代理(配置Let's Encrypt证书)的生产服务器,希望保留Nginx处理静态文件的架构,让Traefik作为Nginx的前置代理。但使用当前配置后浏览器返回"Bad Gateway"错误;若将Traefik标签配置到web服务,Django可正常运行,但无法获取静态文件。
当前配置文件
docker-compose.pro.yml
version: "3.9" # docker-compose for production # It is important that the .env.prod is used. # For this, docker-compose must always be executed # with the command docker-compose -f docker-compose.pro.yml --env-file .env.prod. services: web: build: context: . dockerfile: ./compose/Dockerfile restart: always command: gunicorn project.wsgi:application --bind 0.0.0.0:8000 env_file: - ./.env.prod expose: - 8000 volumes: - static_volume:/code/staticfiles - media_volume:/code/mediafiles depends_on: - redis - db networks: - pjnet db: image: postgres:15 restart: always volumes: - postgres_data:/var/lib/postgresql/data/ environment: - POSTGRES_USER=${DB_USERNAME} - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=${DB_NAME} networks: - pjnet redis: image: redis:7 networks: - pjnet celery: build: context: . dockerfile: ./compose/Dockerfile restart: always command: celery -A project worker -l info volumes: - .:/code env_file: - ./.env.prod depends_on: - db - redis - web networks: - pjnet nginx: build: ./compose/nginx restart: always ports: - ${NGINX_PORT}:80 volumes: - static_volume:/code/staticfiles - media_volume:/code/mediafiles labels: - traefik.enable=true - traefik.http.routers.blogng.rule=Host(`blog.project.com`) - traefik.http.routers.blogng.entrypoints=http - traefik.http.routers.blogng.middlewares=https-redirect - traefik.http.routers.blogngsec.rule=Host(`blog.project.com`) - traefik.http.routers.blogngsec.entrypoints=https - traefik.http.routers.blogngsec.tls.certresolver=le - traefik.http.routers.blogngsec.service=blogngsec - traefik.http.services.blogngsec.loadbalancer.server.port=${NGINX_PORT} depends_on: - web networks: - pjnet - traefik-net volumes: postgres_data: static_volume: media_volume: networks: traefik-net: external: true pjnet:
nginx.conf
upstream web_app { server web:8000; } server { listen 80; location /static/ { alias /code/staticfiles/; } location /media/ { alias /code/mediafiles/; } location / { proxy_pass http://web_app; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_redirect off; } }
问题原因及修复方案
核心错误:Traefik服务端口配置错误
Traefik与Nginx在同一个traefik-net Docker网络中,容器间通信应使用容器内部的端口,而非宿主机的端口映射值。当前配置的traefik.http.services.blogngsec.loadbalancer.server.port=${NGINX_PORT}指向宿主机端口,Traefik无法通过该端口访问到Nginx容器,导致Bad Gateway。
修复步骤
修改Nginx服务的Traefik标签,将服务端口改为Nginx容器内部监听的80端口:
labels: - traefik.enable=true - traefik.http.routers.blogng.rule=Host(`blog.project.com`) - traefik.http.routers.blogng.entrypoints=http - traefik.http.routers.blogng.middlewares=https-redirect - traefik.http.routers.blogngsec.rule=Host(`blog.project.com`) - traefik.http.routers.blogngsec.entrypoints=https - traefik.http.routers.blogngsec.tls.certresolver=le - traefik.http.routers.blogngsec.service=blogngsec - traefik.http.services.blogngsec.loadbalancer.server.port=80 # 改为容器内部端口80可选优化:移除Nginx服务的
ports配置
由于Traefik已作为前置代理处理外部请求,无需将Nginx端口暴露给宿主机,可删除ports: - ${NGINX_PORT}:80这一行,减少不必要的端口暴露。
额外检查点
- 确认Nginx容器正常启动:执行
docker-compose -f docker-compose.pro.yml --env-file .env.prod logs nginx查看日志,排查是否有启动报错。 - 确认静态文件已正确收集:在Django容器中运行
python manage.py collectstatic --noinput,确保静态文件已同步到static_volume卷中。 - 检查Django生产配置:
.env.prod中ALLOWED_HOSTS需包含blog.project.comCSRF_TRUSTED_ORIGINS需添加https://blog.project.comDEBUG需设为False
内容的提问来源于stack exchange,提问作者WillHoh
相关产品推荐
相关产品推荐

