Skip to content

Commit c3fd89b

Browse files
0xrushiclaude
andcommitted
Implement prebuilt image support and enhance Docker Compose configurations
- Add image: fields with CHRONICLE_REGISTRY/CHRONICLE_TAG env vars to all custom services in docker-compose files (backends/advanced, asr-services, speaker-recognition, havpe-relay) - Create scripts/push-images.sh to tag and push local images to DockerHub - Create scripts/pull-images.sh to pull and retag images for local use - Add --use-prebuilt TAG flag to services.py start command; sets CHRONICLE_REGISTRY and CHRONICLE_TAG env vars and disables build - Add unit tests for image versioning changes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 49986e4 commit c3fd89b

8 files changed

Lines changed: 735 additions & 10 deletions

File tree

backends/advanced/docker-compose.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ services:
2626
socat TCP-LISTEN:18123,fork,reuseaddr TCP:100.99.62.5:8123"
2727
2828
chronicle-backend:
29+
image: ${CHRONICLE_REGISTRY:-}chronicle-backend:${CHRONICLE_TAG:-latest}
2930
build:
3031
context: .
3132
dockerfile: Dockerfile
@@ -83,6 +84,7 @@ services:
8384
# - 1+ Stream workers (conditional based on config.yml - Deepgram/Parakeet)
8485
# Uses Python orchestrator for process management, health monitoring, and self-healing
8586
workers:
87+
image: ${CHRONICLE_REGISTRY:-}chronicle-backend:${CHRONICLE_TAG:-latest}
8688
build:
8789
context: .
8890
dockerfile: Dockerfile
@@ -131,6 +133,7 @@ services:
131133
# - Weekly: Fine-tune error detection models using user feedback
132134
# Set DEV_MODE=true in .env for 1-minute intervals (testing)
133135
annotation-cron:
136+
image: ${CHRONICLE_REGISTRY:-}chronicle-backend:${CHRONICLE_TAG:-latest}
134137
build:
135138
context: .
136139
dockerfile: Dockerfile
@@ -153,6 +156,7 @@ services:
153156
- annotation # Optional profile - enable with: docker compose --profile annotation up
154157

155158
webui:
159+
image: ${CHRONICLE_REGISTRY:-}chronicle-webui:${CHRONICLE_TAG:-latest}
156160
build:
157161
context: ./webui
158162
dockerfile: Dockerfile

extras/asr-services/docker-compose.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ services:
2424
dockerfile: providers/nemo/Dockerfile
2525
args:
2626
PYTORCH_CUDA_VERSION: ${PYTORCH_CUDA_VERSION:-cu126}
27-
image: chronicle-asr-nemo:latest
27+
image: ${CHRONICLE_REGISTRY:-}chronicle-asr-nemo:${CHRONICLE_TAG:-latest}
2828
ports:
2929
- "${ASR_PORT:-8767}:8765"
3030
volumes:
@@ -58,7 +58,7 @@ services:
5858
build:
5959
context: .
6060
dockerfile: providers/faster_whisper/Dockerfile
61-
image: chronicle-asr-faster-whisper:latest
61+
image: ${CHRONICLE_REGISTRY:-}chronicle-asr-faster-whisper:${CHRONICLE_TAG:-latest}
6262
ports:
6363
- "${ASR_PORT:-8767}:8765"
6464
volumes:
@@ -92,7 +92,7 @@ services:
9292
dockerfile: providers/vibevoice/Dockerfile
9393
args:
9494
PYTORCH_CUDA_VERSION: ${PYTORCH_CUDA_VERSION:-cu126}
95-
image: chronicle-asr-vibevoice:latest
95+
image: ${CHRONICLE_REGISTRY:-}chronicle-asr-vibevoice:${CHRONICLE_TAG:-latest}
9696
ports:
9797
- "${ASR_PORT:-8767}:8765"
9898
volumes:
@@ -133,7 +133,7 @@ services:
133133
build:
134134
context: .
135135
dockerfile: providers/transformers/Dockerfile
136-
image: chronicle-asr-transformers:latest
136+
image: ${CHRONICLE_REGISTRY:-}chronicle-asr-transformers:${CHRONICLE_TAG:-latest}
137137
ports:
138138
- "${ASR_PORT:-8767}:8765"
139139
volumes:
@@ -193,7 +193,7 @@ services:
193193
build:
194194
context: .
195195
dockerfile: providers/qwen3_asr/Dockerfile.full
196-
image: chronicle-asr-qwen3-wrapper:latest
196+
image: ${CHRONICLE_REGISTRY:-}chronicle-asr-qwen3-wrapper:${CHRONICLE_TAG:-latest}
197197
ports:
198198
- "${ASR_PORT:-8767}:8765"
199199
volumes:
@@ -220,7 +220,7 @@ services:
220220
build:
221221
context: .
222222
dockerfile: providers/qwen3_asr/Dockerfile
223-
image: chronicle-asr-qwen3-bridge:latest
223+
image: ${CHRONICLE_REGISTRY:-}chronicle-asr-qwen3-bridge:${CHRONICLE_TAG:-latest}
224224
ports:
225225
- "${ASR_STREAM_PORT:-8769}:8766"
226226
environment:

extras/havpe-relay/docker-compose.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
services:
22
havpe-relay:
3+
image: ${CHRONICLE_REGISTRY:-}chronicle-havpe-relay:${CHRONICLE_TAG:-latest}
34
build:
45
context: .
56
dockerfile: Dockerfile
@@ -21,8 +22,8 @@ services:
2122
timeout: 10s
2223
retries: 3
2324
start_period: 10s
24-
command: ["uv", "run", "python3", "main.py"]
25+
command: ["uv", "run", "python3", "main.py"]
2526
extra_hosts:
2627
- "host.docker.internal:host-gateway"
2728
volumes:
28-
- ./audio_chunks:/app/audio_chunks
29+
- ./audio_chunks:/app/audio_chunks

extras/speaker-recognition/docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ services:
99
dockerfile: Dockerfile
1010
args:
1111
PYTORCH_CUDA_VERSION: ${PYTORCH_CUDA_VERSION:-cpu}
12-
image: speaker-recognition:latest
12+
image: ${CHRONICLE_REGISTRY:-}chronicle-speaker:${CHRONICLE_TAG:-latest}
1313
env_file:
1414
- .env
1515
ports:
@@ -63,6 +63,7 @@ services:
6363
# React Web UI
6464
web-ui:
6565
platform: linux/amd64
66+
image: ${CHRONICLE_REGISTRY:-}chronicle-speaker-webui:${CHRONICLE_TAG:-latest}
6667
build:
6768
context: webui
6869
dockerfile: Dockerfile

scripts/pull-images.sh

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env bash
2+
# pull-images.sh — Pull Chronicle images from DockerHub and retag them locally
3+
#
4+
# Usage:
5+
# DOCKERHUB_USERNAME=myuser ./scripts/pull-images.sh v1.0.0
6+
#
7+
# After pulling, start with the prebuilt images:
8+
# DOCKERHUB_USERNAME=myuser ./start.sh --use-prebuilt v1.0.0
9+
10+
set -euo pipefail
11+
12+
# ── Colour helpers ─────────────────────────────────────────────────────────────
13+
RED='\033[0;31m'
14+
GREEN='\033[0;32m'
15+
YELLOW='\033[1;33m'
16+
CYAN='\033[0;36m'
17+
BOLD='\033[1m'
18+
RESET='\033[0m'
19+
20+
info() { echo -e "${CYAN}ℹ️ $*${RESET}"; }
21+
success() { echo -e "${GREEN}$*${RESET}"; }
22+
warn() { echo -e "${YELLOW}⚠️ $*${RESET}"; }
23+
error() { echo -e "${RED}$*${RESET}" >&2; }
24+
25+
# ── Validate inputs ────────────────────────────────────────────────────────────
26+
if [[ -z "${DOCKERHUB_USERNAME:-}" ]]; then
27+
error "DOCKERHUB_USERNAME env var is required."
28+
echo " Example: DOCKERHUB_USERNAME=myuser ./scripts/pull-images.sh v1.0.0" >&2
29+
exit 1
30+
fi
31+
32+
TAG="${1:-}"
33+
if [[ -z "$TAG" ]]; then
34+
error "TAG argument is required."
35+
echo " Example: DOCKERHUB_USERNAME=myuser ./scripts/pull-images.sh v1.0.0" >&2
36+
exit 1
37+
fi
38+
39+
REGISTRY="${DOCKERHUB_USERNAME}/"
40+
41+
# ── Image inventory ────────────────────────────────────────────────────────────
42+
# Format: "local-image-name:registry-image-name"
43+
# After pulling, each remote image is retagged to "<local-image-name>:<TAG>"
44+
# so that docker-compose can find it when CHRONICLE_TAG=<TAG> is set.
45+
IMAGES=(
46+
"chronicle-backend:chronicle-backend"
47+
"chronicle-webui:chronicle-webui"
48+
"chronicle-speaker:chronicle-speaker"
49+
"chronicle-speaker-strixhalo:chronicle-speaker-strixhalo"
50+
"chronicle-speaker-webui:chronicle-speaker-webui"
51+
"chronicle-asr-nemo:chronicle-asr-nemo"
52+
"chronicle-asr-nemo-strixhalo:chronicle-asr-nemo-strixhalo"
53+
"chronicle-asr-faster-whisper:chronicle-asr-faster-whisper"
54+
"chronicle-asr-vibevoice:chronicle-asr-vibevoice"
55+
"chronicle-asr-vibevoice-strixhalo:chronicle-asr-vibevoice-strixhalo"
56+
"chronicle-asr-transformers:chronicle-asr-transformers"
57+
"chronicle-asr-qwen3-wrapper:chronicle-asr-qwen3-wrapper"
58+
"chronicle-asr-qwen3-bridge:chronicle-asr-qwen3-bridge"
59+
"chronicle-havpe-relay:chronicle-havpe-relay"
60+
)
61+
62+
echo ""
63+
echo -e "${BOLD}Chronicle Image Pull${RESET}"
64+
echo -e " Registry : ${REGISTRY}"
65+
echo -e " Tag : ${TAG}"
66+
echo ""
67+
68+
# ── Pull loop ─────────────────────────────────────────────────────────────────
69+
PULLED=()
70+
FAILED=()
71+
72+
for entry in "${IMAGES[@]}"; do
73+
LOCAL_BASE="${entry%%:*}"
74+
REMOTE_BASE="${REGISTRY}${entry##*:}"
75+
REMOTE_TAG="${REMOTE_BASE}:${TAG}"
76+
LOCAL_TAG="${LOCAL_BASE}:${TAG}"
77+
78+
echo -e "${CYAN}── ${entry##*:}${RESET}"
79+
info " Pulling ← ${REMOTE_TAG}"
80+
81+
if docker pull "${REMOTE_TAG}"; then
82+
# Retag to local name so docker-compose finds it with CHRONICLE_TAG=<TAG>
83+
info " Retagging → ${LOCAL_TAG}"
84+
docker tag "${REMOTE_TAG}" "${LOCAL_TAG}"
85+
success " Ready as ${LOCAL_TAG}"
86+
PULLED+=("${entry##*:}")
87+
else
88+
warn " Not found on DockerHub — skipping (this service may not have been pushed)"
89+
FAILED+=("${entry##*:}")
90+
fi
91+
echo ""
92+
done
93+
94+
# ── Summary ───────────────────────────────────────────────────────────────────
95+
echo -e "${BOLD}── Summary ──────────────────────────────────────────────────────${RESET}"
96+
printf "%-40s %s\n" "Image" "Status"
97+
printf "%-40s %s\n" "─────────────────────────────────────" "──────"
98+
99+
for entry in "${IMAGES[@]}"; do
100+
IMAGE_NAME="${entry##*:}"
101+
STATUS=""
102+
for p in "${PULLED[@]}"; do
103+
[[ "$p" == "$IMAGE_NAME" ]] && STATUS="${GREEN}pulled${RESET}" && break
104+
done
105+
for f in "${FAILED[@]}"; do
106+
[[ "$f" == "$IMAGE_NAME" ]] && STATUS="${YELLOW}not found${RESET}" && break
107+
done
108+
[[ -z "$STATUS" ]] && STATUS="${YELLOW}not found${RESET}"
109+
printf "%-40s " "${IMAGE_NAME}"
110+
echo -e "${STATUS}"
111+
done
112+
113+
echo ""
114+
if [[ ${#PULLED[@]} -gt 0 ]]; then
115+
success "Pulled ${#PULLED[@]} image(s) tagged as ${TAG}"
116+
echo ""
117+
echo "Start services with prebuilt images:"
118+
echo -e " ${BOLD}DOCKERHUB_USERNAME=${DOCKERHUB_USERNAME} ./start.sh --use-prebuilt ${TAG}${RESET}"
119+
fi
120+
if [[ ${#FAILED[@]} -gt 0 ]]; then
121+
warn "${#FAILED[@]} image(s) not found on DockerHub (these services will fall back to local builds)"
122+
fi

0 commit comments

Comments
 (0)