-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
173 lines (169 loc) · 7.93 KB
/
Copy pathdocker-compose.yml
File metadata and controls
173 lines (169 loc) · 7.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
services:
agora:
# Default-Variante: Dev-Stage aus dem Multi-Stage-Dockerfile (Vite +
# Flask, Hot-Reload). Für Prod-like-Setups gibt es das explizite
# Override `docker-compose.prod.yml`, das `target: prod` setzt und
# gunicorn als WSGI startet. Wer ein vorgebackenes Image (Docker Hub
# / GHCR) ziehen will, ersetzt den `build`-Block durch
# `image: alexle135/agora:latest`.
build:
context: .
target: dev
container_name: agora
env_file:
- .env
# Loopback-Bind: Frontend (Vite) und Backend (Flask) sind im Dev-
# Default nur lokal erreichbar. Tailscale/LAN-Setups können über
# ENV-Variable `AGORA_BIND_HOST=0.0.0.0` explizit auf 0.0.0.0 umschalten.
# Der Default bleibt 127.0.0.1 (sicher-by-default).
ports:
- "${AGORA_BIND_HOST:-127.0.0.1}:${AGORA_FRONTEND_PORT:-5173}:5173"
- "${AGORA_BIND_HOST:-127.0.0.1}:${AGORA_BACKEND_PORT:-5001}:5001"
restart: unless-stopped
read_only: false
dns:
- ${AGORA_DNS_PRIMARY:-8.8.8.8}
- ${AGORA_DNS_SECONDARY:-8.8.4.4}
tmpfs:
- /tmp:size=128M,mode=1777
- /app/backend/logs:size=64M,mode=0700,uid=1000,gid=1000
- /home/agora/.cache:size=256M,mode=0700,uid=1000,gid=1000
- /home/agora/.npm:size=64M,mode=0700,uid=1000,gid=1000
- /app/frontend/node_modules/.vite:size=256M,mode=0755,uid=1000,gid=1000
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
volumes:
- ./backend/uploads:/app/backend/uploads
# Persist UI-saved settings (LLM provider, keys, model) across container restarts.
- ./backend/instance:/app/backend/instance
# Persist Multi-Provider-Hub-Daten (Issue #450 P1.3): Fernet-verschlüsselte
# Provider-Keys (llm_provider_secrets.json) und Workspace-Routing-Defaults
# (workspace_llm_routing.json). Beide Dateien werden vom Backend mit 0600
# geschrieben; das Host-Verzeichnis muss durch den Container-User
# (uid=1000, gid=1000) schreibbar sein.
- ./backend/data:/app/backend/data
# Persist HuggingFace model cache on the external disk so OASIS-pulled
# models (z. B. Twitter/twhin-bert-base, ~1.1 GB) das 256 MB tmpfs nicht
# sprengen und beim Container-Restart nicht neu gezogen werden.
- ./backend/.cache/huggingface:/home/agora/.cache/huggingface
extra_hosts:
- "host.docker.internal:host-gateway"
# Optional: GPU acceleration via NVIDIA Container Toolkit
# Uncomment the following section if nvidia-container-toolkit is installed
# and you want Ollama to use GPU acceleration (CUDA).
# Without this, the container runs in CPU-only mode.
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]
depends_on:
neo4j:
condition: service_healthy
redis:
condition: service_healthy
environment:
# Issue #9 Phase B — event bus transport for Flask↔OASIS IPC.
# Overrides any REDIS_URL in .env so the bus stays pointed at the
# compose-private service regardless of host-side defaults.
- REDIS_URL=redis://redis:6379/0
# Service discovery for compose-internal Neo4j (always wins over .env —
# localhost from .env would not resolve to the compose service).
- NEO4J_URI=bolt://neo4j:7687
# LLM-/Embedding-Endpoints: Compose-Substitution mit Ollama-Default.
# `.env`-Werte gewinnen (z. B. fuer OpenAI-Cloud-Embeddings via
# EMBEDDING_BASE_URL=https://api.openai.com/v1).
#
# ACHTUNG localhost-Falle: Falls in der `.env` `localhost` steht
# (Standard fuer host-side `npm run dev`), wuerde der Wert hier in
# den Container leaken — im Container ist `localhost` der Container
# selbst, nicht der Mac/Linux-Host. Fuer host-Ollama-Setups die
# Variablen in der `.env` auskommentieren oder leer lassen, damit
# der Default (`host.docker.internal`) greift. Cloud-Provider (OpenAI,
# Together, vLLM) sind unproblematisch, weil sie absolute URLs nutzen.
- LLM_BASE_URL=${LLM_BASE_URL:-http://host.docker.internal:11434/v1}
- EMBEDDING_BASE_URL=${EMBEDDING_BASE_URL:-http://host.docker.internal:11434}
# Gemini-API-Key für OASIS-Subprozess (CAMEL ModelPlatformType.GEMINI).
# Der Subprozess liest GEMINI_API_KEY aus env, nicht aus dem Backend-
# Secret-Store — ohne diese Var crashed der Subprozess mit
# ValueError("Missing or empty required API keys: GEMINI_API_KEY").
- GEMINI_API_KEY=${GEMINI_API_KEY:-}
# HF-Token für authentifizierte huggingface_hub-Downloads (z. B.
# Twitter/twhin-bert-base im OASIS-Subprozess). Ohne Token laufen die
# Downloads unauthenticated und werden rate-limited → erster Sim-Round
# blockiert minutenlang beim Cold-Cache-Download. Wert liegt in .env.
- HF_TOKEN=${HF_TOKEN:-}
# Read-only rootfs: don't try to write __pycache__ next to source.
- PYTHONDONTWRITEBYTECODE=1
# .venv wurde beim Image-Build via `uv sync --frozen` vollständig
# installiert. UV_NO_SYNC=1 verhindert, dass `uv run` beim Start
# noch PyPI kontaktiert (hatchling build-system.requires), was im
# Container ohne Internet-Zugang fehlschlagen würde.
- UV_NO_SYNC=1
# Docker Desktop v4.31.0+ aktiviert IPv6-DNS sobald Ports gebunden werden.
# urllib3 versucht IPv6 (ENETUNREACH) ohne IPv4-Fallback (kein Happy Eyeballs).
# Workaround: urllib3 auf IPv4-only setzen. Quelle: docker/for-mac#7332
- DOCKER_IPV4_ONLY=1
# Container-Zeitzone: alle datetime.now()-Naiv-Calls und LogDrawer-
# Date-Schwelle (backend/app/utils/logger.py) laufen auf Europe/Berlin.
# sim_time (Layer-0) bleibt unabhängig — ist tz-aware (UTC + Offset).
- TZ=Europe/Berlin
# LLM-Default für Sim-Runner. 16384 verhindert silent OOM/Truncation
# bei Multi-Agent-Workloads mit großem num_ctx (CAMEL-Issue). Override
# via .env oder LLM_MAX_OUTPUT_TOKENS=… docker compose up.
- LLM_MAX_OUTPUT_TOKENS=${LLM_MAX_OUTPUT_TOKENS:-16384}
redis:
image: redis:7-alpine
container_name: agora-redis
restart: unless-stopped
volumes:
- redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
neo4j:
image: ${NEO4J_IMAGE:-neo4j:5.26-community}
container_name: agora-neo4j
# Loopback-Bind: Browser/Bolt nur lokal erreichbar. Container-zu-
# Container-Verbindungen laufen weiter über das Compose-Netzwerk
# und brauchen die Host-Ports nicht. Im Prod-Override
# (`docker-compose.prod.yml`) werden die Ports per `!reset []`
# komplett rausgenommen.
ports:
- "127.0.0.1:7474:7474" # Neo4j Browser
- "127.0.0.1:7687:7687" # Bolt protocol
environment:
# :?-Syntax: Compose bricht ab, wenn die Variable fehlt oder leer ist.
# Kein Default-Passwort mehr — muss bewusst in .env gesetzt werden.
- NEO4J_AUTH=${NEO4J_USER:-neo4j}/${NEO4J_PASSWORD:?NEO4J_PASSWORD muss in .env gesetzt sein}
- NEO4J_PLUGINS=["apoc"]
- NEO4J_server_memory_heap_initial__size=${NEO4J_HEAP_INITIAL:-512m}
- NEO4J_server_memory_heap_max__size=${NEO4J_HEAP_MAX:-2g}
- NEO4J_server_memory_pagecache_size=${NEO4J_PAGECACHE_SIZE:-4g}
volumes:
- neo4j_data:/data
- neo4j_logs:/logs
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:7474 || exit 1"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
volumes:
neo4j_data:
neo4j_logs:
redis_data:
# Docker Desktop v4.31.0+ aktiviert IPv6 im Container-Netzwerk sobald Ports
# gebunden werden. host.docker.internal bekommt AAAA-Records, Python/urllib3
# versucht IPv6 zuerst (RFC 3484) ohne Happy-Eyeballs-Fallback → ENETUNREACH.
# Explizit deaktivieren fixiert den Fehler. Quelle: docker/for-mac#7332
networks:
default:
enable_ipv6: false