Раскрытие порта websockets через одно и то же место dokku
У меня есть проект django, где я запускаю свои web и django каналы как отдельные procs в Procfile
:
web: gunicorn django_project.wsgi:application
socket: daphne django_project.asgi:application
И выставил ws
/wss
, используя dokku proxy:ports-add web ws:80:8000 wss:443:8000
(web
- это название моего приложения dokku):
=====> web proxy information
Proxy enabled: true
Proxy port map: http:80:5000 https:443:5000 ws:80:8000 wss:443:8000
Proxy type: nginx
Я выставил контейнерный порт 8000
, потому что по умолчанию daphne работает на порту 8000
:
app[socket.1]: Starting server at tcp:port=8000:interface=127.0.0.1
app[socket.1]: Configuring endpoint tcp:port=8000:interface=127.0.0.1
app[socket.1]: Listening on TCP address 127.0.0.1:8000
Но я не могу подключиться к своему websocket в браузере. Я получаю ошибку Not Found: /ws/mywebsocket
для конечной точки моего websocket, а функция socket.onclose
немедленно вызывается с ошибкой code: 1006
.
Я думаю, что мне нужно создать пользовательский nginx.sigil для dokku для перенаправления на websocket, если url содержит /ws/
, но многие ответы кажутся устаревшими и не работают.
Система отображения портов в Dokku передает отображение портов отдельным реализациям прокси, которые должны обрабатывать схему. Встроенный прокси-плагин nginx поддерживает только сопоставления портов http
и http
. Кроме того, он не имеет функциональности для отправки соединений с заданного отображения портов на заданный тип процесса.
Плагин nginx proxy открывает пользовательскую переменную .DOKKU_APP_${PROCESS_TYPE}_LISTENERS
для каждого PROCESS_TYPE
в вашем Procfile
, которую можно использовать в сочетании с пользовательской переменной nginx.conf.sigil
для:
- создайте пользовательский блок восходящего потока
- добавьте блок местоположения, указывающий на этот блок восходящего потока
Вы можете создать блок восходящего потока для вашего конкретного случая использования следующим образом:
# the variable maps to the Procfile entry. Replace `SOCKET` as appropriate for your process type name.
{{ if $.DOKKU_APP_SOCKET_LISTENERS }}
# this assumes the socket listening port is 8000
upstream {{ $.APP }}-socket-8000 {
{{ range $listeners := $.DOKKU_APP_SOCKET_LISTENERS | split " " }}
{{ $listener_list := $listeners | split ":" }}
{{ $listener_ip := index $listener_list 0 }}
server {{ $listener_ip }}:8000;{{ end }}
}
{{ end }}
Блок расположения будет выглядеть следующим образом:
location /ws/ {
proxy_pass http://{{ .APP }}-socket-8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection “upgrade”;
proxy_redirect off;
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 X-Forwarded-Host $server_name;
}