Files
2026-05-05 17:46:17 +09:00

162 lines
5.5 KiB
Docker
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ============================================================
# SmallClaw / LocalClaw – Dockerfile
# ============================================================
# Multi-stage build:
# 1. builder – compiles TypeScript → dist/
# 2. runtime – lean production image with Playwright + Tesseract deps
# ── Stage 1: Builder ────────────────────────────────────────
FROM node:20-slim AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build
# ── Stage 2: Runtime ────────────────────────────────────────
FROM node:20-slim AS runtime
# System deps: Playwright/Chromium + Tesseract OCR + ffmpeg (for voice)
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
wget \
ffmpeg \
fonts-liberation \
libatk-bridge2.0-0 \
libatk1.0-0 \
libcairo2 \
libcups2 \
libdbus-1-3 \
libdrm2 \
libexpat1 \
libgbm1 \
libglib2.0-0 \
libgtk-3-0 \
libnspr4 \
libnss3 \
libpango-1.0-0 \
libpangocairo-1.0-0 \
libx11-6 \
libx11-xcb1 \
libxcb1 \
libxcomposite1 \
libxdamage1 \
libxext6 \
libxfixes3 \
libxrandr2 \
libxrender1 \
libxss1 \
libxtst6 \
xdg-utils \
tesseract-ocr \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Production deps only
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# Install Playwright browser binaries
RUN npx playwright install chromium --with-deps 2>/dev/null || true
# Install Piper TTS binary + Korean voice model (from neurlang — rhasspy repo returns 404 for Korean)
RUN ARCH=$(dpkg --print-architecture) && \
if [ "$ARCH" = "amd64" ]; then PIPER_ARCH="x86_64"; \
elif [ "$ARCH" = "arm64" ]; then PIPER_ARCH="aarch64"; \
elif [ "$ARCH" = "armhf" ]; then PIPER_ARCH="armv7l"; \
else PIPER_ARCH="$ARCH"; fi && \
cd /tmp && \
curl -L "https://github.com/rhasspy/piper/releases/download/2023.11.14-2/piper_linux_${PIPER_ARCH}.tar.gz" -o piper.tar.gz && \
tar xzf piper.tar.gz && \
cp piper/piper /usr/local/bin/piper && \
chmod +x /usr/local/bin/piper && \
cp piper/libespeak-ng.so* /usr/local/lib/ && \
cp piper/libonnxruntime.so* /usr/local/lib/ && \
cp piper/libpiper_phonemize.so* /usr/local/lib/ && \
cp piper/espeak-ng /usr/local/lib/ && \
cp -r piper/espeak-ng-data /usr/local/lib/ && \
ldconfig && \
rm -rf piper piper.tar.gz && \
mkdir -p /usr/local/share/piper-voices && \
curl -L "https://huggingface.co/neurlang/piper-onnx-kss-korean/resolve/main/piper-kss-korean.onnx" \
-o /usr/local/share/piper-voices/ko_KR-kss-medium.onnx && \
curl -L "https://huggingface.co/neurlang/piper-onnx-kss-korean/raw/main/piper-kss-korean.onnx.json" \
-o /usr/local/share/piper-voices/ko_KR-kss-medium.onnx.json
# Install whisper.cpp (build from source — no pre-built Linux binary)
RUN apt-get update && apt-get install -y --no-install-recommends cmake git build-essential && \
cd /tmp && \
git clone https://github.com/ggml-org/whisper.cpp.git && \
cd whisper.cpp && \
cmake -B build && \
cmake --build build --config Release -j$(nproc) && \
cp build/bin/whisper-cli /usr/local/bin/whisper-cli && \
rm -rf /tmp/whisper.cpp && \
apt-get remove -y git build-essential && \
apt-get autoremove -y && \
rm -rf /var/lib/apt/lists/* && \
mkdir -p /usr/local/share/whisper-models && \
curl -L "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin" \
-o /usr/local/share/whisper-models/ggml-base.bin
# Compiled app from builder
COPY --from=builder /app/dist ./dist
# Static web UI
COPY web-ui/ ./web-ui/
# Data directories (overridden by volumes in compose)
RUN mkdir -p /data/workspace /data/logs /root/.localclaw
# ── Environment defaults ─────────────────────────────────────
# These are overridden by docker-compose.yml / -e flags.
# Provider: ollama | lm_studio | llama_cpp | openai | openai_codex
ENV NODE_ENV=production \
DOCKER_CONTAINER=true \
SMALLCLAW_DATA_DIR=/data \
SMALLCLAW_WORKSPACE_DIR=/data/workspace \
GATEWAY_PORT=18789 \
GATEWAY_HOST=0.0.0.0 \
PLAYWRIGHT_BROWSERS_PATH=/root/.cache/ms-playwright \
\
# Active provider
SMALLCLAW_PROVIDER=ollama \
\
# Ollama
OLLAMA_HOST=http://ollama:11434 \
\
# LM Studio (host machine via host.docker.internal)
LM_STUDIO_ENDPOINT=http://host.docker.internal:1234 \
LM_STUDIO_API_KEY="" \
LM_STUDIO_MODEL="" \
\
# llama.cpp (host machine via host.docker.internal)
LLAMA_CPP_ENDPOINT=http://host.docker.internal:8080 \
LLAMA_CPP_MODEL="" \
\
# OpenAI
OPENAI_API_KEY="" \
OPENAI_MODEL=gpt-4o \
\
# OpenAI Codex OAuth (tokens live in mounted ~/.localclaw volume)
CODEX_MODEL=gpt-5.3-codex \
\
# Voice (Piper TTS + Whisper STT model paths)
PIPER_MODEL_PATH=/usr/local/share/piper-voices/ko_KR-kss-medium.onnx \
PIPER_CONFIG_PATH=/usr/local/share/piper-voices/ko_KR-kss-medium.onnx.json \
WHISPER_MODEL_PATH=/usr/local/share/whisper-models/ggml-base.bin
EXPOSE 18789
HEALTHCHECK --interval=30s --timeout=10s --start-period=15s --retries=3 \
CMD curl -f http://localhost:18789/health || exit 1
CMD ["node", "dist/cli/index.js", "gateway"]