Assist_Design/apps/bff/Dockerfile

113 lines
4.1 KiB
Docker
Raw Normal View History

# =============================================================================
# Backend (BFF) Dockerfile - Production Grade
# =============================================================================
# Uses Alpine throughout for consistent native module builds
# Uses pnpm prune instead of pnpm deploy to preserve Prisma client
# =============================================================================
2025-08-21 15:24:40 +09:00
ARG PNPM_VERSION=10.15.0
ARG NODE_VERSION=22
# =============================================================================
# Stage 1: Builder - Install, build, and prune for production
# =============================================================================
FROM node:${NODE_VERSION}-alpine AS builder
ARG PNPM_VERSION
# Install build dependencies for native modules (bcrypt, prisma)
RUN apk add --no-cache \
python3 make g++ pkgconfig openssl-dev libc6-compat \
&& corepack enable \
&& corepack prepare pnpm@${PNPM_VERSION} --activate
WORKDIR /app
# Copy workspace configuration first (better layer caching)
COPY .npmrc pnpm-workspace.yaml package.json pnpm-lock.yaml ./
COPY packages/domain/package.json ./packages/domain/
COPY packages/logging/package.json ./packages/logging/
2025-08-21 15:24:40 +09:00
COPY apps/bff/package.json ./apps/bff/
# Install all dependencies
ENV HUSKY=0
RUN pnpm install --frozen-lockfile
2025-08-21 15:24:40 +09:00
# Copy source code
COPY tsconfig.json tsconfig.base.json ./
COPY packages/ ./packages/
2025-08-21 15:24:40 +09:00
COPY apps/bff/ ./apps/bff/
# Build workspace packages
RUN pnpm --filter @customer-portal/domain build && \
pnpm --filter @customer-portal/logging build
# Generate Prisma client (for Alpine/musl)
RUN cd apps/bff && pnpm exec prisma generate
# Build BFF
RUN pnpm --filter @customer-portal/bff build
# Prune dev dependencies IN PLACE - this keeps .prisma/client intact
RUN pnpm prune --prod
# Remove unnecessary files to reduce image size
RUN rm -rf /app/packages/*/src /app/apps/bff/src \
/app/packages/*/*.ts /app/apps/bff/*.ts \
/app/**/*.map /app/**/*.tsbuildinfo \
/root/.local/share/pnpm/store
# =============================================================================
# Stage 2: Production - Minimal runtime image
# =============================================================================
FROM node:${NODE_VERSION}-alpine AS production
2025-08-21 15:24:40 +09:00
LABEL org.opencontainers.image.title="Customer Portal BFF" \
org.opencontainers.image.description="NestJS Backend-for-Frontend API" \
org.opencontainers.image.vendor="Customer Portal"
# Runtime dependencies only
RUN apk add --no-cache \
dumb-init wget openssl netcat-openbsd libc6-compat \
&& rm -rf /var/cache/apk/*
# Create non-root user
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nestjs
WORKDIR /app
# Copy pruned node_modules (includes .prisma/client)
COPY --from=builder --chown=nestjs:nodejs /app/node_modules ./node_modules
# Copy workspace package outputs
COPY --from=builder --chown=nestjs:nodejs /app/packages/domain/dist ./packages/domain/dist
COPY --from=builder --chown=nestjs:nodejs /app/packages/domain/package.json ./packages/domain/package.json
COPY --from=builder --chown=nestjs:nodejs /app/packages/logging/dist ./packages/logging/dist
COPY --from=builder --chown=nestjs:nodejs /app/packages/logging/package.json ./packages/logging/package.json
# Copy BFF
COPY --from=builder --chown=nestjs:nodejs /app/apps/bff/dist ./apps/bff/dist
COPY --from=builder --chown=nestjs:nodejs /app/apps/bff/prisma ./apps/bff/prisma
COPY --from=builder --chown=nestjs:nodejs /app/apps/bff/package.json ./apps/bff/package.json
# Copy entrypoint
COPY --chown=nestjs:nodejs apps/bff/scripts/docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod +x /app/docker-entrypoint.sh && \
mkdir -p /app/secrets /app/logs && \
chown nestjs:nodejs /app/secrets /app/logs
USER nestjs
EXPOSE 4000
ENV NODE_ENV=production PORT=4000
2025-08-21 15:24:40 +09:00
WORKDIR /app/apps/bff
2025-08-21 15:24:40 +09:00
HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:4000/health || exit 1
ENTRYPOINT ["dumb-init", "--", "/app/docker-entrypoint.sh"]
CMD ["node", "dist/main.js"]