165 lines
5.9 KiB
YAML
165 lines
5.9 KiB
YAML
# The single compose file for dev and prod.
|
|
#
|
|
# Dev: VS Code attaches to `api` (see .devcontainer/devcontainer.json) and
|
|
# starts `runServices` (everything but watchtower). Dev specifics
|
|
# (autoreload, editor, SSH keys, docker CLI) come from devcontainer.json.
|
|
# Prod: `docker compose up -d --build` (own .env with secrets +
|
|
# FRONTEND_MODE=preview). Code updates via `git pull` + restart; image
|
|
# rebuilds only for dependency changes.
|
|
services:
|
|
api:
|
|
build:
|
|
context: ./backend
|
|
dockerfile: Dockerfile
|
|
env_file:
|
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
|
# containers must still create so `config`/`build` work everywhere.
|
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
|
- path: .env
|
|
required: false
|
|
volumes:
|
|
# No venv volume by design: the venv lives at /opt/venv (image-local,
|
|
# see backend/Dockerfile). A named volume here used to shadow the image
|
|
# content with an empty dir on first start (split-brain with the host
|
|
# checkout, plus root-owned interpreters).
|
|
- .:/srv/kirche-einfach
|
|
ports:
|
|
- "8000:8000" # FastAPI
|
|
depends_on:
|
|
lfx:
|
|
condition: service_healthy
|
|
langflow:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD-SHELL",
|
|
"python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8000/health', timeout=5)\"",
|
|
]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 30s
|
|
|
|
frontend:
|
|
build:
|
|
context: ./frontend
|
|
dockerfile: Dockerfile
|
|
env_file:
|
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
|
# containers must still create so `config`/`build` work everywhere.
|
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
|
- path: .env
|
|
required: false
|
|
environment:
|
|
# Dev default (HMR); prod .env sets `preview` (build + serve bundle).
|
|
FRONTEND_MODE: ${FRONTEND_MODE:-dev}
|
|
volumes:
|
|
# No node_modules volume by design: deps live in the bind-mount and the
|
|
# entrypoint runs `npm ci` on first start (a volume used to shadow the
|
|
# image install with an empty dir and diverge from the host checkout).
|
|
- .:/srv/kirche-einfach
|
|
ports:
|
|
- "3000:3000" # Vite
|
|
depends_on:
|
|
api:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
|
|
langflow:
|
|
# Pinned (never :latest): Langflow and LFX are versioned together, their
|
|
# major.minor must match. Bump via LANGFLOW_VERSION in .env (see
|
|
# .env.example) together with Dockerfile.lfx + backend `lfx~=` pin.
|
|
image: langflowai/langflow:${LANGFLOW_VERSION:-1.12.0}
|
|
env_file:
|
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
|
# containers must still create so `config`/`build` work everywhere.
|
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
|
- path: .env
|
|
required: false
|
|
environment:
|
|
# Static values only; secrets/URLs come from .env via env_file.
|
|
LANGFLOW_CONFIG_DIR: /app/langflow
|
|
LANGFLOW_HOST: 0.0.0.0
|
|
PORT: "7860"
|
|
LANGFLOW_AUTO_LOGIN: "false"
|
|
LANGFLOW_API_KEY_SOURCE: env
|
|
# SQLite file inside the langflow-data volume (absolute path required
|
|
# by Langflow); overrides any postgres URL that may linger in .env.
|
|
LANGFLOW_DATABASE_URL: sqlite:////app/langflow/langflow.db
|
|
# Custom form-input components (backend/components, category folders).
|
|
LANGFLOW_COMPONENTS_PATH: /app/components
|
|
# Seed the authoring UI with the canonical flows (read-only: the files
|
|
# stay the source of truth, the API watcher is the only sync path).
|
|
LANGFLOW_LOAD_FLOWS_PATH: /app/flows
|
|
volumes:
|
|
- langflow-data:/app/langflow
|
|
- ./backend/components:/app/components:ro
|
|
- ./backend/flows:/app/flows:ro
|
|
ports:
|
|
- "7860:7860"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD-SHELL",
|
|
"python -c \"import urllib.request; urllib.request.urlopen('http://localhost:7860/health', timeout=5)\"",
|
|
]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 20
|
|
start_period: 60s
|
|
|
|
lfx:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile.lfx
|
|
env_file:
|
|
# Optional: fresh clones and CI checkouts have no `.env` (gitignored);
|
|
# containers must still create so `config`/`build` work everywhere.
|
|
# Runtime secrets come from `.env` when present (see setup.sh).
|
|
- path: .env
|
|
required: false
|
|
environment:
|
|
# lfx resolves its serve key via get_api_key(), which prefers
|
|
# LANGFLOW_API_KEY over LFX_API_KEY. Our backend talks to LFX with
|
|
# LFX_API_KEY, so blank the former here (empty counts as unset) —
|
|
# otherwise every flow deploy 401s and /flows stays empty.
|
|
LANGFLOW_API_KEY: ""
|
|
volumes:
|
|
- lfx-data:/flows
|
|
ports:
|
|
- "6004:6004"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
[
|
|
"CMD-SHELL",
|
|
"python -c \"import urllib.request; urllib.request.urlopen('http://localhost:6004/health', timeout=5)\"",
|
|
]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 12
|
|
start_period: 30s
|
|
|
|
# Nightly auto-updates of :latest images (prod). Never started in dev
|
|
# (not in devcontainer.json runServices; also needs a docker socket).
|
|
# langflow/lfx carry no watchtower label on purpose: both are version-pinned
|
|
# (major.minor must match) and update only via deliberate version bumps.
|
|
watchtower:
|
|
image: nickfedor/watchtower:latest
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
environment:
|
|
WATCHTOWER_LABEL_ENABLE: "true"
|
|
WATCHTOWER_SCHEDULE: "0 0 4 * * *"
|
|
WATCHTOWER_CLEANUP: "true"
|
|
WATCHTOWER_ROLLING_RESTART: "true"
|
|
labels:
|
|
com.centurylinklabs.watchtower.enable: "true"
|
|
restart: unless-stopped
|
|
|
|
volumes:
|
|
langflow-data:
|
|
lfx-data:
|