fix(deploy): switch to network_mode: host — reach postgis + ollama on loopback
The shared postgis container is bound to 127.0.0.1 on the host (security hardening, infrastructure §T12). Ollama is similarly LAN-hardened. The previous `host.docker.internal + extra_hosts: host-gateway` approach points at the bridge gateway IP, not loopback, so the container couldn't reach either service. Switch to `network_mode: host` (same pattern goldstein uses) and update the default IX_POSTGRES_URL / IX_OLLAMA_URL to 127.0.0.1. Keep the GPU reservation block; drop the now-meaningless ports: declaration (host mode publishes directly). AppConfig defaults + .env.example + test_config assertions + inline docstring examples all follow. Caught on fourth deploy attempt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
39a6c10634
commit
c7dc40c51e
6 changed files with 21 additions and 21 deletions
|
|
@ -4,10 +4,10 @@
|
||||||
# the Postgres password.
|
# the Postgres password.
|
||||||
|
|
||||||
# --- Job store -----------------------------------------------------------
|
# --- Job store -----------------------------------------------------------
|
||||||
IX_POSTGRES_URL=postgresql+asyncpg://infoxtractor:<password>@host.docker.internal:5431/infoxtractor
|
IX_POSTGRES_URL=postgresql+asyncpg://infoxtractor:<password>@127.0.0.1:5431/infoxtractor
|
||||||
|
|
||||||
# --- LLM backend ---------------------------------------------------------
|
# --- LLM backend ---------------------------------------------------------
|
||||||
IX_OLLAMA_URL=http://host.docker.internal:11434
|
IX_OLLAMA_URL=http://127.0.0.1:11434
|
||||||
IX_DEFAULT_MODEL=qwen3:14b
|
IX_DEFAULT_MODEL=qwen3:14b
|
||||||
|
|
||||||
# --- OCR -----------------------------------------------------------------
|
# --- OCR -----------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,21 @@
|
||||||
# InfoXtractor Docker Compose stack.
|
# InfoXtractor Docker Compose stack.
|
||||||
#
|
#
|
||||||
# Single service. Postgres + Ollama live in separate long-running
|
# Single service. Uses host networking so the container can reach:
|
||||||
# containers on the host (postgis + ollama); we reach them via
|
# - Ollama at 127.0.0.1:11434
|
||||||
# `host.docker.internal`, which is mapped to the gateway through
|
# - postgis at 127.0.0.1:5431 (bound to loopback only; security hardening)
|
||||||
# `extra_hosts` so the container works whether the Compose plugin version
|
# Both services are LAN-hardened on the host and never exposed publicly,
|
||||||
# adds it automatically or not.
|
# so host-network access stays on-prem. This matches the `goldstein`
|
||||||
|
# container pattern on the same server.
|
||||||
#
|
#
|
||||||
# The GPU reservation block matches the shape used by immich-ml /
|
# The GPU reservation block matches immich-ml / the shape Docker Compose
|
||||||
# monitoring on the same host, so the existing NVIDIA runtime
|
# expects for GPU allocation on this host.
|
||||||
# configuration applies without changes.
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
infoxtractor:
|
infoxtractor:
|
||||||
build: .
|
build: .
|
||||||
container_name: infoxtractor
|
container_name: infoxtractor
|
||||||
|
network_mode: host
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
|
||||||
- "8994:8994"
|
|
||||||
env_file: .env
|
env_file: .env
|
||||||
deploy:
|
deploy:
|
||||||
resources:
|
resources:
|
||||||
|
|
@ -30,5 +29,3 @@ services:
|
||||||
backup.enable: "true"
|
backup.enable: "true"
|
||||||
backup.type: "postgres"
|
backup.type: "postgres"
|
||||||
backup.name: "infoxtractor"
|
backup.name: "infoxtractor"
|
||||||
extra_hosts:
|
|
||||||
- "host.docker.internal:host-gateway"
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ Mac (dev)
|
||||||
│ curl /healthz (60 s gate)
|
│ curl /healthz (60 s gate)
|
||||||
▼
|
▼
|
||||||
Docker container `infoxtractor` (port 8994)
|
Docker container `infoxtractor` (port 8994)
|
||||||
├─ host.docker.internal:11434 → Ollama (qwen3:14b)
|
├─ 127.0.0.1:11434 → Ollama (qwen3:14b; host-network mode)
|
||||||
└─ host.docker.internal:5431 → postgis (database `infoxtractor`)
|
└─ 127.0.0.1:5431 → postgis (database `infoxtractor`; host-network mode)
|
||||||
```
|
```
|
||||||
|
|
||||||
## One-time server setup
|
## One-time server setup
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,16 @@ class AppConfig(BaseSettings):
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- Job store ---
|
# --- Job store ---
|
||||||
|
# Defaults assume the ix container runs with `network_mode: host` and
|
||||||
|
# reaches the shared `postgis` and `ollama` containers on loopback;
|
||||||
|
# spec §11 / docker-compose.yml ship that configuration.
|
||||||
postgres_url: str = (
|
postgres_url: str = (
|
||||||
"postgresql+asyncpg://infoxtractor:<password>"
|
"postgresql+asyncpg://infoxtractor:<password>"
|
||||||
"@host.docker.internal:5431/infoxtractor"
|
"@127.0.0.1:5431/infoxtractor"
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- LLM backend ---
|
# --- LLM backend ---
|
||||||
ollama_url: str = "http://host.docker.internal:11434"
|
ollama_url: str = "http://127.0.0.1:11434"
|
||||||
default_model: str = "qwen3:14b"
|
default_model: str = "qwen3:14b"
|
||||||
|
|
||||||
# --- OCR ---
|
# --- OCR ---
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ class OllamaClient:
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
base_url:
|
base_url:
|
||||||
Root URL of the Ollama server (e.g. ``http://host.docker.internal:11434``).
|
Root URL of the Ollama server (e.g. ``http://127.0.0.1:11434``).
|
||||||
Trailing slashes are stripped.
|
Trailing slashes are stripped.
|
||||||
per_call_timeout_s:
|
per_call_timeout_s:
|
||||||
Hard per-call timeout for ``/api/chat``. Spec default: 1500 s.
|
Hard per-call timeout for ``/api/chat``. Spec default: 1500 s.
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,9 @@ def test_defaults_match_spec(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||||
|
|
||||||
assert cfg.postgres_url == (
|
assert cfg.postgres_url == (
|
||||||
"postgresql+asyncpg://infoxtractor:<password>"
|
"postgresql+asyncpg://infoxtractor:<password>"
|
||||||
"@host.docker.internal:5431/infoxtractor"
|
"@127.0.0.1:5431/infoxtractor"
|
||||||
)
|
)
|
||||||
assert cfg.ollama_url == "http://host.docker.internal:11434"
|
assert cfg.ollama_url == "http://127.0.0.1:11434"
|
||||||
assert cfg.default_model == "qwen3:14b"
|
assert cfg.default_model == "qwen3:14b"
|
||||||
assert cfg.ocr_engine == "surya"
|
assert cfg.ocr_engine == "surya"
|
||||||
assert cfg.tmp_dir == "/tmp/ix"
|
assert cfg.tmp_dir == "/tmp/ix"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue