%20%D0%BD%D0%B5%20%D1%83%D0%B4%D0%B0%D0%BB%D0%BE%D1%81%D1%8C%20(111%3A%20%D1%81%D0%BE%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5%20%D0%BE%D1%82%D0%BA%D0%BB%D0%BE%D0%BD%D0%B5%D0%BD%D0%BE)%20%D0%BF%D1%80%D0%B8%20%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B8%20%D0%BA%20%D0%B2%D0%BE%D1%81%D1%85%D0%BE%D0%B4%D1%8F%D1%89%D0%B5%D0%BC%D1%83%20%D0%BF%D0%BE%D1%82%D0%BE%D0%BA%D1%83%2C%20%D0%BA%D0%BB%D0%B8%D0%B5%D0%BD%D1%82%3A%20192.168.128.1%2C%20%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%3A%20hello-1.local.png)
Я пытаюсь настроить ssl в моей среде django + docker + nginx. Однако я столкнулся с этой ошибкой:
*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, но вы хотите подключиться к порту 443 в Nginx, также используя неправильный протокол (я полагаю)
Поэтому решением будет изменить upstream-config в 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
У меня похожая настройка в моем веб-приложении, где Nginx является обратным прокси для Dockerized Django и React. Я также использую самоподписанный сертификат для SSL в локальной разработке.
У меня возникли трудности, поскольку React (Next.js) извлекает данные из REST API Django, но некоторые запросы поступают с сервера, а другие — с клиента. Серверные запросы могли использовать 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;
}