All checks were successful
ci/woodpecker/push/ci Pipeline was successful
The .npmrc file contains supportedArchitectures settings to force pnpm to install glibc x64 binaries for native modules like matrix-sdk-crypto-nodejs. Without copying this file into the Docker image, pnpm defaults to the platform's native behavior which may skip or install incorrect binaries.
114 lines
4.3 KiB
Docker
114 lines
4.3 KiB
Docker
# Base image for all stages
|
|
# Uses Debian slim (glibc) instead of Alpine (musl) because native Node.js addons
|
|
# (matrix-sdk-crypto-nodejs, Prisma engines) require glibc-compatible binaries.
|
|
FROM git.mosaicstack.dev/mosaic/node-base:24-slim AS base
|
|
|
|
# Install pnpm globally
|
|
RUN corepack enable && corepack prepare pnpm@10.27.0 --activate
|
|
|
|
# Set working directory
|
|
WORKDIR /app
|
|
|
|
# Copy monorepo configuration files
|
|
COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./
|
|
COPY turbo.json ./
|
|
|
|
# ======================
|
|
# Dependencies stage
|
|
# ======================
|
|
FROM base AS deps
|
|
|
|
# Install build tools for native addons (node-pty requires node-gyp compilation)
|
|
# Note: openssl and ca-certificates pre-installed in base image
|
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
python3 make g++ \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Copy all package.json files for workspace resolution
|
|
COPY packages/shared/package.json ./packages/shared/
|
|
COPY packages/ui/package.json ./packages/ui/
|
|
COPY packages/config/package.json ./packages/config/
|
|
COPY apps/api/package.json ./apps/api/
|
|
|
|
# Copy npm configuration for native binary architecture hints
|
|
COPY .npmrc ./
|
|
|
|
# Install dependencies (no cache mount — Kaniko builds are ephemeral in CI)
|
|
# Then explicitly rebuild node-pty from source since pnpm may skip postinstall
|
|
# scripts or fail to find prebuilt binaries for this Node.js version
|
|
RUN pnpm install --frozen-lockfile \
|
|
&& cd node_modules/.pnpm/node-pty@*/node_modules/node-pty \
|
|
&& npx node-gyp rebuild 2>&1 || true
|
|
|
|
# ======================
|
|
# Builder stage
|
|
# ======================
|
|
FROM base AS builder
|
|
|
|
# Copy root node_modules from deps
|
|
COPY --from=deps /app/node_modules ./node_modules
|
|
|
|
# Copy all source code FIRST
|
|
COPY packages ./packages
|
|
COPY apps/api ./apps/api
|
|
|
|
# Then copy workspace node_modules from deps (these go AFTER source to avoid being overwritten)
|
|
COPY --from=deps /app/packages/shared/node_modules ./packages/shared/node_modules
|
|
COPY --from=deps /app/packages/config/node_modules ./packages/config/node_modules
|
|
COPY --from=deps /app/apps/api/node_modules ./apps/api/node_modules
|
|
|
|
# Build the API app and its dependencies using TurboRepo
|
|
# --force disables turbo cache to ensure fresh build from source
|
|
RUN pnpm turbo build --filter=@mosaic/api --force
|
|
|
|
# ======================
|
|
# Production stage
|
|
# ======================
|
|
FROM git.mosaicstack.dev/mosaic/node-base:24-slim AS production
|
|
|
|
# dumb-init, openssl, ca-certificates pre-installed in base image
|
|
|
|
# Single RUN to minimize Kaniko filesystem snapshots (each RUN = full snapshot)
|
|
# - Remove npm/npx to reduce image size (not used in production)
|
|
# - Create non-root user
|
|
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx \
|
|
&& groupadd -g 1001 nodejs && useradd -m -u 1001 -g nodejs nestjs
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy node_modules from builder (includes generated Prisma client in pnpm store)
|
|
# pnpm stores the Prisma client in node_modules/.pnpm/.../.prisma, so we need the full tree
|
|
COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules
|
|
|
|
# Copy built packages (includes dist/ directories)
|
|
COPY --from=builder --chown=nestjs:nodejs /app/packages ./packages
|
|
|
|
# Copy built API application
|
|
COPY --from=builder --chown=nestjs:nodejs /app/apps/api/dist ./apps/api/dist
|
|
COPY --from=builder --chown=nestjs:nodejs /app/apps/api/prisma ./apps/api/prisma
|
|
COPY --from=builder --chown=nestjs:nodejs /app/apps/api/package.json ./apps/api/
|
|
# Copy app's node_modules which contains symlinks to root node_modules
|
|
COPY --from=builder --chown=nestjs:nodejs /app/apps/api/node_modules ./apps/api/node_modules
|
|
|
|
# Copy entrypoint script (runs migrations before starting app)
|
|
COPY --from=builder --chown=nestjs:nodejs /app/apps/api/docker-entrypoint.sh ./apps/api/
|
|
|
|
# Set working directory to API app
|
|
WORKDIR /app/apps/api
|
|
|
|
# Switch to non-root user
|
|
USER nestjs
|
|
|
|
# Expose API port (default 3001, can be overridden via PORT env var)
|
|
EXPOSE ${PORT:-3001}
|
|
|
|
# Health check uses PORT env var (set by docker-compose or defaults to 3001)
|
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
|
|
CMD node -e "const port = process.env.PORT || 3001; require('http').get('http://localhost:' + port + '/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
|
|
|
|
# Use dumb-init to handle signals properly
|
|
ENTRYPOINT ["dumb-init", "--"]
|
|
|
|
# Run migrations then start the application
|
|
CMD ["sh", "docker-entrypoint.sh"]
|