Files
massive-cloud/Dockerfile

139 lines
4.9 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.
# 宏量点云处理软件 - 生产环境Dockerfile
# 多阶段构建,优化镜像大小
# ============================================
# 阶段1: 依赖安装
# ============================================
FROM node:22-alpine AS deps
WORKDIR /app
# 安装pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# 复制依赖文件
COPY package.json pnpm-lock.yaml* ./
COPY patches ./patches
# 安装依赖
RUN pnpm install --frozen-lockfile --prod=false
# ============================================
# 阶段2: 构建应用
# ============================================
FROM node:22-alpine AS builder
WORKDIR /app
# 安装pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# 复制依赖
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# 设置构建时环境变量
ARG VITE_APP_TITLE="宏量点云处理软件"
ENV VITE_APP_TITLE=$VITE_APP_TITLE
# 构建应用
RUN pnpm build
# ============================================
# 阶段3: 生产运行环境(bookworm:与 dev 一致,便于 cadquery manylinux 轮子)
# ============================================
FROM node:22-bookworm-slim AS runner
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
dumb-init \
python3 \
python3-pip \
ca-certificates \
libgl1 \
libglib2.0-0 \
libxrender1 \
libxext6 \
libsm6 \
libice6 \
libx11-6 \
libgomp1 \
&& rm -rf /var/lib/apt/lists/*
# cadquery-ocp 轮子较大,须加大 pip 超时;覆盖:--build-arg PIP_DEFAULT_TIMEOUT=600
ARG PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple
ARG PIP_DEFAULT_TIMEOUT=300
COPY requirements-geometry.txt /tmp/requirements-geometry.txt
RUN python3 -m pip install --no-cache-dir --break-system-packages \
--default-timeout="${PIP_DEFAULT_TIMEOUT}" \
--retries 10 \
-i "${PIP_INDEX_URL}" \
-r /tmp/requirements-geometry.txt \
&& rm /tmp/requirements-geometry.txt \
&& python3 -c "import cadquery; print('cadquery OK')"
# 安装 Miniforge(conda-forge 原生,无 Anaconda ToS 限制)用于 pythonocc-core
ARG CONDA_INSTALLER_URL=https://mirrors.tuna.tsinghua.edu.cn/github-release/conda-forge/miniforge/LatestRelease/Miniforge3-Linux-x86_64.sh
RUN curl -fsSL "${CONDA_INSTALLER_URL}" -o /tmp/miniforge.sh \
&& bash /tmp/miniforge.sh -b -p /opt/conda \
&& rm /tmp/miniforge.sh \
&& PY_VER=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") \
&& /opt/conda/bin/conda config --set channel_priority strict \
&& /opt/conda/bin/conda create -y -n occ python="${PY_VER}" pythonocc-core=7.9.3 -c conda-forge \
&& /opt/conda/bin/conda clean -afy
RUN PY_VER=$(python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") \
&& CONDA_SP="/opt/conda/envs/occ/lib/python${PY_VER}/site-packages" \
&& SYS_SP=$(python3 -c "import site; print(site.getsitepackages()[0])") \
&& ln -sf "${CONDA_SP}/OCC" "${SYS_SP}/OCC"
# conda-forge 编译的 .so 需要新版 libstdc++(CXXABI_1.3.15);
# 动态查找 conda 提供的最新真实文件,避免硬编码版本号或双重软链问题
RUN set -eux \
&& LIBSTDCPP=$(ls /opt/conda/lib/libstdc++.so.6.0.* 2>/dev/null | sort -V | tail -1) \
&& [ -n "$LIBSTDCPP" ] && ln -sf "$LIBSTDCPP" /usr/lib/x86_64-linux-gnu/libstdc++.so.6 \
&& echo "libstdc++ -> $LIBSTDCPP" \
&& python3 -c "from OCC.Core.STEPControl import STEPControl_Reader; print('pythonocc-core OK')" \
&& python3 -c "from OCC.Core.BRep import BRep_Builder; print('OCC BRep OK')"
ENV PYTHON3_PATH=/usr/bin/python3
# 创建非 root 用户(bookworm 用 groupadd/useradd)
RUN groupadd --gid 1001 nodejs && \
useradd --uid 1001 --gid nodejs --system --shell /usr/sbin/nologin appuser
# 安装pnpm (用于运行时)
RUN corepack enable && corepack prepare pnpm@latest --activate
# 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/drizzle ./drizzle
# STEP 装配检测:子进程脚本(runStepParseMvp 从 dist 相对定位 ../scripts)
COPY --from=builder /app/scripts ./scripts
# 通用算法插件(Route B):manifests / Python 适配器 / mock fixtures。
# registry.ts 通过 PLUGIN_DIR 环境变量定位;默认从 dist/plugins/ 加载。
COPY --from=builder /app/server/plugins ./dist/plugins
ENV PLUGIN_DIR=/app/dist/plugins
# 创建日志目录
RUN mkdir -p /app/logs && chown -R appuser:nodejs /app
# 切换到非root用户
USER appuser
# 暴露端口
EXPOSE 3000
# 健康检查 (使用环境变量中的端口,默认3000)
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:${PORT:-3000}/api/health || exit 1
# 使用dumb-init作为PID 1进程
ENTRYPOINT ["dumb-init", "--"]
# 启动应用
CMD ["node", "dist/index.js"]