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. # 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 -----------------------------------------------------------------

View file

@ -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"

View file

@ -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

View file

@ -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 ---

View file

@ -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.

View file

@ -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"