首页 > 解决方案 > 通过 Nginx 代理 HTTPS 向 docker-compose 中的 gunicorn django 提供静态文件

问题描述

我正在使用 docker-compose 将我的 Django/Nginx/Gunicorn webapp 部署到 EC2 实例。EC2 实例具有mywebapp.com/www.mywebapp.com指向的静态 IP,并且我已经完成了certbot验证(站点通过 HTTP 在端口 80 上工作),但现在正试图通过 SSL 工作。

现在,HTTP(包括加载静态文件)正在为我工​​作,HTTPS 动态内容(来自 Django)正在工作,但静态文件不是。我认为我的 nginx 配置很不稳定。

我尝试将location /static/块复制到 nginx conf 文件中的 SSL 服务器上下文,但这导致 SSL 完全停止工作,而不仅仅是 SSL 上的静态文件。

这是最终的 docker-compose.yml:

services:
  certbot:
    entrypoint: /bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h &
      wait $${!}; done;'
    image: certbot/certbot
    volumes:
      - /home/ec2-user/certbot/conf:/etc/letsencrypt:rw
      - /home/ec2-user/certbot/www:/var/www/certbot:rw
  nginx:
    command: /bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done
      & nginx -g "daemon off;"'
    depends_on:
      - web
    image: xxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/xxxxxxxx:latest
    ports:
      - 80:80/tcp
      - 443:443/tcp
    volumes:
      - /home/ec2-user/certbot/conf:/etc/letsencrypt:rw
      - static_volume:/usr/src/app/public:rw
      - /home/ec2-user/certbot/www:/var/www/certbot:rw
  web:
    entrypoint: gunicorn mywebapp.wsgi:application --bind 0.0.0.0:7000"
    image: xxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/xxxxxxxx:latest
    volumes:
      - static_volume:/usr/src/app/public:rw
version: '3.0'
volumes:
  static_volume: {}

nginx.prod.conf

upstream mywebapp {
    # web is the name of the service in the docker-compose.yml
    # 7000 is the port that gunicorn listens on
    server web:7000;
}

server {
    listen 80;
    server_name mywebapp;
    location / {
        proxy_pass       http://mywebapp;
        proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header Host               $host;
        proxy_redirect   off;
    }
    location /static/ {
        alias /usr/src/app/public/;
    }
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}

server {
    # https://github.com/wmnnd/nginx-certbot/blob/master/data/nginx/app.conf
    listen 443    ssl;
    server_name   mywebapp;
    server_tokens off;

    location / {
        proxy_pass          http://mywebapp;
        proxy_set_header    Host                $http_host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    }

    # generated with help of certbot
    ssl_certificate     /etc/letsencrypt/live/mywebapp.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mywebapp.com/privkey.pem;
    include             /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam         /etc/letsencrypt/ssl-dhparams.pem;
}

最后是 nginx 服务 Dockerfile:

FROM nginx:1.15.12-alpine

RUN rm /etc/nginx/conf.d/default.conf
COPY ./nginx.prod.conf /etc/nginx/conf.d

我只是在本地机器上构建、推送到 ECR,然后在 EC2 实例上docker-compose pull运行。docker-compose up -d

我看到的错误docker-compose logs是:

nginx_1    | 2019/05/09 02:30:34 [error] 8#8: *1 connect() failed (111: Connection refused) while connecting to upstream, client: xx.xx.xx.xx, server: mywebapp, request: "GET / HTTP/1.1", upstream: "http://192.168.111.3:7000/", host: "ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com"

而且我不确定出了什么问题。我正在尝试使用我生成并验证的证书在 HTTPS 下正确提供动态内容(gunicorn)和静态内容(来自:/usr/src/app/public)。

有谁知道我可能做错了什么?

标签: djangodockernginxdocker-compose

解决方案


检查您的配置文件nginx -T- 您看到正确的配置了吗?您的构建过程是否引入了正确的配置?

仅在远程机器上调试它会很有帮助 -docker-compose exec nginx sh进入内部并从那里调整 conf 和nginx -s reload. 这将加快您调试 SSL 问题的迭代周期。


推荐阅读