# Stage 1: Build frontend (use Debian-based node to avoid Alpine musl/rollup issues) FROM node:20 AS frontend-build WORKDIR /app/frontend ENV NODE_ENV=development COPY frontend/package*.json ./ RUN rm -f package-lock.json && npm install --legacy-peer-deps COPY frontend/ ./ RUN npm run build # Stage 2: Build backend FROM node:20 AS backend-build WORKDIR /app/backend ENV NODE_ENV=development COPY backend/package*.json ./ RUN npm install COPY backend/ ./ # Copy prisma schema for generation RUN npx prisma generate --schema=src/prisma/schema.prisma RUN npm run build # Stage 3: Production (Debian slim — same glibc as build, no musl/OpenSSL issues) FROM node:20-slim WORKDIR /app RUN apt-get update && apt-get install -y openssl curl --no-install-recommends && rm -rf /var/lib/apt/lists/* # Copy backend COPY --from=backend-build /app/backend/dist ./dist COPY --from=backend-build /app/backend/node_modules ./node_modules COPY --from=backend-build /app/backend/src/prisma ./prisma COPY backend/package.json ./package.json # Copy frontend build — served by Express at /app/public COPY --from=frontend-build /app/frontend/dist ./public COPY start.sh ./ RUN chmod +x start.sh EXPOSE 3000 CMD ["./start.sh"]