Skip to content

Commit f4ba2bf

Browse files
committed
Rewrite server Docker image to pull release binaries
- replace the multi-stage server build with a single-stage image that downloads versioned release artifacts - refresh the server Docker README to cover the new workflow and build args - add a VAD Docker image and README that bundle silero_vad_server alongside echokit_server
1 parent addba37 commit f4ba2bf

File tree

4 files changed

+173
-25
lines changed

4 files changed

+173
-25
lines changed

docker/server-vad/Dockerfile

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# syntax=docker/dockerfile:1.6
2+
3+
FROM debian:bookworm-slim
4+
5+
WORKDIR /app
6+
7+
ARG ECHOKIT_VERSION=0.1.0
8+
ARG VAD_VERSION=0.1.0
9+
10+
RUN apt-get update \
11+
&& apt-get install -y --no-install-recommends \
12+
bash \
13+
ca-certificates \
14+
curl \
15+
unzip \
16+
libgomp1 \
17+
libssl3 \
18+
&& rm -rf /var/lib/apt/lists/*
19+
20+
RUN set -eux; \
21+
curl -L https://download.pytorch.org/libtorch/cu124/libtorch-cxx11-abi-shared-with-deps-2.4.0%2Bcu124.zip -o /tmp/libtorch.zip; \
22+
unzip /tmp/libtorch.zip -d /usr/local/lib; \
23+
rm /tmp/libtorch.zip; \
24+
if [ -f /usr/local/lib/libtorch/lib/libnvrtc-builtins.so ]; then \
25+
ln -sf /usr/local/lib/libtorch/lib/libnvrtc-builtins.so /usr/local/lib/libtorch/lib/libnvrtc-builtins.so.12.4; \
26+
fi
27+
28+
RUN set -eux; \
29+
ARCH_SUFFIX="x86_64-unknown-linux-gnu"; \
30+
tmpdir="$(mktemp -d)"; \
31+
archive="echokit_server-v${ECHOKIT_VERSION}-${ARCH_SUFFIX}.tar.gz"; \
32+
url="https://github.com/second-state/echokit_server/releases/download/v${ECHOKIT_VERSION}/${archive}"; \
33+
curl -fsSL -o /tmp/echokit_server.tar.gz "${url}"; \
34+
tar -xzf /tmp/echokit_server.tar.gz -C "$tmpdir"; \
35+
bin_path="$(find "$tmpdir" -type f -name 'echokit_server' -print -quit)"; \
36+
test -n "$bin_path"; \
37+
install -m 0755 "$bin_path" /usr/local/bin/echokit_server; \
38+
rm -rf "$tmpdir" /tmp/echokit_server.tar.gz
39+
40+
RUN set -eux; \
41+
ARCH_SUFFIX="x86_64-unknown-linux-gnu"; \
42+
tmpdir="$(mktemp -d)"; \
43+
archive="silero_vad_server-v${VAD_VERSION}-${ARCH_SUFFIX}.tar.gz"; \
44+
url="https://github.com/second-state/silero_vad_server/releases/download/v${VAD_VERSION}/${archive}"; \
45+
curl -fsSL -o /tmp/silero_vad_server.tar.gz "${url}"; \
46+
tar -xzf /tmp/silero_vad_server.tar.gz -C "$tmpdir"; \
47+
vad_bin="$(find "$tmpdir" -type f -name 'silero_vad_server' -print -quit)"; \
48+
test -n "$vad_bin"; \
49+
install -m 0755 "$vad_bin" /usr/local/bin/silero_vad_server; \
50+
rm -rf "$tmpdir" /tmp/silero_vad_server.tar.gz
51+
52+
RUN curl -fsSL "https://github.com/second-state/silero_vad_server/raw/refs/tags/v${VAD_VERSION}/silero_vad.jit" -o /app/silero_vad.jit
53+
54+
ENV LD_LIBRARY_PATH=/usr/local/lib/libtorch/lib:$LD_LIBRARY_PATH
55+
ENV LIBTORCH=/usr/local/lib/libtorch
56+
57+
COPY config.toml .
58+
59+
RUN cat <<'EOF' > /usr/local/bin/start_servers.sh \
60+
&& chmod +x /usr/local/bin/start_servers.sh
61+
#!/usr/bin/env bash
62+
set -euo pipefail
63+
64+
vad_pid=""
65+
server_pid=""
66+
67+
terminate() {
68+
if [[ -n "$vad_pid" ]]; then
69+
kill -TERM "$vad_pid" 2>/dev/null || true
70+
fi
71+
if [[ -n "$server_pid" ]]; then
72+
kill -TERM "$server_pid" 2>/dev/null || true
73+
fi
74+
}
75+
76+
silero_vad_server &
77+
vad_pid=$!
78+
79+
echokit_server config.toml &
80+
server_pid=$!
81+
82+
trap terminate SIGINT SIGTERM EXIT
83+
84+
wait -n "$vad_pid" "$server_pid" || true
85+
terminate
86+
wait || true
87+
EOF
88+
89+
ENV RUST_LOG=info
90+
91+
CMD ["/usr/local/bin/start_servers.sh"]

docker/server-vad/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# echokit-server + Silero VAD Docker Image
2+
3+
This directory provides a single-stage runtime image that launches both `echokit_server` and `silero_vad_server` inside the same container.
4+
5+
- **Runtime image** (`debian:bookworm-slim`): installs runtime dependencies, downloads the CUDA-enabled `libtorch` bundle, and fetches the `v0.1.0` release binaries for `echokit_server`, `silero_vad_server`, and the `silero_vad.jit` model.
6+
- **Supervisor script**: `/usr/local/bin/start_servers.sh` starts both services, relays signals, and keeps the container alive while either process is running.
7+
8+
## Run
9+
10+
Expose the application ports and mount your configuration plus a writable recordings directory:
11+
12+
```sh
13+
docker run --rm \
14+
-p 8080:8080 \
15+
-v $(pwd)/config.toml:/app/config.toml \
16+
-v $(pwd)/record:/app/record \
17+
secondstate/echokit:latest-server-vad
18+
```
19+
20+
Mount your `config.toml` directly into `/app/config.toml`. If you need to override additional assets such as `silero_vad.jit`, mount each file individually alongside the config. The servers write generated artifacts to `/app/record`, so ensure the local `record` directory exists and is writable. The container sets `RUST_LOG=info` and runs `start_servers.sh` by default, keeping both services available on ports `8080` and `8000` inside the container.
21+
22+
The VAD server listens on port `8000` internally. Choose one of the following so `echokit_server` talks to it correctly without publishing the VAD port to the host:
23+
24+
1. Update your mounted `config.toml` so `vad_url` and `vad_realtime_url` point to `http://localhost:8000` / `ws://localhost:8000`.
25+
2. Keep the default config (`9093`) and add `-e VAD_LISTEN=9093` to the `docker run` command so the VAD server binds that port inside the container.
26+
27+
## Build
28+
29+
```sh
30+
docker build -t secondstate/echokit:latest-server-vad -f docker/vad/Dockerfile .
31+
```
32+
33+
This Dockerfile always downloads the `linux-x86_64` release artifacts baked into the file. Update the URLs if you need to pin a different release.
34+
35+
## Platform support
36+
37+
Multi-platform builds are **not supported**. The image bundles CUDA-enabled `libtorch` and hard-coded `x86_64-unknown-linux-gnu` binaries for both servers, so `docker buildx` cannot produce working arm64 (or other architecture) variants.
38+
39+
## Publish
40+
41+
```sh
42+
docker login
43+
docker push secondstate/echokit:latest-server-vad
44+
```

docker/server/Dockerfile

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
# syntax=docker/dockerfile:1.6
22

3-
FROM rust:1.85-slim AS builder
4-
5-
WORKDIR /app
6-
7-
# Install build dependencies required by reqwest/rustls toolchain.
8-
RUN apt-get update \
9-
&& apt-get install -y --no-install-recommends pkg-config libssl-dev build-essential \
10-
&& rm -rf /var/lib/apt/lists/*
11-
12-
COPY . .
13-
14-
RUN cargo build --release
15-
16-
17-
FROM debian:bookworm-slim AS runtime
3+
FROM debian:bookworm-slim
184

195
RUN apt-get update \
20-
&& apt-get install -y --no-install-recommends ca-certificates libssl3 \
6+
&& apt-get install -y --no-install-recommends ca-certificates libssl3 curl \
217
&& rm -rf /var/lib/apt/lists/*
228

239
WORKDIR /app
2410

25-
COPY --from=builder /app/config.toml .
26-
COPY --from=builder /app/target/release/echokit_server /usr/local/bin/echokit_server
11+
ARG TARGETPLATFORM
12+
ARG ECHOKIT_VERSION=0.1.0
13+
14+
RUN set -eux; \
15+
case "${TARGETPLATFORM}" in \
16+
"linux/amd64") ARCH_SUFFIX="x86_64-unknown-linux-gnu" ;; \
17+
"linux/arm64") ARCH_SUFFIX="aarch64-unknown-linux-gnu" ;; \
18+
*) echo "Unsupported TARGETPLATFORM: ${TARGETPLATFORM}" >&2; exit 1 ;; \
19+
esac; \
20+
ARCHIVE="echokit_server-v${ECHOKIT_VERSION}-${ARCH_SUFFIX}.tar.gz"; \
21+
URL="https://github.com/second-state/echokit_server/releases/download/v${ECHOKIT_VERSION}/${ARCHIVE}"; \
22+
tmpdir="$(mktemp -d)"; \
23+
curl -fsSL -o /tmp/echokit_server.tar.gz "${URL}"; \
24+
tar -xzf /tmp/echokit_server.tar.gz -C "$tmpdir"; \
25+
bin_path="$(find "$tmpdir" -type f -name 'echokit_server' -print -quit)"; \
26+
test -n "$bin_path"; \
27+
install -m 0755 "$bin_path" /usr/local/bin/echokit_server; \
28+
rm -rf "$tmpdir" /tmp/echokit_server.tar.gz
29+
COPY config.toml config.toml
2730

2831
ENV RUST_LOG=info
2932

docker/server/README.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
# echokit-server Standalone Docker Image
22

3-
This directory contains a multi-stage Dockerfile for producing a lean runtime image of `echokit_server`.
3+
This directory contains a single-stage Dockerfile that produces a lean runtime image of `echokit_server` by downloading official release binaries.
44

5-
- **Builder stage** (`rust:1.85-slim`): installs the minimal Rust toolchain dependencies, copies the repository contents into `/app`, and compiles the project in release mode.
6-
- **Runtime stage** (`debian:bookworm-slim`): installs the required runtime libraries, copies the compiled binary and default `config.toml`, and sets `RUST_LOG=info` before starting the server with that config.
5+
- **Runtime image** (`debian:bookworm-slim`): installs the required runtime libraries, fetches the architecture-specific tarball from GitHub releases (currently `v0.1.0`), places the `echokit_server` binary in `/usr/local/bin`, copies the default `config.toml`, and sets `RUST_LOG=info` before starting the server with that config.
76

87
## Run
98

@@ -12,26 +11,37 @@ Mount your local configuration directory and a writable recordings directory:
1211
```sh
1312
docker run --rm \
1413
-p 8080:8080 \
15-
-v $(pwd)/config:/app \
14+
-v $(pwd)/config.toml:/app/config.toml \
1615
-v $(pwd)/record:/app/record \
1716
secondstate/echokit:latest-server
1817
```
1918

20-
Place `config.toml` and `hello.wav` inside the mounted `config` directory so they appear in `/app` inside the container. The server writes any generated artifacts to `/app/record`, so ensure the `record` directory exists locally and is writable. The container executes `echokit_server config.toml` by default, reading logs at the `info` level.
19+
Mount your `config.toml` directly into `/app/config.toml`. If you need to override additional assets such as `hello.wav`, mount them individually alongside the config file. The server writes any generated artifacts to `/app/record`, so ensure the `record` directory exists locally and is writable. The container executes `echokit_server config.toml` by default, reading logs at the `info` level.
2120

2221
## Build
2322

2423
```sh
2524
docker build -t secondstate/echokit:latest-server -f docker/server/Dockerfile .
2625
```
2726

27+
The build automatically selects the correct release artifact for your build architecture using the BuildKit-provided `TARGETPLATFORM`/`TARGETARCH` arguments. Override the downloaded release by supplying `--build-arg ECHOKIT_VERSION=<version>` (for example `0.1.1`) if you want a different tag.
28+
2829
## Multi-platform build
2930

31+
Use Buildx to produce and publish a multi-arch manifest in one command. BuildKit injects `TARGETPLATFORM` (`linux/amd64`, `linux/arm64`, etc.), so you do not need to set them manually.
32+
3033
```sh
31-
docker buildx build . --platform linux/arm64,linux/amd64 --tag secondstate/echokit:latest-server -f docker/server/Dockerfile
34+
docker buildx build \
35+
--platform linux/amd64,linux/arm64 \
36+
--push \
37+
--build-arg ECHOKIT_VERSION=0.1.0 \
38+
--tag secondstate/echokit:latest-server \
39+
-f docker/server/Dockerfile .
3240
```
3341

34-
## Publish
42+
Adjust `ECHOKIT_VERSION` as needed; omit the flag to fall back to the default version baked into the Dockerfile.
43+
44+
## Publish
3545

3646
```sh
3747
docker login

0 commit comments

Comments
 (0)