host_ip fix
This commit is contained in:
@@ -29,4 +29,4 @@ EXPOSE 8000
|
|||||||
|
|
||||||
# По умолчанию запускаем uvicorn — принимаем HOST и PORT из переменных окружения
|
# По умолчанию запускаем uvicorn — принимаем HOST и PORT из переменных окружения
|
||||||
# Если переменные не заданы, используются значения по умолчанию
|
# Если переменные не заданы, используются значения по умолчанию
|
||||||
CMD ["sh", "-c", "uvicorn server:app --host ${HOST:-0.0.0.0} --port ${PORT:-8000}"]
|
CMD ["sh", "-c", "uvicorn server:app --host ${BIND_HOST:-0.0.0.0} --port ${PORT:-8000}"]
|
||||||
|
|||||||
@@ -26,3 +26,20 @@ docker-compose up --build
|
|||||||
Примечания:
|
Примечания:
|
||||||
- Если у вас headless-сервер и вы не используете GUI-возможности OpenCV, рассмотрите замену `opencv-python` на `opencv-python-headless` в `req.txt`.
|
- Если у вас headless-сервер и вы не используете GUI-возможности OpenCV, рассмотрите замену `opencv-python` на `opencv-python-headless` в `req.txt`.
|
||||||
- При проблемах со сборкой на некоторых платформах установите необходимые системные пакеты (в Dockerfile уже перечислены распространённые зависимости).
|
- При проблемах со сборкой на некоторых платформах установите необходимые системные пакеты (в Dockerfile уже перечислены распространённые зависимости).
|
||||||
|
|
||||||
|
Разделение адресов для биндинга и отображения (важно)
|
||||||
|
- BIND_HOST — адрес, на котором uvicorn внутри контейнера будет слушать соединения. По умолчанию это 0.0.0.0 (в контейнере). Не ставьте сюда внешний IP хоста, если вы запускаете в контейнере.
|
||||||
|
- PUBLIC_HOST (или ADVERTISED_HOST) — адрес, который будет показан в UI (dashboards, ws-URL). Укажите сюда реальный IP хоста (например, 192.168.0.112) или публичный адрес.
|
||||||
|
|
||||||
|
Пример `.env` для корректной работы в Docker:
|
||||||
|
|
||||||
|
```
|
||||||
|
# BIND_HOST указывает, на каком интерфейсе внутри контейнера слушать (оставьте 0.0.0.0)
|
||||||
|
BIND_HOST=0.0.0.0
|
||||||
|
# PORT — хостовый порт (docker-compose подставит его в маппинг)
|
||||||
|
PORT=8000
|
||||||
|
# PUBLIC_HOST — адрес, который будет отображаться в UI (реальный адрес машины)
|
||||||
|
PUBLIC_HOST=192.168.0.112
|
||||||
|
```
|
||||||
|
|
||||||
|
Если в `.env` у вас был `HOST=192.168.0.112`, то Docker раньше пробрасывал эту переменную в контейнер и uvicorn пытался биндиться на этот адрес — внутри контейнера такого адреса может не быть, и bind завершался ошибкой `cannot assign requested address`. Поэтому важно разделять `BIND_HOST` (bind) и `PUBLIC_HOST` (advertised).
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ services:
|
|||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
# Хостовый порт можно переопределить через переменную PORT в .env, по умолчанию 8000
|
||||||
|
- "${PORT:-8000}:8000"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ./static:/app/static
|
- ./static:/app/static
|
||||||
|
|||||||
38
server.py
38
server.py
@@ -38,7 +38,8 @@ load_dotenv()
|
|||||||
|
|
||||||
# ========== КОНФИГУРАЦИЯ ==========
|
# ========== КОНФИГУРАЦИЯ ==========
|
||||||
SERVER_CONFIG = {
|
SERVER_CONFIG = {
|
||||||
"host": os.getenv("host", "0.0.0.0"), # сюда IP смотрящий наружу или 0.0.0.0 для всех интерфейсов
|
# считываем переменную окружения HOST (или legacy 'host'), чтобы можно было управлять через .env / docker-compose
|
||||||
|
"host": os.getenv("HOST", os.getenv("host", "0.0.0.0")), # сюда IP смотрящий наружу или 0.0.0.0 для всех интерфейсов
|
||||||
"port": 8000,
|
"port": 8000,
|
||||||
"debug": False,
|
"debug": False,
|
||||||
"max_clients_per_room": 50,
|
"max_clients_per_room": 50,
|
||||||
@@ -97,13 +98,42 @@ def safe_json_serializer(obj: Any) -> Any:
|
|||||||
|
|
||||||
def get_server_host():
|
def get_server_host():
|
||||||
"""Получение IP адреса сервера"""
|
"""Получение IP адреса сервера"""
|
||||||
try:
|
|
||||||
import socket
|
import socket
|
||||||
|
|
||||||
|
# 0) Если явно задан адрес, который должен отображаться в UI (рекомендуется при запуске в Docker), используем его
|
||||||
|
public_host = os.getenv("PUBLIC_HOST") or os.getenv("ADVERTISED_HOST")
|
||||||
|
if public_host and public_host not in ("", "0.0.0.0", "127.0.0.1", "localhost"):
|
||||||
|
return public_host
|
||||||
|
|
||||||
|
# 1) Если в конфиге явно указан хост (и это не 0.0.0.0 / localhost), используем его
|
||||||
|
cfg_host = SERVER_CONFIG.get("host")
|
||||||
|
if cfg_host and cfg_host not in ("0.0.0.0", "127.0.0.1", "localhost", ""):
|
||||||
|
return cfg_host
|
||||||
|
|
||||||
|
# 2) Попытка определить внешний IP без отправки данных — UDP socket к публичному адресу
|
||||||
|
try:
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
# Не устанавливаем реального соединения, просто используем маршрутную информацию
|
||||||
|
s.connect(("8.8.8.8", 80))
|
||||||
|
ip_address = s.getsockname()[0]
|
||||||
|
s.close()
|
||||||
|
|
||||||
|
if ip_address and not ip_address.startswith("127."):
|
||||||
|
return ip_address
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# 3) Попытка через hostname (может вернуть 127.0.1.1 на некоторых системах)
|
||||||
|
try:
|
||||||
hostname = socket.gethostname()
|
hostname = socket.gethostname()
|
||||||
ip_address = socket.gethostbyname(hostname)
|
ip_address = socket.gethostbyname(hostname)
|
||||||
|
if ip_address and not ip_address.startswith("127."):
|
||||||
return ip_address
|
return ip_address
|
||||||
except:
|
except Exception:
|
||||||
return SERVER_CONFIG["host"]
|
pass
|
||||||
|
|
||||||
|
# 4) Фолбэк — вернуть значение из конфига (возможно 0.0.0.0 или что задано в ENV)
|
||||||
|
return cfg_host or "0.0.0.0"
|
||||||
|
|
||||||
# ========== КЛАССЫ ДЛЯ УПРАВЛЕНИЯ ==========
|
# ========== КЛАССЫ ДЛЯ УПРАВЛЕНИЯ ==========
|
||||||
class RoomManager:
|
class RoomManager:
|
||||||
|
|||||||
Reference in New Issue
Block a user