barsa bc5c7c9bd4 Update package dependencies, enhance Dockerfiles, and improve workspace configuration
- Added glob dependency to package.json and pnpm-lock.yaml for better file handling.
- Updated pnpm-workspace.yaml to include additional built dependencies for improved management.
- Refactored Dockerfiles for BFF and Portal to enhance security and optimize build processes.
- Improved entrypoint scripts to include better logging and readiness checks for services.
- Cleaned up TypeScript configuration files for consistency and alignment with project standards.
2025-12-10 16:31:18 +09:00

104 lines
3.7 KiB
Docker

# syntax=docker/dockerfile:1
# =============================================================================
# Portal (Next.js) Dockerfile
# =============================================================================
# Multi-stage build with standalone output for minimal image size
# Optimized for fast builds, security, and small production images
# =============================================================================
ARG NODE_VERSION=22
ARG PNPM_VERSION=10.25.0
# =============================================================================
# Stage 1: Dependencies (cached layer)
# =============================================================================
FROM node:${NODE_VERSION}-alpine AS deps
ARG PNPM_VERSION
# Install build dependencies
RUN apk add --no-cache libc6-compat \
&& corepack enable \
&& corepack prepare pnpm@${PNPM_VERSION} --activate
WORKDIR /app
# Copy manifests first for dependency caching
COPY .npmrc pnpm-workspace.yaml package.json pnpm-lock.yaml ./
COPY packages/domain/package.json ./packages/domain/
COPY apps/portal/package.json ./apps/portal/
# Install dependencies with cache mount (unique id per app for better caching)
ENV HUSKY=0
RUN --mount=type=cache,id=pnpm-portal,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile
# =============================================================================
# Stage 2: Builder
# =============================================================================
FROM deps AS builder
# Copy source files
COPY tsconfig.json tsconfig.base.json ./
COPY packages/domain/ ./packages/domain/
COPY apps/portal/ ./apps/portal/
# Build-time environment variables
ARG NEXT_PUBLIC_API_BASE=/api
ARG NEXT_PUBLIC_APP_NAME="Customer Portal"
ARG NEXT_PUBLIC_APP_VERSION=1.0.0
ENV NODE_ENV=production \
NEXT_PUBLIC_API_BASE=${NEXT_PUBLIC_API_BASE} \
NEXT_PUBLIC_APP_NAME=${NEXT_PUBLIC_APP_NAME} \
NEXT_PUBLIC_APP_VERSION=${NEXT_PUBLIC_APP_VERSION} \
NEXT_TELEMETRY_DISABLED=1
# Build: domain → Next.js (standalone output)
RUN pnpm --filter @customer-portal/domain build \
&& pnpm --filter @customer-portal/portal build
# =============================================================================
# Stage 3: Production
# =============================================================================
FROM node:${NODE_VERSION}-alpine AS production
LABEL org.opencontainers.image.title="Customer Portal Frontend" \
org.opencontainers.image.description="Next.js Customer Portal" \
org.opencontainers.image.vendor="Customer Portal"
# Minimal runtime dependencies + security hardening
RUN apk add --no-cache dumb-init libc6-compat \
&& addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs \
# Remove apk cache and unnecessary files
&& rm -rf /var/cache/apk/* /tmp/* /root/.npm
WORKDIR /app
# Copy standalone build artifacts with correct ownership
COPY --from=builder --chown=nextjs:nodejs /app/apps/portal/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/apps/portal/.next/static ./apps/portal/.next/static
COPY --from=builder --chown=nextjs:nodejs /app/apps/portal/public ./apps/portal/public
# Security: Run as non-root user
USER nextjs
# Expose frontend port
EXPOSE 3000
# Environment configuration
ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
PORT=3000 \
HOSTNAME="0.0.0.0" \
# Node.js production optimizations
NODE_OPTIONS="--max-old-space-size=512"
# Health check for container orchestration
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD node -e "fetch('http://localhost:3000/api/health').then(r=>r.ok||process.exit(1)).catch(()=>process.exit(1))"
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "apps/portal/server.js"]