diff --git a/.dockerignore b/.dockerignore index 337be6f..30331cb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,14 +1,18 @@ -# Dependencies +# Following pnpm Docker best practices: https://pnpm.io/docker + +# Dependencies (will be installed in container) node_modules .pnpm-store -# Build outputs +# Build outputs (will be built in container) **/dist -**/build -**/.next -**/.nuxt -# Testing +# Git +.git +.gitignore +*.md + +# Testing (not needed in production) **/__tests__ **/*.test.ts **/*.test.js @@ -17,20 +21,11 @@ node_modules **/coverage **/.vitest -# Environment files -# Note: .env files in apps/api are included for container defaults -# Override at runtime with docker run -e or --env-file -!apps/api/.env* -**/.env -**/.env.* -!**/.env.example - # Development files **/*.log **/.DS_Store **/npm-debug.log* **/yarn-debug.log* -**/yarn-error.log* **/pnpm-debug.log* # IDE @@ -39,20 +34,9 @@ node_modules **/.vs **/*.swp **/*.swo -**/*~ - -# Git -.git -.gitignore -.gitattributes - -# Documentation (not needed in production image) -**/*.md -!**/README.md # CI/CD .github -**/.gitlab-ci.yml **/cloudbuild.yaml **/.circleci @@ -62,4 +46,6 @@ node_modules **/.cache **/tmp **/temp +**/.next +**/.nuxt diff --git a/apps/api/Dockerfile b/apps/api/Dockerfile index 7d465fd..773d0ee 100644 --- a/apps/api/Dockerfile +++ b/apps/api/Dockerfile @@ -3,76 +3,59 @@ # ============================================================================== # NOTE: This Dockerfile should be built from the monorepo root, not from apps/api # Build command: docker build -f apps/api/Dockerfile -t xtablo-api . -FROM node:20-alpine AS base +FROM node:20-slim AS base -# Build argument for NODE_ENV -ARG NODE_ENV=production +# Configure pnpm +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable -# Install security updates and pnpm -RUN apk --no-cache upgrade && \ - corepack enable && \ - corepack prepare pnpm@latest --activate - -# Create app directory and set up non-root user +# Copy all files to working directory +COPY . /app WORKDIR /app -RUN addgroup -g 1001 -S nodejs -RUN adduser -S nodejs -u 1001 - -# Copy workspace configuration and root package files -COPY pnpm-workspace.yaml package.json pnpm-lock.yaml ./ - -# Copy packages directory (shared packages) -COPY packages ./packages - -# Copy api app package.json -COPY apps/api/package.json ./apps/api/package.json - -# ============================================================================== -# Dependencies stage - Install all dependencies -# ============================================================================== -FROM base AS deps - -# Install all dependencies (including devDependencies for build) -# This installs dependencies for the entire workspace -RUN pnpm install --frozen-lockfile - -# ============================================================================== -# Build stage - Compile TypeScript -# ============================================================================== -FROM deps AS build - -# Copy api source code -COPY apps/api ./apps/api - -# Build the api application -WORKDIR /app/apps/api -RUN pnpm run build # ============================================================================== # Production dependencies stage - Install only production dependencies # ============================================================================== FROM base AS prod-deps +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile -# Install only production dependencies -RUN pnpm install --frozen-lockfile --prod && pnpm store prune +# ============================================================================== +# Build stage - Install all dependencies and build +# ============================================================================== +FROM base AS build +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile +# Build only the API and its dependencies +WORKDIR /app/apps/api +RUN pnpm run build # ============================================================================== # Final stage - Production image # ============================================================================== -FROM base AS final +FROM node:20-slim -# Copy built api application -COPY --from=build /app/apps/api/dist ./apps/api/dist -COPY --from=build /app/apps/api/package.json ./apps/api/package.json +# Configure pnpm +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable -# Copy shared packages (needed for workspace resolution) -COPY --from=prod-deps /app/packages ./packages +# Create non-root user +RUN groupadd --gid 1001 nodejs && \ + useradd -l --uid 1001 --gid nodejs --shell /bin/bash --create-home nodejs -# Install production dependencies -# This ensures proper symlink structure for pnpm -RUN pnpm install --frozen-lockfile --prod --filter @xtablo/api... +# Copy production dependencies from prod-deps stage +COPY --from=prod-deps /app/node_modules /app/node_modules +COPY --from=prod-deps /app/packages /app/packages -# Set working directory to api app +# Copy built application from build stage +COPY --from=build /app/apps/api/dist /app/apps/api/dist +COPY --from=build /app/apps/api/package.json /app/apps/api/package.json + +# Copy workspace files for proper resolution +COPY --from=build /app/pnpm-workspace.yaml /app/pnpm-workspace.yaml +COPY --from=build /app/package.json /app/package.json + +# Set working directory WORKDIR /app/apps/api # Change ownership to nodejs user @@ -85,5 +68,4 @@ USER nodejs EXPOSE 8080 # NODE_ENV will be set via Cloud Run environment variables -# Start the application CMD ["pnpm", "start"] \ No newline at end of file