Skip to contentPedro Farbo
Lesson 21 / 2555 min

Docker and Containers

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 down

Health 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! 🚀

Enjoyed the content? Your contribution helps keep everything online and free!

PIX:0737160d-e98f-4a65-8392-5dba70e7ff3e