Files
zhuiguang-ai/Dockerfile
T

105 lines
4.4 KiB
Docker
Raw 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.
# =============================================================================
# 追光AI 项目 Dockerfile (多阶段构建)
# - stage 1 deps : 安装全部依赖 (含 dev)
# - stage 2 builder : 跑 next build + prisma generate
# - stage 3 runner : 仅拷贝运行所需,最小化镜像
# - 一个镜像两种身份:APP 启动 nextjs / CRON 启动 supercronic(docker-compose 决定)
# =============================================================================
# ---- 阶段 1: 安装依赖 ----
FROM node:20-alpine AS deps
WORKDIR /app
# 装 python + make + g++ 给 mysql2 / bcryptjs 等原生模块编译用
# 先切换到 aliyun apk 镜像(默认源在中国大陆极慢,1m+ vs 0.1s)
RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories \
&& apk add --no-cache python3 make g++ openssl
# 先 copy lock file 缓存层
COPY package.json package-lock.json ./
COPY prisma ./prisma
# 用 ci 安装保证版本一致(同时切到 npmmirror 加速)
RUN npm config set registry https://registry.npmmirror.com \
&& npm ci --no-audit --no-fund --include=dev
# ---- 阶段 2: 构建 ----
FROM node:20-alpine AS builder
WORKDIR /app
RUN sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories \
&& apk add --no-cache python3 make g++ openssl
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
ENV npm_config_registry=https://registry.npmmirror.com
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 跑 next build 生成 .next/
# DATABASE_URL 在 build 时不需要(next 是 SSG/SSR-on-demand),但 prisma generate 需要
# 用 .env.example 当 placeholder 生成 prisma client
# 同时注入 OPENAI_API_KEY / DEEPSEEK_API_KEY 占位值,避免 openai SDK v6+ 构造时抛错
# (build 期不会真正调用 AI,仅为通过模块求值)
RUN if [ ! -f .env ]; then cp .env.example .env 2>/dev/null || echo "DATABASE_URL=placeholder" > .env; fi \
&& export DEEPSEEK_API_KEY="${DEEPSEEK_API_KEY:-sk-build-placeholder}" \
&& export OPENAI_API_KEY="${OPENAI_API_KEY:-sk-build-placeholder}" \
&& npx prisma generate \
&& DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" OPENAI_API_KEY="$OPENAI_API_KEY" npm run build
# ---- 阶段 3: 运行 ----
FROM node:20-alpine AS runner
WORKDIR /app
# runtime 基础包
RUN apk add --no-cache openssl tini curl bash
# supercronic 用于 cron 容器调度(架构:alpine musl 兼容)
# 直接 COPY 本地预下载的二进制(避免 Docker build 阶段从 GitHub 下载超时)
# 下载源: https://github.com/aptible/supercronic/releases/tag/v0.2.33
# SHA1: 71b0d58cc53f6bd72cf2f293e09e294b79c666d8
ARG SUPERCRONIC=supercronic-linux-amd64
COPY --chown=root:root scripts/bin/${SUPERCRONIC} /usr/local/bin/${SUPERCRONIC}
RUN chmod +x /usr/local/bin/${SUPERCRONIC}
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=8301
ENV HOSTNAME=0.0.0.0
# 非 root 运行
RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001
# 拷贝必要文件
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/scripts ./scripts
# seed data files for volume auto-fill
COPY --from=builder --chown=nextjs:nodejs /app/data ./data-seed
# 配置/类型文件(必须存在;如果不存在 COPY 会失败但构建继续)
COPY --from=builder /app/next.config.mjs ./next.config.mjs
COPY --from=builder /app/postcss.config.mjs ./postcss.config.mjs
COPY --from=builder /app/tsconfig.json ./tsconfig.json
COPY --from=builder /app/components.json ./components.json
# entrypoint 脚本
COPY --chown=root:root scripts/entrypoint-app.sh /usr/local/bin/entrypoint-app.sh
COPY --chown=root:root scripts/entrypoint-cron.sh /usr/local/bin/entrypoint-cron.sh
RUN chmod +x /usr/local/bin/entrypoint-app.sh /usr/local/bin/entrypoint-cron.sh
# 数据 / 日志目录交给 nextjs
RUN mkdir -p /app/data /app/public/bot-avatars /app/logs && chown -R nextjs:nodejs /app/data /app/public /app/logs
# 健康检查 (用 curl 探活)
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD curl -fs http://localhost:8301/api/health || exit 1
# 默认是 app 身份,cron 容器在 compose 里 override command
USER nextjs
EXPOSE 8301
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["/usr/local/bin/entrypoint-app.sh"]