包含: - furniture-3d-system:Next.js 16 全栈应用(资产中心、产品管理、3D装配动画) - autocad-plugin:AutoCAD 家具导出插件源码 - 资产中心改造:编辑弹窗化、删除功能、Toast反馈、自定义Select组件 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
192 lines
5.9 KiB
Docker
192 lines
5.9 KiB
Docker
# ============================================
|
||
# 3D家具安装展示系统 - 优化版Dockerfile
|
||
# 优先使用本地缓存,支持离线构建
|
||
# ============================================
|
||
|
||
# ============================================
|
||
# 阶段 1: 基础镜像
|
||
# ============================================
|
||
FROM node:18-alpine AS base
|
||
|
||
# 使用阿里云镜像源加速(中国网络优化)
|
||
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
|
||
|
||
# 安装基础运行时依赖
|
||
RUN apk add --no-cache \
|
||
libc6-compat \
|
||
ca-certificates \
|
||
openssl3
|
||
|
||
# ============================================
|
||
# 阶段 2: 依赖安装 (deps)
|
||
# ============================================
|
||
FROM base AS deps
|
||
|
||
# 安装构建时依赖
|
||
RUN apk add --no-cache --virtual .build-deps \
|
||
python3 \
|
||
make \
|
||
g++ \
|
||
pkgconfig \
|
||
openssl-dev
|
||
|
||
WORKDIR /app
|
||
|
||
# 复制package文件
|
||
COPY package.json package-lock.json* ./
|
||
|
||
# 检查是否有本地缓存的node_modules
|
||
COPY cache/node_modules* ./cache_node_modules/ 2>/dev/null || true
|
||
|
||
# 配置npm使用国内镜像源
|
||
RUN npm config set registry https://registry.npmmirror.com/
|
||
|
||
# 智能安装依赖:优先使用缓存,然后网络安装
|
||
RUN set -ex && \
|
||
# 如果有本地缓存,先复制关键包
|
||
if [ -d "./cache_node_modules" ]; then \
|
||
echo "🔄 发现本地依赖缓存,正在复制..." && \
|
||
mkdir -p node_modules && \
|
||
# 复制关键包
|
||
for pkg in "@prisma" ".prisma" "prisma" "sharp" "next" "react" "react-dom" "@aws-sdk" "three" "gsap"; do \
|
||
if [ -d "./cache_node_modules/$pkg" ]; then \
|
||
echo "📦 复制缓存包: $pkg" && \
|
||
cp -r "./cache_node_modules/$pkg" "./node_modules/" || true; \
|
||
fi; \
|
||
done; \
|
||
fi && \
|
||
# 执行npm install(会跳过已存在的包)
|
||
echo "📥 安装剩余依赖..." && \
|
||
npm ci --prefer-offline --no-audit || npm install --prefer-offline --no-audit
|
||
|
||
# 清理构建依赖
|
||
RUN apk del .build-deps && \
|
||
npm config delete registry && \
|
||
rm -rf ./cache_node_modules
|
||
|
||
# ============================================
|
||
# 阶段 3: 构建应用 (builder)
|
||
# ============================================
|
||
FROM base AS builder
|
||
|
||
# 构建参数
|
||
ARG DATABASE_URL=""
|
||
ARG NEXTAUTH_URL=""
|
||
ARG APP_PUBLIC_URL=""
|
||
|
||
# 环境变量
|
||
ENV DATABASE_URL=${DATABASE_URL}
|
||
ENV NEXTAUTH_URL=${NEXTAUTH_URL}
|
||
ENV APP_PUBLIC_URL=${APP_PUBLIC_URL}
|
||
ENV NEXT_TELEMETRY_DISABLED=1
|
||
ENV NODE_ENV=production
|
||
|
||
WORKDIR /app
|
||
|
||
# 安装OpenSSL(Prisma需要)
|
||
RUN apk add --no-cache openssl3
|
||
|
||
# 从deps阶段复制node_modules
|
||
COPY --from=deps /app/node_modules ./node_modules
|
||
|
||
# 复制应用源代码
|
||
COPY . .
|
||
|
||
# 复制本地Prisma引擎缓存(如果存在)
|
||
COPY cache/prisma-engines* ./prisma/engine-cache/ 2>/dev/null || true
|
||
|
||
# 配置Prisma引擎缓存路径
|
||
ENV PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1
|
||
ENV PRISMA_ENGINE_CACHE_PATH=/app/prisma/engine-cache/libquery_engine-linux-musl-openssl-3.0.x.so.node
|
||
ENV PRISMA_SCHEMA_ENGINE_CACHE_PATH=/app/prisma/engine-cache/schema-engine-linux-musl-openssl-3.0.x
|
||
|
||
# 智能生成Prisma Client:优先使用本地引擎
|
||
RUN set -ex && \
|
||
# 检查本地引擎缓存
|
||
if [ -f "${PRISMA_ENGINE_CACHE_PATH}" ]; then \
|
||
echo "🔧 使用本地Prisma查询引擎缓存" && \
|
||
export PRISMA_QUERY_ENGINE_LIBRARY="${PRISMA_ENGINE_CACHE_PATH}" && \
|
||
export PRISMA_CLIENT_ENGINE_TYPE=library && \
|
||
export PRISMA_CLI_QUERY_ENGINE_TYPE=library; \
|
||
else \
|
||
echo "⚠️ 本地Prisma引擎缓存不可用,将在线下载"; \
|
||
fi && \
|
||
if [ -f "${PRISMA_SCHEMA_ENGINE_CACHE_PATH}" ]; then \
|
||
echo "🔧 使用本地Prisma schema引擎缓存" && \
|
||
export PRISMA_SCHEMA_ENGINE_BINARY="${PRISMA_SCHEMA_ENGINE_CACHE_PATH}"; \
|
||
fi && \
|
||
# 生成Prisma Client
|
||
if npx prisma generate; then \
|
||
echo "✅ Prisma Client生成成功"; \
|
||
else \
|
||
echo "⚠️ 官方源失败,尝试镜像源..." && \
|
||
PRISMA_ENGINES_MIRROR="https://registry.npmmirror.com/-/binary/prisma/" npx prisma generate; \
|
||
fi
|
||
|
||
# 构建Next.js应用
|
||
RUN set -ex && \
|
||
echo "🏗️ 构建Next.js应用..." && \
|
||
npm run build && \
|
||
echo "✅ 构建完成"
|
||
|
||
# 验证构建产物
|
||
RUN if [ ! -f ".next/standalone/server.js" ]; then \
|
||
echo "❌ standalone输出未生成,请检查next.config.js配置" >&2 && \
|
||
exit 1; \
|
||
fi
|
||
|
||
# ============================================
|
||
# 阶段 4: 生产运行 (runner)
|
||
# ============================================
|
||
FROM base AS runner
|
||
|
||
WORKDIR /app
|
||
|
||
# 生产环境变量
|
||
ENV NODE_ENV=production
|
||
ENV NEXT_TELEMETRY_DISABLED=1
|
||
ENV PORT=3000
|
||
ENV HOSTNAME="0.0.0.0"
|
||
|
||
# 安装运行时依赖
|
||
RUN apk add --no-cache \
|
||
# 字体支持(3D渲染可能需要)
|
||
fontconfig \
|
||
ttf-dejavu \
|
||
# 图像处理(Sharp需要)
|
||
vips-dev
|
||
|
||
# 创建非root用户
|
||
RUN addgroup --system --gid 1001 nodejs && \
|
||
adduser --system --uid 1001 nextjs
|
||
|
||
# 复制构建产物
|
||
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||
|
||
# 复制必要文件
|
||
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
|
||
COPY --from=builder --chown=nextjs:nodejs /app/prisma ./prisma
|
||
|
||
# 复制关键运行时模块
|
||
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/.prisma ./node_modules/.prisma
|
||
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma
|
||
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/prisma ./node_modules/prisma
|
||
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/.bin ./node_modules/.bin
|
||
|
||
# 创建上传目录
|
||
RUN mkdir -p /app/uploads && \
|
||
chown -R nextjs:nodejs /app/uploads && \
|
||
chmod -R 755 /app/uploads
|
||
|
||
# 切换到非root用户
|
||
USER nextjs
|
||
|
||
EXPOSE 3000
|
||
|
||
# 健康检查
|
||
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||
CMD curl -f http://localhost:3000/api/health || exit 1
|
||
|
||
# 启动应用
|
||
CMD ["node", "server.js"] |