-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathDockerfile
More file actions
81 lines (76 loc) · 3.02 KB
/
Copy pathDockerfile
File metadata and controls
81 lines (76 loc) · 3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# BokeBox · 生产镜像(激进瘦身)
#
# 1) 全流程 Alpine,保证 sharp 拿到 musl 预编译
# 2) pnpm deploy 导出最小 server 闭包;最终层无 pnpm / monorepo
# 3) ffmpeg-static 单文件,不用发行版 ffmpeg 全家桶
FROM node:22-alpine AS base
WORKDIR /app
ENV PNPM_HOME="/pnpm" \
PATH="/pnpm:$PATH" \
CI=1
RUN apk add --no-cache libc6-compat \
&& corepack enable \
&& corepack prepare pnpm@9.15.0 --activate \
&& pnpm --version
FROM base AS deps
WORKDIR /app
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY apps/server/package.json ./apps/server/
COPY apps/web/package.json ./apps/web/
COPY packages/shared/package.json ./packages/shared/
RUN pnpm install --frozen-lockfile
FROM deps AS build
WORKDIR /app
COPY apps ./apps
COPY packages ./packages
RUN pnpm --filter @bokebox/shared build \
&& pnpm --filter @bokebox/web build \
&& pnpm --filter @bokebox/server build
FROM build AS export
WORKDIR /app
RUN pnpm --filter @bokebox/server deploy --prod /out \
&& node -e "const p=require('/out/node_modules/ffmpeg-static'); if(!p) process.exit(1); console.log('ffmpeg', p)" \
&& node -e "require('/out/node_modules/sharp'); console.log('sharp ok')" \
&& find /out/node_modules -type f \( \
-name '*.md' -o -name '*.markdown' -o -name 'CHANGELOG*' \
-o -name '*.map' -o -name 'tsconfig*.json' -o -name '*.ts' \
\) ! -path '*/ffmpeg-static/*' -delete || true \
&& find /out/node_modules -type d \( \
-name 'test' -o -name 'tests' -o -name '__tests__' \
-o -name 'docs' -o -name 'example' -o -name 'examples' \
-o -name '.github' \
\) -prune -exec rm -rf {} + || true \
&& rm -rf /out/node_modules/.cache /tmp/* /root/.local /root/.cache
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production \
HOST=0.0.0.0 \
PORT=8787 \
BOKEBOX_ROOT=/app \
WEB_DIST=/app/web \
STORAGE_DIR=/app/storage
# 生产运行只需要 node 运行时;移除镜像自带的 npm/corepack/yarn,避免扫描到无用供应链 CVE
RUN apk add --no-cache libc6-compat \
&& apk upgrade --no-cache \
&& npm -g uninstall npm || true \
&& rm -rf /usr/local/lib/node_modules/npm \
/usr/local/lib/node_modules/corepack \
/usr/local/bin/npm \
/usr/local/bin/npx \
/usr/local/bin/corepack \
/usr/local/bin/yarn \
/usr/local/bin/yarnpkg \
/root/.npm \
/tmp/* \
/var/cache/apk/*
COPY --from=export /out/ ./
COPY --from=build /app/apps/web/dist ./web
RUN node --input-type=module -e "await import('./dist/services/content/scriptPrompt.js')" \
&& node --input-type=module -e "await import('sharp')" \
&& node -e "const p=require('ffmpeg-static'); if(!p) process.exit(1)" \
&& mkdir -p /app/storage/jobs \
&& rm -rf /tmp/* /root/.npm /root/.cache
EXPOSE 8787
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:'+(process.env.PORT||8787)+'/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
CMD ["node", "dist/index.js"]