Docker-compose + Nginx + Certbot +简单Django Rest框架应用

lvjbypge  于 2022-11-22  发布在  Nginx
关注(0)|答案(2)|浏览(386)

我正在尝试使用Docker将一个简单的Django Rest Framework应用部署到生产服务器。我的目标是同时安装Nginx代理和常规Let'sEncrypt SSL的Certbot。我在DockerFiles和Docker-compose中管理我的依赖项。
因此,文件夹结构具有以下视图:

  • 应用程序
  • 停靠文件
  • 恩金
  • 停靠文件
  • init-letsencrypt.sh
  • nginx.conf
  • docker-compose.yml

我的想法是在app/docker-compose.yml中保存所有的配置,并从同一个源代码启动许多不同的示例。但我在app/DockerFile中没有任何nginx或certbot配置--这只适用于Django Rest Framework,并且运行良好。但在docker-compose.yml中,我有以下代码:

version: '3'

'services':
    app:
      container_name: djangoserver
      command: gunicorn prototyp.wsgi:application --env DJANGO_SETTINGS_MODULE=prototyp.prod_settings --bind 0.0.0.0:8000 --workers=2 --threads=4 --worker-class=gthread
      build:
        context: ./api
        dockerfile: Dockerfile
      restart: always
      ports:
        - "8000:8000"
      depends_on:
        - otherserver
    otherserver:
      container_name: otherserver
      build:
        context: ./otherserver
        dockerfile: Dockerfile
      restart: always
    nginx:
      build: ./nginx
      ports:
         - 80:80
      depends_on:
         - app
      command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
    certbot:
      image: certbot/certbot
      entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

这使我建立“app”,“otherserver”,“nginx”和“certbot”。最重要的部分是在“nginx”文件夹。我使用this manual和克隆文件“init-letsencrypt.sh“从源代码只是它被描述的方式。然后我试图猛击它:

nginx/停靠文件

FROM nginx:1.19.0-alpine
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
RUN mkdir -p /usr/src/app
COPY init-letsencrypt.sh /usr/src/app
WORKDIR /usr/src/app
RUN chmod +x init-letsencrypt.sh
ENTRYPOINT ["/usr/src/app/init-letsencrypt.sh"]

nginx/nginx.conf中,我有以下代码:

upstream django {
    server app:8000;
}

server {
    listen 80;
    server_name app.com www.app.com;
    location / {
        return 301 https://$host$request_uri;
    }
}

server {

    listen 443 ssl;
    server_name app.com www.app.com;
    access_log /var/log/nginx-access.log;
    error_log /var/log/nginx-error.log;

    ssl_certificate /etc/letsencrypt/live/app.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location ^/static/rest_framework/((img/|css/|js/|fonts).*)$ {
        autoindex on;
        access_log off;
        alias /usr/src/app/static/rest_framework/$1;
    }

    location / {
        proxy_pass http://django;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_body_buffer_size 256k;

        proxy_connect_timeout 120;
        proxy_send_timeout 120;
        proxy_read_timeout 120;

        proxy_buffer_size 64k;
        proxy_buffers 4 64k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        client_max_body_size 100M;
    }
}

因此,当我进行“docker-compose构建”时,使用此配置,构建工作没有任何错误,一切都成功构建。但我一做“docker-compose up”,我就遇到了certbot和nginx没有连接的问题,应用程序只有在我使用http://app.com:8000而不是https://app.com时才能工作。在控制台中,我没有任何错误。我做错了什么?我错过了什么?任何帮助都将不胜感激。

vzgqcmou

vzgqcmou1#

在你的设置中,你试图在nginx容器中运行let 's encrypt。但是我相信有一个更好的方法,我在here中详细描述了。这个方法的想法是用一个docker-compose文件来初始化letssencrypt证书,另一个docker-compose文件来运行系统和更新证书。
因此,不用再多说了,这里是文件结构和内容,是工作真的很好,为我(您仍然需要适应文件,以适应您的需要)

  • setup.sh
  • ./停驻-撰写-初始化.yaml
  • ./停靠-组合.yaml
  • ./etc/nginx/模板/默认配置模板
  • ./etc/nginx/模板初始化/默认配置模板

设置分为两个阶段:

在第一个阶段“初始化阶段”中,我们将运行一个nginx容器和一个certbot容器,以首次获取ssl证书并将其存储在主机上。/etc/letsencrypt文件夹
在第二个阶段“操作阶段”,我们运行应用程序的所有必要服务,包括nginx,这次它将使用letsencrypt文件夹在端口443上提供https服务,certbot容器也将运行(按需)来更新证书。我们可以为此添加一个cron作业。因此,setup.sh脚本是一个简单的方便脚本,它一个接一个地运行命令:

#!/bin/bash
# the script expects two arguments:
# - the domain name for which we are obtaining the ssl certificatee
# - the Email address associated with the ssl certificate
echo DOMAIN=$1 >> .env
echo EMAIL=$2 >> .env

# Phase 1 "Initiation"
docker-compose -f ./docker-compose-first.yaml up -d nginx
docker-compose -f ./docker-compose-first.yaml up certbot
docker-compose -f ./docker-compose-first.yaml down

# Phase 2 "Operation"    
crontab ./etc/crontab
docker-compose -f ./docker-compose.yaml up -d

阶段1:SSL证书初始化阶段:

./停驻-撰写-初始化.yaml

version: "3"
services:
  nginx:
    container_name: nginx
    image: nginx:latest
    environment:
      - DOMAIN
    ports:
      - 80:80
    volumes:
      - ./etc/nginx/templates-initiate:/etc/nginx/templates:ro
      - ./etc/letsencrypt:/etc/letsencrypt:ro
      - ./certbot/data:/var/www/certbot
  certbot:
    container_name: certbot
    image: certbot/certbot:latest
    depends_on:
      - nginx
    command: >- 
             certonly --reinstall --webroot --webroot-path=/var/www/certbot
             --email ${EMAIL} --agree-tos --no-eff-email
             -d ${DOMAIN}
    volumes:
      - ./etc/letsencrypt:/etc/letsencrypt
      - ./certbot/data:/var/www/certbot

./etc/nginx/模板初始化/默认配置模板

server {
    listen [::]:80;
    listen 80;
    server_name $DOMAIN;
    location ~/.well-known/acme-challenge {
        allow all;
        root /var/www/certbot;
    }
}

阶段2:操作阶段

./停靠-组合.yaml

services:
  app:
    {{your_configurations_here}}
  {{other_services...}}:
    {{other_services_configuraitons}}
  nginx:
    container_name: nginx
    image: nginx:latest
    restart: always
    environment:
      - DOMAIN
    depends_on:
      - app
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./etc/nginx/templates:/etc/nginx/templates:ro
      - ./etc/letsencrypt:/etc/letsencrypt
      - ./certbot/data:/var/www/certbot
      - /var/log/nginx:/var/log/nginx
  certbot:
    container_name: certbot
    image: certbot/certbot:latest
    depends_on:
      - nginx
    command: >-
             certonly --reinstall --webroot --webroot-path=/var/www/certbot
             --email ${EMAIL} --agree-tos --no-eff-email
             -d ${DOMAIN} 
    volumes:
      - ./etc/letsencrypt:/etc/letsencrypt
      - ./certbot/data:/var/www/certbot

./etc/nginx/模板/默认配置模板

server {
    listen [::]:80;
    listen 80;

    server_name $DOMAIN;

    return 301 https://$host$request_uri;
}
server {
    listen [::]:443 ssl http2;
    listen 443 ssl http2;

    server_name $DOMAIN; 

    ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;

    location ~ /.well-known/acme-challenge {
        allow all;
        root /var/www/html;
    }

    access_log  /var/log/nginx/access.log;
    error_log   /var/log/nginx/error.log;

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Proto https;
      proxy_pass http://app:80;
  }
}
j0pj023g

j0pj023g2#

正如我所看到的,您还没有公开nginx容器的端口443:

nginx:
      build: ./nginx
      ports:
         - 80:80
         - 443:443
      depends_on:

添加更多443端口。

相关问题