82 lines
3.8 KiB
Docker
82 lines
3.8 KiB
Docker
# syntax=docker/dockerfile:1
|
||
# 与 .node-version 对齐;可用 build-arg 覆盖
|
||
ARG NODE_VERSION=26.7.0
|
||
|
||
FROM node:${NODE_VERSION}-alpine AS base
|
||
WORKDIR /app
|
||
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 \
|
||
TURBO_TELEMETRY_DISABLED=1 \
|
||
DO_NOT_TRACK=1
|
||
# Node 25+ 官方镜像不再内置 corepack,需显式安装以使用 yarn@4
|
||
RUN npm install -g corepack && corepack enable
|
||
|
||
# ---- 依赖层:只拷清单,最大化 yarn 缓存 ----
|
||
FROM base AS deps
|
||
COPY package.json yarn.lock .yarnrc.yml ./
|
||
COPY app/web/package.json app/web/package.json
|
||
# workspaces: app/* + packages/* — 清单缺一不可,否则 yarn 解析 workspace:* 失败或漏链
|
||
COPY app/docs/package.json app/docs/package.json
|
||
COPY packages/adsense/package.json packages/adsense/package.json
|
||
COPY packages/dao/package.json packages/dao/package.json
|
||
COPY packages/db/package.json packages/db/package.json
|
||
COPY packages/design-tokens/package.json packages/design-tokens/package.json
|
||
COPY packages/i18n/package.json packages/i18n/package.json
|
||
COPY packages/models/package.json packages/models/package.json
|
||
COPY packages/seo-geo/package.json packages/seo-geo/package.json
|
||
COPY packages/trpc/package.json packages/trpc/package.json
|
||
COPY packages/types/package.json packages/types/package.json
|
||
COPY packages/ui/package.json packages/ui/package.json
|
||
RUN --mount=type=cache,target=/root/.yarn/berry/cache \
|
||
yarn install --immutable
|
||
|
||
# ---- 构建层:只 build web 依赖闭包 + 裁剪生产依赖 ----
|
||
FROM deps AS build
|
||
COPY . .
|
||
# Astro 构建期内联 PUBLIC_*;空串会导致 canonical/sitemap 抛 Invalid URL,
|
||
# 因此给 localhost 默认值,生产用 --build-arg PUBLIC_SITE_URL=https://example.com 覆盖
|
||
ARG PUBLIC_SITE_URL=http://localhost:4321
|
||
ENV PUBLIC_SITE_URL=${PUBLIC_SITE_URL} \
|
||
ASTRO_TELEMETRY_DISABLED=1 \
|
||
TURBO_TELEMETRY_DISABLED=1
|
||
# --filter=@app/web...:web + 其上游依赖;跳过 adsense 等无关包
|
||
# --cache-dir 指到 /tmp:与 .turbo 分离,rm -rf .turbo 不会清掉 BuildKit 缓存挂载
|
||
# 缓存挂载需 BuildKit(DOCKER_BUILDKIT=1)
|
||
RUN --mount=type=cache,id=turbo-cache,target=/tmp/turbo-cache \
|
||
yarn turbo run build --filter=@app/web... --cache-dir=/tmp/turbo-cache \
|
||
&& yarn workspaces focus --production @app/web \
|
||
&& rm -rf .git .turbo output \
|
||
&& rm -rf packages/*/src packages/*/*.tsbuildinfo \
|
||
&& rm -rf app/web/src app/web/node_modules/.vite
|
||
|
||
# ---- 运行层:仅产物 + 生产 node_modules ----
|
||
FROM node:${NODE_VERSION}-alpine AS runner
|
||
WORKDIR /app
|
||
ENV NODE_ENV=production \
|
||
HOST=0.0.0.0 \
|
||
HOSTNAME=0.0.0.0 \
|
||
PORT=4321 \
|
||
# file: 库与 session 的可写位置(/app 属主为 root,node 用户不可写)
|
||
TMPDIR=/tmp \
|
||
# 默认本地 sqlite;生产可 -e TURSO_DATABASE_URL=libsql://... 覆盖
|
||
TURSO_DATABASE_URL=file:/app/data/local.db \
|
||
# 挂载凭据加密(64 hex):运行时必须 -e MEDIA_SECRET_KEY=...
|
||
MEDIA_SECRET_KEY= \
|
||
# 可选:开放弹幕 AppId/Secret、Bangumi/Open API 地址见 .env.example
|
||
OPEN_DANMAKU_APP_ID= \
|
||
OPEN_DANMAKU_APP_SECRET=
|
||
|
||
COPY --from=build --chown=node:node /app/package.json /app/yarn.lock /app/.yarnrc.yml ./
|
||
COPY --from=build --chown=node:node /app/app/web/package.json app/web/package.json
|
||
COPY --from=build --chown=node:node /app/app/web/dist app/web/dist
|
||
COPY --from=build --chown=node:node /app/packages packages
|
||
COPY --from=build --chown=node:node /app/node_modules node_modules
|
||
# 工作区内可能存在的局部 node_modules(会话缓存写在其 .astro 下)
|
||
COPY --from=build --chown=node:node /app/app/web/node_modules app/web/node_modules
|
||
RUN mkdir -p /app/data && chown node:node /app/data
|
||
|
||
USER node
|
||
EXPOSE 4321
|
||
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
|
||
CMD wget -q -O /dev/null "http://127.0.0.1:4321/" || exit 1
|
||
CMD ["node", "app/web/dist/server/entry.mjs"]
|