Adds: - tsx@4.21.0 as a regular (non-dev) dependency. Bundle ~3 MB; required in production since Dockerfile installs with --omit=dev. - npm script: start → 'tsx server.js' (was 'node server.js'). - Dockerfile CMD → ['/app/node_modules/.bin/tsx', 'server.js']. Why: any backend file can now be renamed .js → .ts without breaking the require chain — tsx handles both transparently. server.js itself stays plain JS for now; the conversion is route-by-route in subsequent commits. Validation: - ./node_modules/.bin/tsx loads all 32 src/routes/*.js files cleanly, including the argon2 native module. - 46/46 unit tests pass (tests run under plain node --test, unaffected by start-command change). - Local server can't fully boot here (no Postgres on dev box), but the request chain, AI-provider init, and route loading all complete before the DB connect step. Rollback anchors: - pre-ts-migration-2026-04-26 (commit 47b8511) — pre-scaffold - ts-phase-0-2026-04-27 — scaffold installed, runtime unchanged - ts-phase-1-2026-04-27 (this commit) — tsx runtime active
62 lines
3.1 KiB
Docker
62 lines
3.1 KiB
Docker
# ─── OpenBao CLI, copied from upstream image (multi-arch automatic) ───
|
|
# Update the tag here to adopt a newer OpenBao. Binary is statically linked,
|
|
# safe to drop into the Node alpine image as-is.
|
|
FROM openbao/openbao:2.5.3 AS bao-src
|
|
|
|
FROM node:20-alpine
|
|
|
|
WORKDIR /app
|
|
|
|
# ffmpeg: audio conversion for AWS Transcribe (WebM → PCM)
|
|
# curl: download Whisper models for browser-based transcription
|
|
# jq: JSON parsing for the entrypoint's OpenBao secret-fetch step
|
|
RUN apk add --no-cache ffmpeg curl jq
|
|
|
|
# Pull the bao CLI out of the upstream image — matches host arch because
|
|
# buildx pulls the right manifest-list variant per build.
|
|
COPY --from=bao-src /bin/bao /usr/local/bin/bao
|
|
RUN /usr/local/bin/bao version
|
|
|
|
COPY package.json ./
|
|
# argon2 compiles native code via node-gyp — needs python3/make/g++ at build time
|
|
RUN apk add --no-cache --virtual .build-deps python3 make g++ \
|
|
&& npm install --omit=dev \
|
|
&& apk del .build-deps
|
|
|
|
COPY . .
|
|
|
|
# Ensure the entrypoint is executable regardless of host file permissions
|
|
RUN chmod +x /app/docker-entrypoint.sh
|
|
|
|
RUN mkdir -p /app/data/logs
|
|
|
|
# Download Browser Whisper (COMPLETE self-hosting - zero CDN dependencies)
|
|
# Library + Models all bundled and served from our server
|
|
RUN mkdir -p /app/public/models/Xenova/whisper-tiny.en/onnx && \
|
|
cd /app/public/models && \
|
|
echo "Downloading transformers.js library (worker-compatible build)..." && \
|
|
curl -sL -o transformers.min.js https://cdn.jsdelivr.net/npm/@xenova/transformers@2.0.0/dist/transformers.min.js && \
|
|
cd Xenova/whisper-tiny.en && \
|
|
echo "Downloading Whisper model files..." && \
|
|
curl -sL -o config.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/config.json && \
|
|
curl -sL -o tokenizer.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/tokenizer.json && \
|
|
curl -sL -o preprocessor_config.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/preprocessor_config.json && \
|
|
curl -sL -o generation_config.json https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/generation_config.json && \
|
|
curl -sL -o onnx/encoder_model_quantized.onnx https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/onnx/encoder_model_quantized.onnx && \
|
|
curl -sL -o onnx/decoder_model_merged_quantized.onnx https://huggingface.co/Xenova/whisper-tiny.en/resolve/main/onnx/decoder_model_merged_quantized.onnx && \
|
|
echo "✅ Browser Whisper: 100% self-hosted (library: 760KB, models: 42MB)"
|
|
|
|
EXPOSE 3000
|
|
|
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s \
|
|
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
|
|
|
|
# Entrypoint wrapper handles optional OpenBao secret fetch before exec'ing CMD.
|
|
# See docker-entrypoint.sh for the logic — it is a no-op if OPENBAO_ADDR is
|
|
# unset, so legacy .env-only deployments continue to work unchanged.
|
|
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
|
# tsx instead of node so the runtime accepts .ts files transparently as
|
|
# the migration progresses. Currently server.js is still plain JS — tsx
|
|
# runs it identically. Direct path to the binary avoids npx startup cost.
|
|
CMD ["/app/node_modules/.bin/tsx", "server.js"]
|
|
|