-
Notifications
You must be signed in to change notification settings - Fork 124
Expand file tree
/
Copy pathdocker-compose.yml
More file actions
182 lines (174 loc) · 6.84 KB
/
docker-compose.yml
File metadata and controls
182 lines (174 loc) · 6.84 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
174
175
176
177
178
179
180
181
182
# Asterisk AI Voice Agent - Main Services
#
# DEFAULT NETWORK MODE: Host (for telephony/low-latency)
# - Direct access to host network (127.0.0.1 reaches Asterisk)
# - No port mapping needed
# - Best for telephony integrations
#
# PERMISSION ALIGNMENT:
# If your Asterisk uses a different GID than 995 (FreePBX default):
# export ASTERISK_GID=$(id -g asterisk)
# docker compose build ai_engine
# docker compose up -d
#
# Prometheus-format metrics are available at `http://<host>:15000/metrics`.
# Per-call debugging is via Admin UI → Call History.
name: asterisk-ai-voice-agent
services:
ai_engine:
image: asterisk-ai-voice-agent-ai-engine:latest
pull_policy: build
build:
context: .
dockerfile: Dockerfile
network: host
args:
ASTERISK_GID: ${ASTERISK_GID:-995}
container_name: ai_engine
# Container runs as appuser (member of asterisk group via Dockerfile)
# Files inherit group ownership from setgid directory (set up by preflight.sh)
user: "appuser"
network_mode: host
volumes:
- ./src:/app/src
- ./main.py:/app/main.py
- ./config:/app/config
- ./scripts:/app/scripts
- ./models:/app/models
- ./asterisk_media:/mnt/asterisk_media
- ./data:/app/data
- ./secrets:/app/project/secrets # Vertex AI service account credentials
env_file:
- .env
environment:
- PYTHONPATH=/app
- PYTHONUNBUFFERED=1
# Note: TZ is loaded from .env via env_file directive above
# Do NOT add TZ here with ${TZ:-default} - it prevents UI env changes from taking effect
# Enable health endpoint access from other containers (admin-ui needs /sessions/stats)
- HEALTH_BIND_HOST=0.0.0.0
# Note: ASTERISK_HOST is loaded from .env via env_file directive above
# Do NOT add ASTERISK_HOST here - it prevents UI env changes from taking effect
tty: true
stdin_open: true
restart: unless-stopped
local_ai_server:
image: asterisk-ai-voice-agent-local-ai-server:latest
pull_policy: build
build:
context: ./local_ai_server
dockerfile: Dockerfile
network: host
args:
- INCLUDE_VOSK=${INCLUDE_VOSK:-true}
- INCLUDE_SHERPA=${INCLUDE_SHERPA:-true}
- INCLUDE_FASTER_WHISPER=${INCLUDE_FASTER_WHISPER:-false}
- INCLUDE_WHISPER_CPP=${INCLUDE_WHISPER_CPP:-false}
- INCLUDE_PIPER=${INCLUDE_PIPER:-true}
- INCLUDE_KOKORO=${INCLUDE_KOKORO:-true}
- INCLUDE_MELOTTS=${INCLUDE_MELOTTS:-false}
- INCLUDE_LLAMA=${INCLUDE_LLAMA:-true}
- INCLUDE_KROKO_EMBEDDED=${INCLUDE_KROKO_EMBEDDED:-false}
container_name: local_ai_server
network_mode: host
env_file:
- .env
volumes:
- ./models:/app/models
- ./data:/app/data
environment:
- PYTHONUNBUFFERED=1
# Note: All LOCAL_* variables are loaded from .env via env_file directive above
# Do NOT add them here with ${VAR:-default} - it prevents UI env changes from taking effect
# The .env file should contain defaults, or use install.sh to set them
tty: true
stdin_open: true
restart: unless-stopped
# Uncomment below for NVIDIA GPU support:
# deploy:
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: 1
# capabilities: [gpu]
healthcheck:
test:
- CMD-SHELL
- |
python - <<'PY'
import asyncio
import json
import os
import websockets
async def main():
port = os.getenv("LOCAL_WS_PORT", "8765")
token = (os.getenv("LOCAL_WS_AUTH_TOKEN", "") or "").strip()
uri = f"ws://127.0.0.1:{port}"
ws = await websockets.connect(
uri,
ping_interval=None,
ping_timeout=None,
close_timeout=2,
max_size=None,
)
try:
if token:
await ws.send(json.dumps({"type": "auth", "auth_token": token}))
raw = await ws.recv()
if isinstance(raw, (bytes, bytearray)):
raise RuntimeError("Unexpected binary auth response")
data = json.loads(raw)
if data.get("type") != "auth_response" or data.get("status") != "ok":
raise RuntimeError(f"Auth rejected: {data}")
await ws.send(json.dumps({"type": "status"}))
raw = await ws.recv()
if isinstance(raw, (bytes, bytearray)):
raise RuntimeError("Unexpected binary status response")
data = json.loads(raw)
if data.get("type") != "status_response" or data.get("status") != "ok":
raise RuntimeError(f"Unexpected status response: {data}")
finally:
await ws.close()
asyncio.run(main())
PY
interval: 60s
timeout: 5s
# 30 retries × 60s interval = 30 min window after start_period.
# Large models may take 5-10 min to load; increase if needed.
retries: 30
start_period: 120s
admin_ui:
image: asterisk-ai-voice-agent-admin-ui:latest
pull_policy: build
build:
context: ./admin_ui
dockerfile: Dockerfile
network: host
container_name: admin_ui
network_mode: host
# Grant docker socket access to non-root user (appuser runs as UID 1000)
# Docker socket is typically owned by group 'docker' (GID varies by distro/host).
# Override DOCKER_GID in .env if your system uses a different GID.
# Note: admin_ui also auto-detects the socket GID at startup (defense-in-depth).
group_add:
- ${DOCKER_GID:-999}
volumes:
- ./:/app/project
- ${DOCKER_SOCK:-/var/run/docker.sock}:/var/run/docker.sock
# The admin-ui image installs Docker CLI + Compose plugin internally.
# Optional fallback (host binaries): use `docker compose -f docker-compose.yml -f docker-compose.admin-ui-host-binaries.yml up -d admin_ui`
- /etc/os-release:/host/etc/os-release:ro
- ./asterisk_media:/mnt/asterisk_media
- ./data:/app/data
- ${ASTERISK_RECORDING_PATH:-/var/spool/asterisk/monitor}:/mnt/asterisk_recordings:ro
env_file:
- .env
environment:
- PROJECT_ROOT=/app/project
# HOST_PROJECT_ROOT is the actual host filesystem path for docker compose operations.
# This is critical because Docker (via socket) resolves volume mounts on the HOST, not inside this container.
- HOST_PROJECT_ROOT=${HOST_PROJECT_ROOT:-/root/Asterisk-AI-Voice-Agent}
# Note: UVICORN_HOST, UVICORN_PORT, JWT_SECRET, TZ are loaded from .env via env_file
# Do NOT add them here with ${VAR:-default} - it prevents UI env changes from taking effect
restart: unless-stopped