%20%E3%81%8C%E5%A4%B1%E6%95%97%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%20(111%3A%20%E6%8E%A5%E7%B6%9A%E3%81%8C%E6%8B%92%E5%90%A6%E3%81%95%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F)%E3%80%82%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%3A%20192.168.128.1%E3%80%81%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%3A%20hello-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 がなくても Web サイトは正常に動作します。何が問題なのでしょうか?
答え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-config を次のように変更します。
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 証明書をお持ちの場合は、 をSwagger URL としてexample.local
設定する必要があります。 の場合、私の は次のとおりです。https://example.local
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;
}