在AWS Lightsail部署Django/Docker/Nginx等技术栈失败求助
连续一周每天花数小时部署,始终失败。作为技术新手,试了几百种配置组合都没用,现在遇到502 Bad Gateway错误,怀疑是Nginx找不到静态文件、upstream配置无法识别web服务或Nginx权限问题。
Nginx错误日志:
connect() failed (111: Connection refused) while connecting to upstream...upstream: "https://some-ip-address-here?:443" (this might be that nginx doesn't know about the web)
Dockerfile
# 基础镜像 FROM python:3.10.2-slim-bullseye # 设置环境变量 ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 # 创建并设置工作目录`app` RUN mkdir -p /app RUN mkdir -p /app/staticfiles WORKDIR /app # 安装依赖 COPY requirements.txt /tmp/requirements.txt RUN set -ex && \ pip install --upgrade pip && \ pip install -r /tmp/requirements.txt && \ apt-get -y update && \ apt-get -y upgrade && \ apt-get install -y ffmpeg && \ rm -rf /root/.cache/ # 复制本地项目文件 COPY . /app/ COPY wait-for-it.sh /wait-for-it.sh RUN chmod +x /wait-for-it.sh
docker-compose.yml
version: '3.7' services: web: container_name: web build: . restart: always command: ["/wait-for-it.sh", "db:5432", "--", "gunicorn", "--bind", "0.0.0.0:8000", "--workers", "3", "my_project.wsgi"] volumes: - .:/app ports: - "8000:8000" - "443" env_file: .env depends_on: - db nginx: container_name: nginx restart: always image: jonasal/nginx-certbot:4.2.0-nginx1.23.3 env_file: - .env.nginx volumes: - nginx_secrets:/etc/letsencrypt - ./nginx/user_conf.d:/etc/nginx/user_conf.d - .:/app ports: - 80:80 - 443:443 depends_on: - web - db db: container_name: db image: postgres:13 restart: always volumes: - postgres_data:/var/lib/postgresql/data/ env_file: .env celery: container_name: celery restart: always build: context: . command: celery -A my_project worker -l info -B volumes: - .:/app env_file: - .env depends_on: - web - rabbitmq3 rabbitmq3: container_name: rabbitmq image: rabbitmq:3-management-alpine ports: - 5672:5672 - 15672:15672 volumes: postgres_data: nginx_secrets:
Nginx 配置
upstream web { server web:443; } # 重定向所有HTTP请求到HTTPS server { listen 80; server_name myurl.com; return 301 https://$server_name$request_uri; location /static/ { alias /app/staticfiles/; } location /media/ { alias /app/media/; } } # 将请求转发到web容器 server { location / { proxy_pass https://web/; } access_log /var/log/nginx/project.access.log; error_log /var/log/nginx/project.error.log; # 监听IPv4和IPv6的443端口 listen 443 ssl default_server reuseport; listen [::]:443 ssl default_server reuseport; server_name www.myurl.com myurl.com; # 加载证书文件 ssl_certificate /etc/letsencrypt/live/my-site/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/my-site/privkey.pem; ssl_trusted_certificate /etc/letsencrypt/live/my-site/chain.pem; # 加载Diffie-Hellman参数 ssl_dhparam /etc/letsencrypt/dhparams/dhparam.pem; location /static/ { alias /app/staticfiles/; } location /media/ { alias /app/media/; } }
问题排查与修复方案
从错误日志和配置来看,核心问题是Nginx尝试连接web容器的443端口,但web容器实际在8000端口提供HTTP服务,导致连接被拒绝。
1. 修正Nginx的upstream配置
你的web容器用gunicorn绑定的是8000端口,且没有配置HTTPS,所以Nginx应该转发到web容器的8000端口,而不是443。修改Nginx配置中的upstream部分:
upstream web { server web:8000; # 把443改成8000 }
同时,proxy_pass也要改成HTTP协议(因为web容器没有HTTPS服务):
location / { proxy_pass http://web/; # 把https改成http }
2. 移除web容器的443端口暴露
在docker-compose.yml里,web服务的ports中- "443"是多余的,因为web容器本身不提供443端口的服务,直接删除这一行:
ports: - "8000:8000" # 移除 - "443"
3. 优化静态文件配置
HTTP重定向的server块里的静态文件配置不会生效,因为该块直接返回301,建议把静态文件配置只保留在HTTPS的server块中,避免冗余。
4. 验证web容器运行状态
执行以下命令查看web容器的日志,确认gunicorn是否成功启动:
docker logs web
如果有数据库连接失败的问题,检查wait-for-it.sh是否正确等待数据库启动,或者调整depends_on的配置(注意depends_on只保证启动顺序,不保证服务就绪)。
5. 确保静态文件目录权限
在Dockerfile中添加目录权限设置,避免Nginx无法读取静态文件:
RUN chmod -R 755 /app/staticfiles /app/media
内容的提问来源于stack exchange,提问作者michaelbane

