Repository navigation
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
170 lines (158 loc) · 4.53 KB
/
Copy pathdocker-compose.yml
File metadata and controls
170 lines (158 loc) · 4.53 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
# Default Compose file = prod: only nginx is published (:8080).
# uv run poe up-prod · docker compose up
# Dev (direct host ports, no nginx):
# uv run poe up · docker compose -f docker-compose.yml -f docker-compose.dev.yml up
#
# Prod (host): http://localhost:8080/ UI
# http://localhost:8080/api/ FastAPI
# http://localhost:8080/docs/ Sphinx
# Dev (host): http://localhost:14321 UI
# http://localhost:14322 API
# http://localhost:14323 Docs
# Internal listen ports (Compose network ``soju``): web:14321 · backend:14322 · docs:14323
# Host Ollama: backend uses host.docker.internal:11434 (see docker/soju/backend*.yaml).
#
# Ollama model cache on the host (default: ~/.ollama). Override with OLLAMA_DATA_DIR.
x-ollama-volume: &ollama-volume "${OLLAMA_DATA_DIR:-${HOME}/.ollama}:/root/.ollama"
# Chat / embed models for ollama-pull (backend YAML is source of truth for the API).
x-soju-ai-chat-model: &soju-ai-chat-model gemma4:e4b
x-soju-ai-embed-model: &soju-ai-embed-model nomic-embed-text
# Speech: local = Soju backend TTS; browser = Web Speech API.
x-soju-tts-engine: &soju-tts-engine local
# Same-origin API via nginx (browser never talks to internal ports).
x-soju-api-base-url: &soju-api-base-url /api
# Minimal browser-visible env (models / tutor prompt come from GET /v1/soju/config/client).
x-soju-web-environment: &soju-web-environment
DATA_DIR: /data
PUBLIC_TTS_ENGINE: *soju-tts-engine
PUBLIC_AI_ENABLED: "true"
PUBLIC_AI_BASE_URL: *soju-api-base-url
name: soju
networks:
soju:
driver: bridge
services:
web:
build:
context: .
dockerfile: docker/Dockerfile.web
target: dev
# Compose command wins over image CMD so port changes apply without a rebuild.
command: ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "14321"]
expose:
- "14321"
volumes:
- ./data:/data:rw
- ./apps/web:/app:rw
- web_node_modules:/app/node_modules
environment:
<<: *soju-web-environment
# HMR websocket through published nginx :8080 (overridden in docker-compose.dev.yml).
VITE_HMR_CLIENT_PORT: "8080"
extra_hosts:
- host.docker.internal:host-gateway
networks:
- soju
backend:
build:
context: .
dockerfile: docker/Dockerfile.backend
command:
[
"soju",
"backend",
"--config",
"/config/soju/backend.yaml",
"--host",
"0.0.0.0",
"--port",
"14322",
]
volumes:
- ./docker/soju:/config/soju:ro
- ./data:/data:ro
environment:
DATA_DIR: /data
extra_hosts:
- host.docker.internal:host-gateway
expose:
- "14322"
networks:
- soju
restart: unless-stopped
docs:
build:
context: .
dockerfile: docker/Dockerfile.docs
target: prod
expose:
- "14323"
networks:
- soju
restart: unless-stopped
nginx:
build:
context: .
dockerfile: docker/Dockerfile.nginx
ports:
- "8080:80"
environment:
SOJU_WEB_PORT: "8080"
volumes:
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- web
- backend
- docs
networks:
- soju
restart: unless-stopped
ollama:
image: ollama/ollama
profiles: ["ollama"]
environment:
OLLAMA_ORIGINS: "*"
ports:
- "11434:11434"
volumes:
- *ollama-volume
networks:
- soju
# Ensures the chat + embedding models exist in the shared Ollama cache (pull is incremental).
ollama-pull:
image: ollama/ollama
profiles: ["ollama"]
depends_on:
ollama:
condition: service_started
environment:
OLLAMA_HOST: http://ollama:11434
OLLAMA_MODEL: *soju-ai-chat-model
OLLAMA_EMBED_MODEL: *soju-ai-embed-model
volumes:
- *ollama-volume
networks:
- soju
entrypoint: ["/bin/sh", "-c"]
command:
- |
pull_with_retry() {
model="$$1"
for i in 1 2 3 4 5 6 7 8 9 10; do
if ollama show "$$model" >/dev/null 2>&1; then
echo "Model $$model already present"
return 0
fi
ollama pull "$$model" && return 0
sleep 3
done
echo "Failed to pull $$model" >&2
return 1
}
status=0
pull_with_retry "$$OLLAMA_MODEL" || status=1
pull_with_retry "$$OLLAMA_EMBED_MODEL" || status=1
exit "$$status"
restart: "no"
volumes:
web_node_modules: