diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..aef3611 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,53 @@ +# Dependencies +node_modules +npm-debug.log + +# Build output +dist + +# Environment files +.env +.env.* +!.env.example + +# IDE +.idea +.vscode +*.swp +*.swo + +# OS +.DS_Store +Thumbs.db + +# Git +.git +.gitignore + +# Docker +Dockerfile +docker-compose*.yml +.dockerignore + +# Testing +coverage +.nyc_output +test +*.spec.ts +*.test.ts + +# Documentation +docs +*.md +!README.md + +# Logs +logs +*.log + +# Prisma +prisma/migrations + +# Misc +.eslintcache +.prettierignore diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a1769a3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,71 @@ +# =========================================== +# Backend Dockerfile (NestJS + Prisma) +# =========================================== + +# Stage 1: Build +FROM node:20-alpine AS builder + +WORKDIR /app + +# Install OpenSSL for Prisma +RUN apk add --no-cache openssl + +# Copy package files +COPY package*.json ./ +COPY prisma ./prisma/ + +# Install dependencies +RUN npm ci + +# Generate Prisma client +RUN npx prisma generate + +# Copy source code +COPY . . + +# Build the application +RUN npm run build + +# Compile the seed script +RUN npx tsc prisma/seed.ts --outDir dist/prisma --skipLibCheck --module commonjs --target es2020 + +# Stage 2: Production +FROM node:20-alpine AS production + +WORKDIR /app + +# Install OpenSSL for Prisma +RUN apk add --no-cache openssl + +# Create non-root user +RUN addgroup -g 1001 -S nodejs && \ + adduser -S nestjs -u 1001 + +# Copy package files +COPY package*.json ./ + +# Install production dependencies only +RUN npm ci --only=production + +# Copy Prisma schema and generate client +COPY prisma ./prisma/ +RUN npx prisma generate + +# Copy built application from builder stage +COPY --from=builder /app/dist ./dist + +# Set ownership +RUN chown -R nestjs:nodejs /app + +# Switch to non-root user +USER nestjs + +# Expose port +EXPOSE 3001 + +# Health check +HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ + CMD wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1 + +# Start the application +CMD ["node", "dist/main"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6f4580e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,47 @@ +# =========================================== +# Backend Docker Compose (Development) +# =========================================== + +services: + # =========================================== + # PostgreSQL Database + # =========================================== + postgres: + image: postgres:16-alpine + container_name: re-postgres + restart: unless-stopped + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: real_estate + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5432:5432" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + + # =========================================== + # Redis Cache + # =========================================== + redis: + image: redis:7-alpine + container_name: re-redis + restart: unless-stopped + command: redis-server --appendonly yes + volumes: + - redis_data:/data + ports: + - "6379:6379" + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + postgres_data: + redis_data: