我正在尝试在 django + docker + nginx 环境中设置 ssl。但是我遇到了这个错误:
*19 connect() 连接到上游时失败(111:连接被拒绝),客户端:192.168.128.1,服务器:hello-1.local,请求:“GET / HTTP/1.1”,上游:“https://192.168.128.4:443/”,主机:“hello-1.local”
我的 Nginx 配置:
client_max_body_size 10M;
upstream web {
ip_hash;
server web:443;
}
server {
listen 80;
server_name hello-1.local;
return 301 https://$host$request_uri;
}
server {
location /static/ {
autoindex on;
alias /src/static/;
}
location /media/ {
autoindex on;
alias /src/media/;
}
``
location / {
proxy_pass https://web/;
}
listen 443 ssl;
server_name hello-1.local;
ssl_certificate /etc/certs/hello-1.local.crt;
ssl_certificate_key /etc/certs/hello-1.local.key;
}
docker-compose.yml:
version: "3"
volumes:
local_postgres_data: {}
local_postgres_data_backups: {}
services:
nginx:
image: nginx:alpine
container_name: nz01
ports:
- 443:443
- 80:80
volumes:
- ./src:/src
- ./config/nginx:/etc/nginx/conf.d
- ./config/certs:/etc/certs
depends_on:
- web
networks:
- djangonetwork
web:
build:
context: .
dockerfile: compose/django/Dockerfile
container_name: dz01
depends_on:
- db
volumes:
- ./src:/src
expose:
- 8000
links:
- redis
env_file:
- ./.envs/.django
networks:
- djangonetwork
db:
build:
context: .
dockerfile: compose/postgres/Dockerfile
container_name: pz01
env_file:
- ./.envs/.postgres
volumes:
- local_postgres_data:/var/lib/postgresql/data
- local_postgres_data_backups:/backups
networks:
- djangonetwork
redis:
image: redis:alpine
container_name: rz01
ports:
- "6379:6379"
networks:
- djangonetwork
networks:
djangonetwork:
driver: bridge
在浏览器中,我收到 502 Bad Gateway 错误,并且没有 SSL,网站运行良好。可能是什么问题?
答案1
那么上游是什么?
上游定义如下:
upstream web {
ip_hash;
server web:443;
}
我对此的第一印象是,Nginx 无法正确连接到名为的上游服务器web
。
这可能有多种原因:
- 你的 Nginx 无法解析
web
- 正在运行的 Web 服务器
web
未提供 https/port 443 服务 - 运行的 Web 服务器
web
未使用有效且受信任的主机名证书web
看一下你的docker-compose.yml:
- 应用程序
web
暴露在端口 8000 上,但你想连接到 Nginx 中的端口 443,也使用了错误的协议(我猜)
因此解决方案是像这样更改 nginx.conf 中的上游配置:
upstream web {
ip_hash;
server web:8000;
}
并且位置块如下(https --> http):
location / {
proxy_pass http://web/;
}
关于代理/上游的 SSL/TLS:请查看 Nginx 文档中的相关内容:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ssl_verify
答案2
我的 Web 应用程序中也有类似的设置,其中 Nginx 是 Dockerized Django 和 React 的反向代理。我在本地开发中也使用自签名证书进行 SSL。
我遇到了困难,因为 React (Next.js) 正在从 Django 的 REST API 获取数据——但有些请求来自服务器,而其他请求来自客户端。基于服务器的请求可以使用http://backend:8000
(Docker 服务名称和公开端口),但基于客户端的请求需要经过https://example.local
。
如果有人遇到这个问题并使用 Swagger UI(即 drf-yasg),这就是我的致命弱点——您需要配置 OpenAPI“DEFAULT_API_URL”。如果您有自签名 SSL 证书example.local
,则应将其设置https://example.local
为您的 Swagger URL。使用drf-yasg
,这是我的settings.py
:
# Swagger
ENDPOINT_DOMAIN = "https://example.com"
if DEBUG:
ENDPOINT_DOMAIN = "https://example.local"
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'basic': {
'type': 'basic'
}
},
'DEFAULT_API_URL': ENDPOINT_DOMAIN,
}
此外,我必须在我的 Next.js 配置中匹配这一点(next.config.js
):
const nextConfig = {
...
assetPrefix: 'https://example.local',
...
}
最后,我的 Nginx 配置如下:
server {
listen 80;
listen [::]:80;
server_name example.local;
return 302 https://example.local$request_uri;
}
# Main server directive
server {
http2 on;
listen 443 default ssl;
listen [::]:443 default ssl;
ssl_certificate /etc/nginx/certs/example.test.crt;
ssl_certificate_key /etc/nginx/certs/example.test.key;
root /app;
server_name example.local;
charset utf-8;
gzip on;
gzip_disable "msie6";
gzip_comp_level 6;
gzip_min_length 1100;
gzip_buffers 16 8k;
gzip_proxied any;
gzip_types
text/plain
text/css
text/js
text/xml
text/javascript
application/javascript
application/json
application/xml
application/rss+xml
image/svg+xml;
# Setup frontend requests to use port 3000
location @frontend {
internal;
root /app/frontend/;
proxy_pass http://frontend:3000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Url-Scheme $scheme;
}
# Setup backend requests to use port 8000
location @backend {
proxy_pass http://backend:8000;
proxy_redirect off;
proxy_ssl_verify off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Url-Scheme $scheme;
}
# Frontend =============================================
location / {
try_files $uri @frontend;
}
location ~ ^/assets/(.*)$ {
root /app/frontend/public/;
try_files $uri @frontend;
}
location ~ ^/favicon(.*)$ {
root /app/frontend/public/assets/favicon/;
try_files $uri @frontend;
}
location ~ ^/_next/(.*)$ {
root /app/frontend/;
try_files $uri @frontend;
}
location /_next/webpack-hmr {
root /app/frontend/;
try_files $uri @frontend;
# Websockets
proxy_http_version 1.1;
proxy_set_header Connection "upgrade";
proxy_set_header Upgrade $http_upgrade;
}
location /404 {
try_files $uri @frontend;
}
# Backend ===============================================
location ~ ^/swagger(.*)$ {
try_files $uri @backend;
}
location ~ ^/redoc(.*)$ {
try_files $uri @backend;
}
location ~ ^/admin(.*)$ {
try_files $uri @backend;
}
location ~ ^/api(.*)$ {
try_files $uri @backend;
}
location ~ ^/webmention(.*)$ {
try_files $uri @backend;
}
location ~ ^/rss(.*)$ {
try_files $uri @backend;
}
location /sitemap.xml {
try_files $uri @backend;
}
location ~ ^/static/(.*)$ {
root /app/backend/;
try_files $uri @backend;
autoindex on;
}
location ~ ^/uploads/(.*)$ {
root /app/backend/;
try_files $uri @backend;
}
location /(500|502|503|504) {
try_files $uri @backend;
}
# Error handling
error_page 404 /404;
error_page 500 502 503 504 /500;
}