diff --git a/Dockerfile b/Dockerfile index 7d837c5..80e6479 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ -FROM node:22-alpine AS base +# sherpa-onnx 사전 빌드 바이너리가 glibc에 링크되어 있어 Alpine(musl)에서는 +# ld-linux-aarch64.so.1 을 찾지 못한다. glibc 계열인 slim 을 쓴다. +FROM node:22-slim AS base FROM base AS deps WORKDIR /app @@ -15,8 +17,8 @@ RUN npm run build FROM base AS runner WORKDIR /app ENV NODE_ENV=production -RUN addgroup --system --gid 1001 nodejs -RUN adduser --system --uid 1001 nextjs +RUN groupadd --system --gid 1001 nodejs \ + && useradd --system --uid 1001 --gid nodejs nextjs COPY --from=builder /app/public ./public COPY --from=builder /app/.next/standalone ./ COPY --from=builder /app/.next/static ./.next/static @@ -24,6 +26,9 @@ COPY --from=builder /app/prisma ./prisma RUN mkdir -p uploads && chown nextjs:nodejs uploads +# sherpa-onnx의 .so는 표준 검색 경로에 없으므로 명시해준다. +ENV LD_LIBRARY_PATH=/app/node_modules/sherpa-onnx-linux-arm64:/app/node_modules/sherpa-onnx-linux-x64 + USER nextjs EXPOSE 3000 ENV PORT=3000 diff --git a/README.md b/README.md index d6e8f2b..ea51b2e 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,10 @@ Next.js 프로세스에서 실행합니다. **오디오가 외부로 나가지 npm run setup:diarization ``` +> Docker로 실행하실 때도 **호스트에서** 위 명령을 먼저 실행하세요. `models/` 디렉터리가 +> 컨테이너에 읽기 전용으로 마운트됩니다. 받지 않으면 대면 모드만 비활성화되고 나머지는 +> 정상 동작합니다. + > 💡 **참석자 수를 정확히 입력하세요.** 자동 추정은 화자 수를 잘못 세는 것이 주 실패 > 모드입니다. 실측에서 4인 오디오가 자동 모드로는 5명, 참석자 수를 알려주면 4명으로 > 정확히 나왔습니다. diff --git a/docker-compose.yml b/docker-compose.yml index d744dfd..03252fb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,8 +43,17 @@ services: environment: DATABASE_URL: postgresql://${POSTGRES_USER:?required}:${POSTGRES_PASSWORD:?required}@db:5432/${POSTGRES_DB:?required} GEMINI_API_KEY: ${GEMINI_API_KEY:-} + # OpenAI 호환 프로바이더 (선택) — 없으면 브라우저에 저장된 설정을 쓴다 + LLM_PROVIDER: ${LLM_PROVIDER:-} + LLM_BASE_URL: ${LLM_BASE_URL:-} + LLM_MODEL: ${LLM_MODEL:-} + LLM_API_KEY: ${LLM_API_KEY:-} + DIARIZATION_MODEL_DIR: /app/models/diarization volumes: - uploads:/app/uploads + # 화자 분리 모델 — 호스트에서 npm run setup:diarization 으로 받은 것을 읽기 전용으로 마운트. + # 없으면 빈 디렉터리가 되고 대면 화자 분리만 비활성화된다 (앱은 정상 동작). + - ./models:/app/models:ro depends_on: db: condition: service_healthy diff --git a/next.config.ts b/next.config.ts index ef9a988..fbd3ef9 100644 --- a/next.config.ts +++ b/next.config.ts @@ -14,6 +14,11 @@ const nextConfig: NextConfig = { output: "standalone", // sherpa-onnx-node는 네이티브 애드온이라 번들링하면 안 된다. serverExternalPackages: ["sherpa-onnx-node"], + // 트레이싱은 .node 파일만 잡고 동반 공유 라이브러리(.so/.dylib)를 놓친다. + // 플랫폼 패키지를 통째로 포함시켜야 standalone 빌드에서 로드된다. + outputFileTracingIncludes: { + "/api/diarize": ["./node_modules/sherpa-onnx-*/**"], + }, async headers() { return [ {