podman fixes: bind docling-serve to 0.0, improve logging, support magic podman and docker hostnames
This commit is contained in:
parent
0dcfff15b3
commit
a5aab8e92a
3 changed files with 41 additions and 17 deletions
|
|
@ -37,6 +37,9 @@ AWS_SECRET_ACCESS_KEY=
|
|||
# OPTIONAL url for openrag link to langflow in the UI
|
||||
LANGFLOW_PUBLIC_URL=
|
||||
|
||||
# OPTIONAL: Override host for docling service (for special networking setups)
|
||||
# HOST_DOCKER_INTERNAL=host.containers.internal
|
||||
|
||||
# Langflow auth
|
||||
LANGFLOW_AUTO_LOGIN=False
|
||||
LANGFLOW_SUPERUSER=
|
||||
|
|
|
|||
|
|
@ -41,24 +41,37 @@ def determine_docling_host() -> str:
|
|||
"""Determine the host address used for docling health checks."""
|
||||
container_type = detect_container_environment()
|
||||
if container_type:
|
||||
# Try HOST_DOCKER_INTERNAL env var first
|
||||
container_host = get_container_host()
|
||||
if container_host:
|
||||
logger.info("Using container-aware host '%s'", container_host)
|
||||
return container_host
|
||||
|
||||
# Try special hostnames (Docker Desktop and rootless podman)
|
||||
import socket
|
||||
for hostname in ["host.docker.internal", "host.containers.internal"]:
|
||||
try:
|
||||
socket.getaddrinfo(hostname, None)
|
||||
logger.info("Using %s for container-to-host communication", hostname)
|
||||
return hostname
|
||||
except socket.gaierror:
|
||||
logger.debug("%s not available", hostname)
|
||||
|
||||
# Try gateway IP detection (Docker on Linux)
|
||||
gateway_ip = _get_gateway_ip_from_route()
|
||||
if gateway_ip:
|
||||
logger.info("Detected host gateway IP: %s", gateway_ip)
|
||||
return gateway_ip
|
||||
|
||||
# Either we're not inside a container or gateway detection failed.
|
||||
# Fallback to bridge IP
|
||||
fallback_ip = guess_host_ip_for_containers(logger=logger)
|
||||
if container_type:
|
||||
logger.info("Falling back to container bridge host %s", fallback_ip)
|
||||
else:
|
||||
logger.info("Running outside a container; using host %s", fallback_ip)
|
||||
return fallback_ip
|
||||
|
||||
# Running outside a container
|
||||
logger.info("Running outside a container; using localhost")
|
||||
return "localhost"
|
||||
|
||||
|
||||
# Detect the host IP once at startup
|
||||
HOST_IP = determine_docling_host()
|
||||
|
|
@ -70,10 +83,11 @@ async def health(request: Request) -> JSONResponse:
|
|||
Proxy health check to docling-serve.
|
||||
This allows the frontend to check docling status via same-origin request.
|
||||
"""
|
||||
health_url = f"{DOCLING_SERVICE_URL}/health"
|
||||
try:
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get(
|
||||
f"{DOCLING_SERVICE_URL}/health",
|
||||
health_url,
|
||||
timeout=2.0
|
||||
)
|
||||
|
||||
|
|
@ -83,6 +97,7 @@ async def health(request: Request) -> JSONResponse:
|
|||
"host": HOST_IP
|
||||
})
|
||||
else:
|
||||
logger.warning("Docling health check failed", url=health_url, status_code=response.status_code)
|
||||
return JSONResponse({
|
||||
"status": "unhealthy",
|
||||
"message": f"Health check failed with status: {response.status_code}",
|
||||
|
|
@ -90,13 +105,14 @@ async def health(request: Request) -> JSONResponse:
|
|||
}, status_code=503)
|
||||
|
||||
except httpx.TimeoutException:
|
||||
logger.warning("Docling health check timeout", url=health_url)
|
||||
return JSONResponse({
|
||||
"status": "unhealthy",
|
||||
"message": "Connection timeout",
|
||||
"host": HOST_IP
|
||||
}, status_code=503)
|
||||
except Exception as e:
|
||||
logger.error("Docling health check failed", error=str(e))
|
||||
logger.error("Docling health check failed", url=health_url, error=str(e))
|
||||
return JSONResponse({
|
||||
"status": "unhealthy",
|
||||
"message": str(e),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import threading
|
|||
import time
|
||||
from typing import Optional, Tuple, Dict, Any, List, AsyncIterator
|
||||
from utils.logging_config import get_logger
|
||||
from utils.container_utils import guess_host_ip_for_containers
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
|
@ -32,7 +31,8 @@ class DoclingManager:
|
|||
|
||||
self._process: Optional[subprocess.Popen] = None
|
||||
self._port = 5001
|
||||
self._host = guess_host_ip_for_containers(logger=logger) # Get appropriate host IP based on runtime
|
||||
# Bind to all interfaces by default (can be overridden with DOCLING_BIND_HOST env var)
|
||||
self._host = os.getenv('DOCLING_BIND_HOST', '0.0.0.0')
|
||||
self._running = False
|
||||
self._external_process = False
|
||||
|
||||
|
|
@ -150,16 +150,20 @@ class DoclingManager:
|
|||
else:
|
||||
pid = self._load_pid()
|
||||
|
||||
# Use localhost for display URLs when bound to 0.0.0.0
|
||||
display_host = "localhost" if self._host == "0.0.0.0" else self._host
|
||||
|
||||
return {
|
||||
"status": "running",
|
||||
"port": self._port,
|
||||
"host": self._host,
|
||||
"endpoint": f"http://{self._host}:{self._port}",
|
||||
"docs_url": f"http://{self._host}:{self._port}/docs",
|
||||
"ui_url": f"http://{self._host}:{self._port}/ui",
|
||||
"endpoint": f"http://{display_host}:{self._port}",
|
||||
"docs_url": f"http://{display_host}:{self._port}/docs",
|
||||
"ui_url": f"http://{display_host}:{self._port}/ui",
|
||||
"pid": pid
|
||||
}
|
||||
else:
|
||||
display_host = "localhost" if self._host == "0.0.0.0" else self._host
|
||||
return {
|
||||
"status": "stopped",
|
||||
"port": self._port,
|
||||
|
|
@ -176,10 +180,9 @@ class DoclingManager:
|
|||
return False, "Docling serve is already running"
|
||||
|
||||
self._port = port
|
||||
# Use provided host or the bridge IP we detected in __init__
|
||||
# Use provided host or keep default from __init__
|
||||
if host is not None:
|
||||
self._host = host
|
||||
# else: keep self._host as already set in __init__
|
||||
|
||||
# Check if port is already in use before trying to start
|
||||
import socket
|
||||
|
|
@ -293,7 +296,8 @@ class DoclingManager:
|
|||
self._running = False
|
||||
return False, f"Docling serve process exited immediately (code: {return_code})"
|
||||
|
||||
return True, f"Docling serve starting on http://{host}:{port}"
|
||||
display_host = "localhost" if self._host == "0.0.0.0" else self._host
|
||||
return True, f"Docling serve starting on http://{display_host}:{port}"
|
||||
|
||||
except FileNotFoundError:
|
||||
return False, "docling-serve not available. Please install: uv add docling-serve"
|
||||
|
|
@ -454,7 +458,8 @@ class DoclingManager:
|
|||
async def follow_logs(self) -> AsyncIterator[str]:
|
||||
"""Follow logs from the docling-serve process in real-time."""
|
||||
# First yield status message and any existing logs
|
||||
status_msg = f"Docling serve is running on http://{self._host}:{self._port}"
|
||||
display_host = "localhost" if self._host == "0.0.0.0" else self._host
|
||||
status_msg = f"Docling serve is running on http://{display_host}:{self._port}"
|
||||
|
||||
with self._log_lock:
|
||||
if self._log_buffer:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue