Передача запросов от хоста к контейнеру с помощью доменного сокета
У меня есть uwsgi, запущенный в контейнере docker. Nginx работает на хосте.
Текущая настройка:
;uwsgi.ini
http-socket=:8080
С помощью docker я перенаправил порт 8080 хоста на порт 8080 контейнера. Nginx настроен следующим образом
server {
listen 443 ssl http2;
server_name domain.example.com;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
Это работает отлично, единственная проблема: мой порт 8080 открыт, и я могу напрямую запросить порт на публичном IP. Я должен быть в состоянии использовать доменные сокеты, чтобы смягчить это, но я не знаю, как это будет выглядеть.
Вот моя полупопытка:
; uwsgi.ini in container
socket=/path/uwsgi.sock
# nginx on host
upstream prod_server {
server unix:///path/uwsgi.sock;
}
server {
listen 443 ssl http2;
server_name example.domain.com;
location {
uwsgi_pass pror_server;
}
}
Поскольку nginx находится на хосте, он будет искать путь на хост-сервере, является ли добавление сокета в качестве тома правильным способом? Есть ли другая лучшая практика? Как бы вы рекомендовали настроить? Спасибо.
мой порт 8080 открыт, и я могу напрямую запросить порт на публичном IP
При публикации порта опции docker run -p
и Compose ports:
принимают необязательный IP-адрес. Это IP-адрес хоста, к которому Docker должен привязать внешний слушающий сокет. По умолчанию он равен 0.0.0.0, или "все интерфейсы", но вы можете указать 127.0.0.1, чтобы привязать его только к интерфейсу localhost хоста, и тогда бэкенд не будет доступен из других систем.
docker run -p 127.0.0.1:8080:8080 ...
# ^^^^^^^^^
ports:
- '127.0.0.1:8000:8000'
# ^^^^^^^^^
правильно ли добавлять сокет [Unix] в качестве тома?
Если вы хотите использовать здесь сокет Unix, вам нужно монтировать Docker bind mount (а не именованный том), причем монтировать нужно каталог, содержащий сокет, а не сам сокет. Это, вероятно, означает, что каталог должен быть пустым, поскольку содержимое каталога хоста полностью заменит содержимое образа - не пытайтесь использовать здесь каталог, содержащий код вашего приложения.
docker run -v /path:/path ...
# -v /host/path:/container/path ...
volumes:
- "/path:/path
Первый путь - это путь к хосту, он соответствует конфигурации Nginx; второй - это путь к контейнеру, он соответствует вашему файлу uwsgi.ini
. Эти два пути не обязательно должны совпадать.
Unix-сокеты могут вообще не работать на Docker Desktop или других установках на базе ВМ; они могут работать только на хосте native-Linux, на котором непосредственно запущен движок Docker.
Как бы вы рекомендовали настраивать?
Я бы запустил Nginx в контейнере, если это возможно. Тогда два контейнера смогут использовать сетевое взаимодействие Docker для связи, и вам не придется публиковать порт бэкенда.
Если прокси уже находится на хостовой системе (возможно, вы проксируете смесь контейнерных и неконтейнерных приложений, или несколько приложений, и нет смысла прикреплять прокси к какому-то одному конкретному), то я бы использовал TCP-сокет, но опубликованный только на хосте, как в первой половине. Это более простая настройка и позволяет избежать проблем с разрешениями файловой системы.