Вопрос или проблема
Я наткнулся на проблему конфигурации, которую считал относительно легкой для решения. К сожалению, это, похоже, не так.
Вот в чем проблема: я хотел бы использовать несколько docker экземпляров Jupyter notebooks для обслуживания проекта документации, состоящего из нескольких документов (использование JupyterHub не рассматривается в данный момент). Каждый docker экземпляр был бы подключен к «внешнему» docker мосту, чтобы каждый экземпляр был доступен через его DNS имя. Но для простоты я сначала начинаю здесь с доступа к одному экземпляру через его отображаемый порт на 127.0.0.1:8888. Я хотел бы, чтобы опубликованный документ (скомпилированный с помощью dockerized Sphinx, также встроенного в контейнер) появился, например, под https://exemple.com/document1
, а его «редактируемая» версия была доступна под https://exemple.com/document1/edit
.
Вот моя конфигурация Nginx (только релевантные части):
upstream jupyter {
server 127.0.0.1:8888;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name exemple.com
include snippets/letsencrypt.conf;
if ($request_uri !~ ^/\.well-known) {
rewrite ^(.*) https://$host$1 permanent;
}
}
server {
# server port and name
listen 443 ssl http2;
server_name exemple.com;
# Let's Encrypt SSL
....
if ($request_uri ~* ^(.*)\/edit) {
rewrite ^(.*)$ /edit/$1;
}
location / {
alias /var/www/document1/_build/html/;
index index.html index.htm;
}
location /edit/ {
# Proxy
rewrite ^(.*)\/edit\/(.*)$ $1/$2 break;
proxy_pass http://jupyter;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Я думал, что расположение “/edit/” должно иметь приоритет над “/edit” и, следовательно, передавать запросы на сервис docker 127.0.0.1:8888. URL https://exemple.com/document1
обслуживается правильно, но при переходе на https://exemple.com/document1/edit
я вижу, что веб-запросы обслуживаются правильно, но кажется, что websocket соединение закрывается, как только активируется.
См. журнал сети Chrome
Что я упускаю здесь?
Заранее большое спасибо за любые подсказки 😉
Ответ или решение
Конфигурация Nginx, используемая для проксирования запросов и веб-сокетов к докеру Jupyter, может вызвать затруднения, особенно при настройке нескольких переписываний URL и подключении веб-сокетов. Рассмотрим проблему более подробно.
Теория
Nginx часто используется в качестве обратного прокси-сервера для управления входящими запросами и распределения их к соответствующим сервисам, которые могут работать в отдельных контейнерах Docker. Он также может выступать в качестве SSL-терминатора, обеспечивая шифрование на уровне транспортного слоя. В данной конфигурации основной задачей является обеспечение доступности документов, генерируемых с использованием Sphinx и Jupyter, а также правильная маршрутизация запросов, включая поддержку веб-сокетов для редактирования.
Пример
В вашем случае, конфигурация Nginx состоит из двух серверных блоков для обработки HTTP и HTTPS запросов. Особое внимание уделяется следующему:
- Переписывание запросов: Используется для направления запросов с
/edit
на соответствующий проксирующий сервер. - Поддержка веб-сокетов: Настройки веб-сокетов, такие как
proxy_set_header Upgrade
иproxy_set_header Connection
, необходимы, чтобы уведомить сервер о том, что соединение должно быть "повышено" до веб-сокета.
Проблема
Ваше описание проблемы включает в себя корректное отображение страниц по адресу https://exemple.com/document1
, но сбой подключения веб-сокетов при доступе к https://exemple.com/document1/edit
. Это указывает на вероятные проблемы с переработкой URI и маршрутизацией веб-сокетов.
Кроме того, ваш код содержит некоторые потенциальные ошибки:
-
Включение блоков
if
может вызывать неожиданные эффекты при работе со сложными конфигурациями. В контексте Nginxif
может иногда приводить к неожиданному поведению, особенно когда конфигурация сети должна учитывать веб-сокеты. -
Переписывания в блоке
location
, особенно с условиемbreak
, могут вызывать конфликт с обработкой заголовков веб-сокетов. Веб-сокеты требуют устойчивого соединения, и здесь важно убедиться, что заголовки обработаны правильно. -
SSL-настройки и их отсутствие в предоставленном коде. Без полной конфигурации SSL возможно, что какие-то заголовки или параметры запроса могут быть потеряны.
Решение
Теперь давайте рассмотрим, как можно решить данную проблему:
-
Проверка переписывания URL: Проверьте порядок переписывания и убедитесь, что маршрутизация определяется правильно. Также избегайте использования условных операций, которые могут привести к неожиданным последствиям в контексте Nginx.
-
Настройка веб-сокетов: Убедитесь, что все необходимые заголовки для веб-сокетов правильно установлены, и что переписывание не прерывает установленное соединение.
-
Логи и отладка: Включите подробные логи, чтобы увидеть точную точку, в которой происходит разрыв соединения. Это часто помогает выявить проблему на стороне клиента или сервера.
-
Проверка Docker-сети: Проверяйте, что докер-контейнеры правильно настроены для взаимодействия с хост-сетью и имеют доступ к необходимым для работы порту и DNS-именам.
Пример доработанной конфигурации
upstream jupyter {
server 127.0.0.1:8888;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name exemple.com;
include snippets/letsencrypt.conf;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
server_name exemple.com;
# Добавьте ваши SSL конфигурации
location /document1 {
alias /var/www/document1/_build/html/;
index index.html index.htm;
}
location /document1/edit {
proxy_pass http://jupyter;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Заключение
Корректная настройка Nginx с поддержкой веб-сокетов может быть непростой задачей в среде с несколькими сервисами и переписываниями URL. При этом важно тщательно проверить конфигурацию и использовать отладочные средства, чтобы выявить и корректировать проблемы на ранних стадиях настройки системы.