Compare commits

...

2 commits

Author SHA1 Message Date
44c3428993 fix(deploy): network_mode: host (#34)
Some checks failed
tests / test (push) Has been cancelled
2026-04-18 11:00:14 +00:00
c7dc40c51e fix(deploy): switch to network_mode: host — reach postgis + ollama on loopback
All checks were successful
tests / test (push) Successful in 1m12s
tests / test (pull_request) Successful in 1m10s
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>
2026-04-18 13:00:02 +02:00
6 changed files with 21 additions and 21 deletions

View file

@ -4,10 +4,10 @@
# the Postgres password.
# --- 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 ---------------------------------------------------------
IX_OLLAMA_URL=http://host.docker.internal:11434
IX_OLLAMA_URL=http://127.0.0.1:11434
IX_DEFAULT_MODEL=qwen3:14b
# --- OCR -----------------------------------------------------------------

View file

@ -1,22 +1,21 @@
# InfoXtractor Docker Compose stack.
#
# Single service. Postgres + Ollama live in separate long-running
# containers on the host (postgis + ollama); we reach them via
# `host.docker.internal`, which is mapped to the gateway through
# `extra_hosts` so the container works whether the Compose plugin version
# adds it automatically or not.
# Single service. Uses host networking so the container can reach:
# - Ollama at 127.0.0.1:11434
# - postgis at 127.0.0.1:5431 (bound to loopback only; security hardening)
# Both services are LAN-hardened on the host and never exposed publicly,
# 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 /
# monitoring on the same host, so the existing NVIDIA runtime
# configuration applies without changes.
# The GPU reservation block matches immich-ml / the shape Docker Compose
# expects for GPU allocation on this host.
services:
infoxtractor:
build: .
container_name: infoxtractor
network_mode: host
restart: always
ports:
- "8994:8994"
env_file: .env
deploy:
resources:
@ -30,5 +29,3 @@ services:
backup.enable: "true"
backup.type: "postgres"
backup.name: "infoxtractor"
extra_hosts:
- "host.docker.internal:host-gateway"

View file

@ -14,8 +14,8 @@ Mac (dev)
│ curl /healthz (60 s gate)
Docker container `infoxtractor` (port 8994)
├─ host.docker.internal:11434 → Ollama (qwen3:14b)
└─ host.docker.internal:5431 → postgis (database `infoxtractor`)
├─ 127.0.0.1:11434 → Ollama (qwen3:14b; host-network mode)
└─ 127.0.0.1:5431 → postgis (database `infoxtractor`; host-network mode)
```
## One-time server setup

View file

@ -33,13 +33,16 @@ class AppConfig(BaseSettings):
)
# --- 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 = (
"postgresql+asyncpg://infoxtractor:<password>"
"@host.docker.internal:5431/infoxtractor"
"@127.0.0.1:5431/infoxtractor"
)
# --- LLM backend ---
ollama_url: str = "http://host.docker.internal:11434"
ollama_url: str = "http://127.0.0.1:11434"
default_model: str = "qwen3:14b"
# --- OCR ---

View file

@ -36,7 +36,7 @@ class OllamaClient:
Parameters
----------
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.
per_call_timeout_s:
Hard per-call timeout for ``/api/chat``. Spec default: 1500 s.

View file

@ -51,9 +51,9 @@ def test_defaults_match_spec(monkeypatch: pytest.MonkeyPatch) -> None:
assert cfg.postgres_url == (
"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.ocr_engine == "surya"
assert cfg.tmp_dir == "/tmp/ix"