fix docker port

This commit is contained in:
Kevin
2026-05-22 15:11:22 +08:00
parent e92dc1a6d9
commit f28c0bd66d
6 changed files with 53 additions and 8 deletions

View File

@@ -91,8 +91,10 @@ POSTGRES_PORT=45432
# DEMO_ORCHESTRATOR_RTSP_PORT=18554
# 联调台 HLS 预览MediaMTX 8888 映射到宿主机端口API 反代给浏览器)
# DEMO_HLS_PREVIEW_PORT=18888
# API 在 Docker 内时设为 host.docker.internal
# API 在 Docker 内访问宿主机 HLShost.docker.internaldocker -p 会自动绑定 127.0.0.1
# DEMO_HLS_PREVIEW_HOST=127.0.0.1
# 可选:显式指定 docker -p 绑定地址(一般留空)
# DEMO_HLS_PREVIEW_BIND_HOST=127.0.0.1
# Docker 内 API 访问宿主机假流时写入站点 JSON 的主机名(默认 host.docker.internal
# DOCKER_DEMO_ORCHESTRATOR_RTSP_JSON_HOST=host.docker.internal
# 链路 2 simulated-start / fake_rtsp_from_file 起 MediaMTX 容器用

View File

@@ -36,7 +36,11 @@ from app.schemas import (
build_consumption_summary,
)
from app.services.recording_live import accept_live_recording
from app.services.hls_preview import HlsPreviewManager, fetch_hls_upstream
from app.services.hls_preview import (
HlsPreviewManager,
docker_publish_bind_host,
fetch_hls_upstream,
)
from app.services.rtsp_preview import capture_rtsp_jpeg_frame
from app.services.surgery_pipeline import SurgeryPipeline
from app.services.video.backend_resolver import BackendResolver
@@ -213,6 +217,10 @@ async def hls_preview_ensure(
)
hls_host = (settings.demo_hls_preview_host or "127.0.0.1").strip() or "127.0.0.1"
hls_port = int(settings.demo_hls_preview_port)
bind_host = docker_publish_bind_host(
hls_host,
explicit_bind=(settings.demo_hls_preview_bind_host or "").strip(),
)
resolver = BackendResolver(settings, hikvision_runtime=None)
sources: dict[str, str] = {}
@@ -238,6 +246,7 @@ async def hls_preview_ensure(
sources=sources,
hls_host=hls_host,
hls_port=hls_port,
bind_host=bind_host,
)
try:

View File

@@ -190,7 +190,13 @@ class Settings(BaseSettings):
demo_hls_preview_port: int = Field(default=18888, ge=1, le=65535)
demo_hls_preview_host: str = Field(
default="127.0.0.1",
description="MediaMTX HLS 监听地址;API 反代目标。容器内 API 可设为 host.docker.internal。",
description="API 反代访问的 MediaMTX HLS 地址;容器内 API 可设为 host.docker.internal。",
)
demo_hls_preview_bind_host: str = Field(
default="",
description=(
"docker run -p 绑定到宿主机的地址;留空时 host.docker.internal/localhost 自动用 127.0.0.1。"
),
)
#: 视觉管线记账默认 ``doctor_id``TSV 未提供医生列时的回退);语音确认仍为独立常量 ``voice``。

View File

@@ -22,6 +22,20 @@ from app.services.synthetic_rtsp import MEDIAMTX_IMAGE
CONTAINER_NAME_PREFIX = "orm-hls-preview-"
_MEDIAMTX_HLS_INTERNAL_PORT = 8888
_PATH_SAFE = re.compile(r"[^a-zA-Z0-9._-]+")
# docker -p 只接受 IP/0.0.0.0,不能写 host.docker.internal
_DOCKER_PUBLISH_ALIAS_HOSTS = frozenset(
{"host.docker.internal", "host.containers.internal", "localhost"}
)
def docker_publish_bind_host(hls_host: str, *, explicit_bind: str = "") -> str:
"""``docker run -p <bind>:port`` 用的宿主机地址;与 API 反代用的 ``hls_host`` 可不同。"""
if (explicit_bind or "").strip():
return explicit_bind.strip()
h = (hls_host or "").strip().lower()
if h in _DOCKER_PUBLISH_ALIAS_HOSTS:
return "127.0.0.1"
return (hls_host or "").strip() or "127.0.0.1"
def sanitize_mediamtx_path(name: str) -> str:
@@ -107,6 +121,7 @@ class HlsPreviewManager:
sources: dict[str, str],
hls_host: str,
hls_port: int,
bind_host: str | None = None,
ready_timeout_sec: float = 30.0,
) -> HlsPreviewSession:
"""链路 1独立 MediaMTX 容器按路径拉取各 RTSP。"""
@@ -129,6 +144,7 @@ class HlsPreviewManager:
cfg = work / "mediamtx.yml"
_write_mediamtx_config(cfg, mtx_paths)
publish_host = docker_publish_bind_host(hls_host, explicit_bind=bind_host or "")
container = CONTAINER_NAME_PREFIX + uuid.uuid4().hex[:12]
cmd = [
"docker",
@@ -139,7 +155,7 @@ class HlsPreviewManager:
"-v",
f"{cfg.resolve()}:/mediamtx.yml:ro",
"-p",
f"{hls_host}:{hls_port}:{_MEDIAMTX_HLS_INTERNAL_PORT}",
f"{publish_host}:{hls_port}:{_MEDIAMTX_HLS_INTERNAL_PORT}",
MEDIAMTX_IMAGE,
]
r = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
@@ -164,9 +180,11 @@ class HlsPreviewManager:
)
cls._active = sess
logger.info(
"HLS preview (pull) started container={} cameras={} hls=http://{}:{}/",
"HLS preview (pull) started container={} cameras={} publish={}:{} upstream=http://{}:{}/",
container,
list(path_by_camera),
publish_host,
hls_port,
hls_host,
hls_port,
)

View File

@@ -10,7 +10,11 @@ from fastapi.testclient import TestClient
from app.api import router as api_router
from app.config import Settings
from app.services.hls_preview import HlsPreviewManager, HlsPreviewSession
from app.services.hls_preview import (
HlsPreviewManager,
HlsPreviewSession,
docker_publish_bind_host,
)
@pytest.fixture
@@ -28,6 +32,12 @@ def hls_client(tmp_path) -> TestClient:
HlsPreviewManager.stop()
def test_docker_publish_bind_host_maps_docker_internal() -> None:
assert docker_publish_bind_host("host.docker.internal") == "127.0.0.1"
assert docker_publish_bind_host("127.0.0.1") == "127.0.0.1"
assert docker_publish_bind_host("host.docker.internal", explicit_bind="0.0.0.0") == "0.0.0.0"
def test_hls_preview_ensure_pull(hls_client: TestClient) -> None:
fake_sess = HlsPreviewSession(
hls_host="127.0.0.1",