Pular para o conteúdoPedro Farbo
Lição 21 / 2550 min

Docker e Containers

Docker e Containers

Docker garante que seu app rode igual em qualquer ambiente.

Dockerfile

dockerfile
# DockerfileFROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./RUN npm ci COPY . .RUN npm run build # Production imageFROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production # Cria usuário não-rootRUN addgroup --system --gid 1001 nodejsRUN adduser --system --uid 1001 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 # Gera Prisma ClientRUN npx prisma generate USER api EXPOSE 3000 CMD ["node", "dist/server.js"]

Docker Compose

yaml
# docker-compose.ymlversion: '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      - JWT_SECRET=${JWT_SECRET}    depends_on:      db:        condition: service_healthy      redis:        condition: service_started    restart: unless-stopped   db:    image: postgres:15-alpine    ports:      - "5432:5432"    environment:      - POSTGRES_USER=postgres      - POSTGRES_PASSWORD=postgres      - POSTGRES_DB=ecommerce    volumes:      - postgres_data:/var/lib/postgresql/data    healthcheck:      test: ["CMD-SHELL", "pg_isready -U postgres"]      interval: 5s      timeout: 5s      retries: 5   redis:    image: redis:7-alpine    ports:      - "6379:6379"    volumes:      - redis_data:/data    command: redis-server --appendonly yes   nginx:    image: nginx:alpine    ports:      - "80:80"      - "443:443"    volumes:      - ./nginx.conf:/etc/nginx/nginx.conf:ro      - ./certs:/etc/nginx/certs:ro    depends_on:      - api volumes:  postgres_data:  redis_data:

Docker Compose para Dev

yaml
# docker-compose.dev.ymlversion: '3.8' services:  api:    build:      context: .      dockerfile: Dockerfile.dev    ports:      - "3000:3000"    volumes:      - .:/app      - /app/node_modules    environment:      - NODE_ENV=development      - DATABASE_URL=postgresql://postgres:postgres@db:5432/ecommerce_dev      - REDIS_URL=redis://redis:6379    command: npm run dev   db:    image: postgres:15-alpine    ports:      - "5432:5432"    environment:      - POSTGRES_USER=postgres      - POSTGRES_PASSWORD=postgres      - POSTGRES_DB=ecommerce_dev   redis:    image: redis:7-alpine    ports:      - "6379:6379"
dockerfile
# Dockerfile.devFROM node:20-alpine WORKDIR /app COPY package*.json ./RUN npm install COPY . . EXPOSE 3000 CMD ["npm", "run", "dev"]

Nginx como Reverse Proxy

nginx
# nginx.confevents {    worker_connections 1024;} http {    upstream api {        server api:3000;    }     server {        listen 80;        server_name api.ecommerce.com;         location / {            proxy_pass http://api;            proxy_http_version 1.1;            proxy_set_header Upgrade $http_upgrade;            proxy_set_header Connection 'upgrade';            proxy_set_header Host $host;            proxy_set_header X-Real-IP $remote_addr;            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;            proxy_set_header X-Forwarded-Proto $scheme;            proxy_cache_bypass $http_upgrade;        }    }}

Comandos Úteis

bash
# Build e startdocker-compose up --build # Backgrounddocker-compose up -d # Logsdocker-compose logs -f api # Executar migrationsdocker-compose exec api npx prisma migrate deploy # Shell no containerdocker-compose exec api sh # Parar tudodocker-compose down # Parar e remover volumesdocker-compose down -v

.dockerignore

node_modules
dist
.git
.env
.env.local
*.log
coverage
.nyc_output

Health Check na API

typescript
// src/routes/health.routes.tsimport { Router } from 'express';import { prisma } from '../config/database';import redis from '../config/redis'; const router = Router(); router.get('/health', async (req, res) => {  const health = {    status: 'ok',    timestamp: new Date().toISOString(),    services: {      database: 'ok',      redis: 'ok',    },  };   try {    await prisma.$queryRaw`SELECT 1`;  } catch {    health.services.database = 'error';    health.status = 'degraded';  }   try {    await redis.ping();  } catch {    health.services.redis = 'error';    health.status = 'degraded';  }   const statusCode = health.status === 'ok' ? 200 : 503;  res.status(statusCode).json(health);}); export default router;

Resumo

  • ✅ Dockerfile multi-stage otimizado
  • ✅ Docker Compose para todos os serviços
  • ✅ Ambiente de desenvolvimento com hot reload
  • ✅ Nginx como reverse proxy
  • ✅ Health checks

Próxima aula: Deploy em Produção! 🚀

Gostou do conteúdo? Sua contribuição ajuda a manter tudo online e gratuito!

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