# ============================================================================= # Stage 1: Builder # ============================================================================= FROM node:22-slim AS builder ARG APP_NAME=xhs-mcp ARG HTTP_PROXY ARG HTTPS_PROXY ENV HTTP_PROXY=${HTTP_PROXY} \ HTTPS_PROXY=${HTTPS_PROXY} RUN corepack enable RUN pnpm config set registry https://registry.npmmirror.com WORKDIR /app # Copy manifests first for better caching COPY pnpm-workspace.yaml package.json pnpm-lock.yaml tsconfig.json tsconfig.base.json ./ COPY packages/core/package.json packages/core/tsconfig.json packages/core/tsup.config.ts ./packages/core/ COPY apps/xhs-mcp/package.json apps/xhs-mcp/tsconfig.json apps/xhs-mcp/tsup.config.ts ./apps/xhs-mcp/ COPY apps/xhh-mcp/package.json apps/xhh-mcp/tsconfig.json apps/xhh-mcp/tsup.config.ts ./apps/xhh-mcp/ RUN pnpm install --frozen-lockfile # Install Chromium matching rebrowser-playwright version (NOT playwright) RUN npx rebrowser-playwright install chromium # Copy source code COPY packages ./packages COPY apps ./apps # Build shared core first, then selected app RUN pnpm --filter @social/core build RUN pnpm --filter @social/${APP_NAME} build # ============================================================================= # Stage 2: Runtime # ============================================================================= FROM node:22-slim ARG APP_NAME=xhs-mcp ARG HTTP_PROXY ARG HTTPS_PROXY ENV HTTP_PROXY=${HTTP_PROXY} \ HTTPS_PROXY=${HTTPS_PROXY} RUN sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \ sed -i 's|deb.debian.org|mirrors.aliyun.com|g' /etc/apt/sources.list 2>/dev/null || true # Chromium runtime dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ libnss3 \ libnspr4 \ libatk1.0-0 \ libatk-bridge2.0-0 \ libcups2 \ libdrm2 \ libdbus-1-3 \ libxkbcommon0 \ libxcomposite1 \ libxdamage1 \ libxfixes3 \ libxrandr2 \ libgbm1 \ libpango-1.0-0 \ libcairo2 \ libasound2 \ libatspi2.0-0 \ libwayland-client0 \ fonts-noto-cjk \ && rm -rf /var/lib/apt/lists/* RUN groupadd --gid 1001 appuser \ && useradd --uid 1001 --gid appuser --shell /bin/sh --create-home appuser WORKDIR /app COPY --from=builder --chown=appuser:appuser /app/package.json ./package.json COPY --from=builder --chown=appuser:appuser /app/pnpm-workspace.yaml ./pnpm-workspace.yaml COPY --from=builder --chown=appuser:appuser /app/node_modules ./node_modules COPY --from=builder --chown=appuser:appuser /app/packages ./packages COPY --from=builder --chown=appuser:appuser /app/apps ./apps COPY --from=builder --chown=appuser:appuser /root/.cache/ms-playwright /home/appuser/.cache/ms-playwright RUN mkdir -p /home/appuser/.social-mcp-xhs /home/appuser/.social-mcp-xhh \ && chown -R appuser:appuser /home/appuser/.social-mcp-xhs /home/appuser/.social-mcp-xhh USER appuser ENV HTTP_PROXY= \ HTTPS_PROXY= \ NODE_ENV=production \ HOST=0.0.0.0 \ PORT=9527 \ HEADLESS=true \ COOKIE_DIR=/home/appuser/.social-mcp-xhs \ APP_NAME=${APP_NAME} \ ALLOW_REMOTE=yes-i-understand-the-risk EXPOSE 9527 HEALTHCHECK --interval=30s --timeout=5s --retries=3 --start-period=10s \ CMD node -e "fetch('http://localhost:' + (process.env.PORT || '9527') + '/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))" CMD ["sh", "-lc", "node apps/${APP_NAME}/dist/main.js"]