Dockerfile 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # Stage 1: Install dependencies (isolated layout, same as local dev)
  2. FROM node:22-bookworm AS deps
  3. # 使用阿里云镜像源。
  4. # 注意: Kaniko 构建时挂了 HTTP/HTTPS 代理, 该代理只放行 HTTPS(CONNECT 隧道),
  5. # 拒绝转发明文 HTTP(会返回 403)。所以 apt 源必须用 https://, 不能用 http://。
  6. RUN sed -i 's|http://deb.debian.org|https://mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources
  7. RUN corepack enable && corepack prepare pnpm@10.24.0 --activate
  8. RUN apt-get update && \
  9. apt-get install -y --no-install-recommends ffmpeg python3 python3-pip && \
  10. rm -rf /var/lib/apt/lists/*
  11. RUN pip3 install --break-system-packages -i https://mirrors.aliyun.com/pypi/simple/ faster-whisper
  12. WORKDIR /app
  13. COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
  14. COPY apps/cli/package.json apps/cli/
  15. COPY apps/web/package.json apps/web/
  16. COPY packages/shared/package.json packages/shared/
  17. COPY packages/core/package.json packages/core/
  18. COPY packages/tts/package.json packages/tts/
  19. COPY packages/templates/package.json packages/templates/
  20. COPY packages/collect/package.json packages/collect/
  21. RUN pnpm config set registry https://registry.npmmirror.com && \
  22. pnpm install --frozen-lockfile
  23. # Stage 2: Build
  24. FROM deps AS build
  25. COPY . .
  26. RUN pnpm build
  27. # Stage 3: Runtime — fresh prod install with hoisted layout
  28. FROM node:22-bookworm-slim AS runtime
  29. # 同上: apt 源用 https, 走代理 CONNECT 隧道, 避免明文 HTTP 被 403。
  30. RUN sed -i 's|http://deb.debian.org|https://mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources
  31. RUN corepack enable && corepack prepare pnpm@10.24.0 --activate
  32. RUN apt-get update && \
  33. apt-get install -y --no-install-recommends \
  34. ffmpeg python3 python3-pip fontconfig \
  35. libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 libdrm2 \
  36. libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
  37. libgbm1 libpango-1.0-0 libcairo2 libasound2 && \
  38. rm -rf /var/lib/apt/lists/*
  39. RUN pip3 install --break-system-packages -i https://mirrors.aliyun.com/pypi/simple/ faster-whisper
  40. WORKDIR /app
  41. # Copy workspace manifests + lockfile so pnpm install can resolve workspaces
  42. COPY --from=build /app/package.json /app/pnpm-lock.yaml /app/pnpm-workspace.yaml /app/turbo.json ./
  43. COPY --from=build /app/apps/cli/package.json apps/cli/
  44. COPY --from=build /app/apps/web/package.json apps/web/
  45. COPY --from=build /app/packages/shared/package.json packages/shared/
  46. COPY --from=build /app/packages/core/package.json packages/core/
  47. COPY --from=build /app/packages/tts/package.json packages/tts/
  48. COPY --from=build /app/packages/templates/package.json packages/templates/
  49. COPY --from=build /app/packages/collect/package.json packages/collect/
  50. # Install production deps with hoisted layout (everything flat at root node_modules)
  51. RUN pnpm config set registry https://registry.npmmirror.com && \
  52. pnpm install --frozen-lockfile --prod --config.node-linker=hoisted
  53. # Re-create workspace symlinks at root so any package can resolve @pipeline/* by walking up
  54. RUN mkdir -p node_modules/@pipeline && \
  55. ln -s ../../packages/shared node_modules/@pipeline/shared && \
  56. ln -s ../../packages/core node_modules/@pipeline/core && \
  57. ln -s ../../packages/tts node_modules/@pipeline/tts && \
  58. ln -s ../../packages/templates node_modules/@pipeline/templates && \
  59. ln -s ../../packages/collect node_modules/@pipeline/collect
  60. # Copy build artifacts (dist, .next, template src for Remotion entry, etc.)
  61. COPY --from=build /app/apps/cli/dist apps/cli/dist/
  62. COPY --from=build /app/apps/web/.next apps/web/.next/
  63. COPY --from=build /app/apps/web/next.config.mjs apps/web/
  64. COPY --from=build /app/apps/web/src apps/web/src/
  65. COPY --from=build /app/packages/shared/dist packages/shared/dist/
  66. COPY --from=build /app/packages/core/dist packages/core/dist/
  67. COPY --from=build /app/packages/tts/dist packages/tts/dist/
  68. COPY --from=build /app/packages/tts/scripts packages/tts/scripts/
  69. COPY --from=build /app/packages/templates/dist packages/templates/dist/
  70. COPY --from=build /app/packages/templates/src packages/templates/src/
  71. COPY --from=build /app/packages/collect/dist packages/collect/dist/
  72. COPY --from=build /app/assets assets/
  73. COPY --from=build /app/config config/
  74. # Install bundled Noto Sans SC as system font so Chrome can render CJK via fontconfig fallback
  75. RUN mkdir -p /usr/share/fonts/truetype/noto && \
  76. cp assets/fonts/NotoSansSC-Regular.ttf assets/fonts/NotoSansSC-Bold.ttf /usr/share/fonts/truetype/noto/ && \
  77. fc-cache -f
  78. # Run as the non-root `node` user (uid/gid 1000, shipped in the base image) so
  79. # the image is Pod Security "restricted"-friendly. Only the writable paths are
  80. # chowned to keep the layer small: the PVC-backed output, Next.js' .next cache,
  81. # and a HOME for Remotion's browser / faster-whisper model download cache.
  82. ENV HOME=/home/node
  83. RUN mkdir -p /app/output /home/node && \
  84. chown -R node:node /app/output /home/node /app/apps/web/.next
  85. USER node
  86. EXPOSE 3000
  87. # Docker Compose / `docker run` health; Kubernetes uses its own probes against
  88. # the same endpoints. global fetch is available on Node 22.
  89. HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
  90. CMD node -e "fetch('http://127.0.0.1:3000/api/health/live').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
  91. WORKDIR /app/apps/web
  92. CMD ["/app/node_modules/.bin/next", "start"]