docker - 如何在 Docker 容器中设置 SSL
问题描述
恢复
我有一Apache
台服务器在生产中运行两个应用程序。我想实现在 Django 中制作的其他应用程序,由Nginx
Docker 容器提供服务。架构如下:
User request --> Apache --> Nginx inside Docker --> Gunicorn inside Docker --> Django app inside Docker
我想要的是
我想实现SSL certbot certificate
,但我不知道应该如何使用 HTTPS 在主机(Apache)和容器(Nginx)之间建立通信。
- 我必须为 Apache 安装 Certbot 证书,而我可以为 Nginx 使用相同的证书吗?
- 主机中的 Apache 和容器中的 Nginx 之间的 HTTPS 重定向应该如何?.
我将这篇文章作为参考,其中实现了类似的架构,不同之处在于 Apache 安装在主机和 Docker 容器中,并且使用Certbot
为两个服务器创建的相同证书,但我不知道相同的逻辑是否适用在 Apache 和 Nginx 等不同服务器之间。
我有的
Apache 主机服务器配置文件
<VirtualHost *:80>
ServerName app.com.co
ServerAdmin webmaster@app.com.co
ErrorLog /var/log/app_com_co/error.log
CustomLog /var/log/app_com_co/access.log combined
ProxyPreserveHost On
ProxyPass "/" "http://127.0.0.1:1300/"
ProxyPassReverse "/" "http://127.0.0.1:1300/"
</VirtualHost>
# Apache SSL Relate things in host
<VirtualHost *:443>
ServerName app.com.co
ServerAdmin webmaster@app.com.co
ErrorLog /var/log/app_com_co/error.log
CustomLog /var/log/app_com_co/access.log combined
# Enable/Disable SSL for this virtual host.
SSLEngine on
# Activate SSL for proxy
SSLProxyEngine On
# Disable certificate verification in communication between host and container
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
# Defines that The host will pass the Host: line from the incoming request to
# the container instead of the hostname specified in the ProxyPass line.
ProxyPreserveHost On
ProxyPass "/" "https://127.0.0.1:14443/"
ProxyPassReverse "/" "https://127.0.0.1:14443/"
# Self signed SSL Certificate file
SSLCertificateFile /etc/letsencrypt/live/app.com.co/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/app.com.co/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
码头工人-compose.yml
version: '3.8'
services:
nginx:
build: ./nginx
ports:
- 1300:80
- 14443:443
depends_on:
- backend
networks:
- backend-tier
backend:
expose:
- 8000
build:
context: .
dockerfile: ./Dockerfile
restart: unless-stopped
networks:
- backend-tier
depends_on:
- db
- redis
volumes:
- ./app_com_co/:/app/app_com_co:Z
- ./app_com_co/templates/:/app/app_com_co/templates:Z
# shared volume between worker, beat and backend for media
- app-media:/app/app_com_co/media
env_file: common.env
db:
image: library/postgres:11.1-alpine
ports:
- 5439:5432
restart: unless-stopped
networks:
- backend-tier
volumes:
- app-db:/var/lib/postgresql/data
environment:
- POSTGRES_USER=myuser
- POSTGRES_PASSWORD=mypassword
- POSTGRES_DB=mydb
redis:
image: library/redis:5.0-alpine
ports:
- 6379:6379
restart: unless-stopped
networks:
- backend-tier
volumes:
- app-redis:/data
worker:
build:
context: .
dockerfile: ./Dockerfile
command: celery -A config --app=config.celery_app:app worker --loglevel=info
restart: unless-stopped
networks:
- backend-tier
env_file: common.env
depends_on:
- redis
volumes:
- ./app_com_co/:/app/app_com_co:Z,cached
- ./app_com_co/templates/:/app/app_com_co/templates:Z,cached
# shared volume between worker, beat and backend for media
- app-media:/app/app_com_co/media
beat:
build:
context: .
dockerfile: ./Dockerfile
command: celery -A config --app=config.celery_app:app beat --loglevel=info
restart: unless-stopped
networks:
- backend-tier
env_file: common.env
depends_on:
- redis
volumes:
- ./app_com_co/:/app/app_com_co:Z,cached
- ./app_com_co/templates/:/app/app_com_co/templates:Z,cached
# shared volume between worker, beat and backend for media
- app-media:/app/app_com_co/media
volumes:
app-db:
driver: local
app-redis:
driver: local
app-media:
networks:
backend-tier:
driver: bridge
Docker 容器内的 Nginx 配置
我不确定如何在 Docker 容器内的 Nginx 中配置 HTTPS 连接以接收来自 Apache 的 https 请求,然后重定向到 DJango 应用程序。
upstream django {
server backend:8000;
}
server {
listen 80;
location / {
proxy_pass http://django;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_redirect off;
client_max_body_size 4G;
}
}
解决方案
尽量让你的容器保持无状态,所以不要在容器内使用 certbot。而是将 certbot 用于 Apache 或您在应用程序容器之外拥有的任何 Web 服务器。
可以让 Apache 以纯 HTTP 与您的应用程序容器对话,因为您的容器不会暴露给公共网络(确保它只接受 localhost 连接)。许多人采取了更简单的方法并将 Cloudflare 用于 SSL,这意味着从 http 到 https 的切换发生在离最终用户更近的地方。
注意:这种让反向代理处理 SSL 而不是您的应用程序的方法称为“SSL 终止”。
推荐阅读
- javascript - 如何从状态访问卸载状态
- ros - catkin 如何与 ROS2 一起使用?
- c# - 直接从 HttpServer 返回响应
- java - 我想将我当前的移动日期与我的 firebase 日期进行比较,然后显示用户点击日期的数据
- c# - 从 AAD 登录获取令牌
- python - 为什么我的 QVideoFilterRunnable 在 PySide2 中的“run()”方法没有被执行?
- python - 每个进程运行多个蜘蛛 - 不保存输出数据
- symfony - Symfony 命令的 Docker 执行:权限被拒绝
- crop - 如何从android表面的媒体编解码器的dequeoutputbuffer裁剪视频缓冲区?
- laravel - 我如何测试 Laravel 护照 API 端点