Docker and Containers
Containerize your application with Docker.
Dockerfile
dockerfile
FROM node:20-alpine AS builderWORKDIR /appCOPY package*.json ./RUN npm ciCOPY . .RUN npm run build FROM node:20-alpine AS runnerWORKDIR /appENV NODE_ENV=production RUN addgroup --system nodejsRUN adduser --system api COPY --from=builder /app/dist ./distCOPY --from=builder /app/node_modules ./node_modulesCOPY --from=builder /app/package*.json ./COPY --from=builder /app/prisma ./prisma RUN npx prisma generateUSER apiEXPOSE 3000CMD ["node", "dist/server.js"]Docker Compose
yaml
version: '3.8' services: api: build: . ports: - "3000:3000" environment: - NODE_ENV=production - DATABASE_URL=postgresql://postgres:postgres@db:5432/ecommerce - REDIS_URL=redis://redis:6379 depends_on: - db - redis db: image: postgres:15-alpine environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - POSTGRES_DB=ecommerce volumes: - postgres_data:/var/lib/postgresql/data redis: image: redis:7-alpine volumes: - redis_data:/data volumes: postgres_data: redis_data:Commands
bash
# Build and startdocker-compose up --build # Backgrounddocker-compose up -d # Logsdocker-compose logs -f api # Run migrationsdocker-compose exec api npx prisma migrate deploy # Stopdocker-compose downHealth Check
typescript
router.get('/health', async (req, res) => { const health = { status: 'ok', services: {} }; try { await prisma.$queryRaw`SELECT 1`; health.services.database = 'ok'; } catch { health.services.database = 'error'; health.status = 'degraded'; } res.status(health.status === 'ok' ? 200 : 503).json(health);});Summary
- ✅ Multi-stage Dockerfile
- ✅ Docker Compose with all services
- ✅ Health checks
Next lesson: Production Deploy! 🚀