%20%E5%A4%B1%E6%95%97%EF%BC%88111%EF%BC%9A%E9%80%A3%E7%B7%9A%E8%A2%AB%E6%8B%92%E7%B5%95%EF%BC%89%EF%BC%8C%E5%AE%A2%E6%88%B6%E7%AB%AF%EF%BC%9A192.168.128.1%EF%BC%8C%E4%BC%BA%E6%9C%8D%E5%99%A8%EF%BC%9Ahello-1.local.png)
我正在嘗試在 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
不提供 https/連接埠 443 - 運行的網路伺服器
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-docs: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;
}