AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Deploy Docker

skill-felvieira-claude-skills-fv-07-deploy-docker · by felvieira

|

No reviews yet
0 installs
30 views
0.0% view→install

Install

$ agentstack add skill-felvieira-claude-skills-fv-07-deploy-docker

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-felvieira-claude-skills-fv-07-deploy-docker)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Deploy Docker? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Deployer - Dockerização e Deploy

O Deployer é o último passo. Recebe código aprovado pelo security review e coloca em produção.

Governanca Global

Esta skill segue GLOBAL.md, policies/execution.md, policies/handoffs.md, policies/quality-gates.md, policies/token-efficiency.md, policies/stack-flexibility.md, policies/tool-safety.md e policies/evals.md.

Para exemplos completos de Dockerfile, compose, CI/CD e estrategias de release, consultar docs/skill-guides/deploy-docker.md apenas quando necessario.

Quando Usar

  • empacotar, publicar ou promover mudanca entre ambientes
  • configurar pipeline, health check, rollback ou release strategy

Quando Nao Usar

  • para validar codigo de negocio como atividade principal
  • para executar acao externa de alto risco sem aprovacao

Entradas Esperadas

  • artefatos aprovados por QA, Security e Reviewer
  • requisitos de ambiente, health check e rollback
  • restricoes operacionais e de observabilidade

Saidas Esperadas

  • estrategia de deploy clara
  • configuracao de build/release coerente
  • handoff operacional curto para execucao ou monitoramento

Responsabilidades

  1. Dockerizar a aplicação (front + back + banco)
  2. Configurar CI/CD pipeline
  3. Gerenciar ambientes (dev, staging, prod)
  4. Configurar reverse proxy (nginx/Traefik)
  5. SSL/TLS com certbot
  6. Monitoramento e logs
  7. Rollback strategy

Estrategia Base de Deploy

  • builds reproduziveis e multi-stage quando fizer sentido
  • imagens minimas e sem secrets embutidos
  • health checks, rollback e monitoramento antes de promover release
  • aprovacao explicita para acoes em producao seguindo policies/tool-safety.md

Para exemplos completos de Dockerfile, compose e pipelines, consultar docs/skill-guides/deploy-docker.md.

Infrastructure as Code (IaC)

Tratar infraestrutura como código: o estado de servidores, redes e recursos cloud vive em arquivos versionados, revisáveis e reproduzíveis — nunca em passos manuais ou conhecimento tribal. Os princípios abaixo são atemporais (destilados de "DevOps na prática", Casa do Código); o ferramental moderno (Terraform, OpenTofu, Ansible, Pulumi) substitui o ferramental datado da literatura original (Puppet, Vagrant, Chef).

Princípios (atemporais)

  1. Provisionamento declarativo, não imperativo. Não escreva "instale o pacote X". Declare o estado final desejado — "o pacote X deve estar instalado", "deve existir uma VM com este tamanho". A ferramenta calcula o diff entre o estado atual e o declarado e aplica só o necessário. O arquivo descreve o destino, não a sequência de passos.
  2. Idempotência. Aplicar o mesmo código N vezes converge sempre pro mesmo estado. Pacote já instalado não reinstala, serviço já rodando não reinicia. Isso distingue IaC de shell script proprietário, que normalmente só funciona na primeira execução (este kit já aplica idempotência pontual em ssl-init.sh — IaC é a mesma ideia no nível de servidor/infra inteira).
  3. Ambientes reproduzíveis. dev, staging e prod nascem do mesmo código, parametrizado por ambiente. "Funciona na minha máquina" deixa de existir porque a máquina é descrita em código. Server provisionado a partir de manifesto é descartável e recriável — gado, não bicho de estimação.
  4. Convergência por dependência, não por ordem de linha. O grafo de dependências entre recursos (banco antes da app, config antes do restart) é declarado explicitamente. Mudança em config notifica e dispara o restart do serviço dependente.
  5. Combater drift. Drift é a divergência entre o estado declarado e o real (alguém deu ssh e mudou à mão). IaC detecta e corrige drift reaplicando o estado declarado. Mudança em produção que não passa pelo código é dívida — o próximo apply a reverte ou o plan a denuncia.
  6. Reuso de módulos. Padrões de infra (web server, banco, VPC) viram módulos parametrizados e versionados, não copy-paste. Equivalente moderno do Puppet Forge: Terraform Registry, Ansible Galaxy.

Mapeamento ferramental (livro datado → moderno)

| Conceito do livro | Ferramenta datada | Equivalente moderno | |---|---|---| | Provisionar VM / recurso cloud | Vagrant + VirtualBox | Terraform / OpenTofu / Pulumi | | Configuration management (estado do SO/serviços) | Puppet, Chef | Ansible (agentless), cloud-init | | Manifesto / recurso declarativo | .pp (Puppet) | .tf (HCL), playbook YAML | | Reuso comunitário | Puppet Forge | Terraform Registry, Ansible Galaxy | | Idempotência | core do Puppet | core de Terraform (plan/apply) e Ansible |

Regra de bolso atual: Terraform/OpenTofu provisiona (cria VM, rede, bucket, cluster); Ansible configura (instala pacote, ajusta arquivo, sobe serviço). Em ambiente totalmente container/Kubernetes, boa parte do config management migra pro Dockerfile + manifesto K8s + GitOps (Argo CD / Flux) — o princípio declarativo é o mesmo, o apply muda de dono.

Fronteira de responsabilidade

  • IaC (esta skill, 07): forma da infra. Provisionar recursos, configurar SO e serviços base, garantir estado declarado e reproduzível. "Como o ambiente é construído e mantido idempotente."
  • Observabilidade / SRE (skill 20): saúde da infra em execução. Logs, métricas, SLO, probes, alertas. IaC declara o probe; a 20 define o que ele significa e o alerta.
  • Release orchestration (skill 24): promoção de versões de aplicação sobre a infra existente. O ciclo de vida do servidor (IaC) é mais lento que o da aplicação (release) — o mesmo servidor recebe dezenas de releases.

Em resumo: IaC constrói o palco (07), a 24 troca o ator em cena, a 20 vigia o espetáculo. Drift de infra é da 07; degradação em runtime é da 20; deploy da versão errada é da 24.

Quando aplicar

  • ambiente novo (greenfield) onde servidores/recursos cloud precisam nascer reproduzíveis
  • divergência staging↔prod → codificar o ambiente
  • onboarding de servidor manual existente → importar pro estado declarado (terraform import)
  • suspeita de drift → plan/--check pra detectar antes de reaplicar

Para um único servidor descartável com docker-compose, IaC pesado é overkill — o compose já é declarativo no nível de containers. IaC entra quando a infra abaixo dos containers (VM, rede, DNS, certificado, cluster) também precisa ser versionada e recriável.

Dockerfile - Backend (Node.js/Express)

# Dockerfile.backend

FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --only=production

FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npx prisma generate
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production

RUN addgroup --system --gid 1001 nodejs && \
    adduser --system --uid 1001 appuser

COPY --from=builder --chown=appuser:nodejs /app/dist ./dist
COPY --from=builder --chown=appuser:nodejs /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:nodejs /app/prisma ./prisma
COPY --from=builder /app/package.json ./

USER appuser

EXPOSE 3001

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1

CMD ["sh", "-c", "npx prisma migrate deploy && node dist/server.js"]

Docker Compose - Ambiente Completo

# docker-compose.yml
version: '3.8'

services:
  # ── Frontend ──
  frontend:
    build:
      context: ./frontend
      dockerfile: Dockerfile.frontend
      args:
        NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
        NEXT_PUBLIC_APP_URL: ${NEXT_PUBLIC_APP_URL}
    restart: unless-stopped
    ports:
      - "3000:3000"
    depends_on:
      backend:
        condition: service_healthy
    networks:
      - app-network
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'

  # ── Backend ──
  backend:
    build:
      context: ./backend
      dockerfile: Dockerfile.backend
    restart: unless-stopped
    ports:
      - "3001:3001"
    env_file:
      - ./backend/.env
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - app-network
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: '0.5'

  # ── PostgreSQL ──
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app-network
    deploy:
      resources:
        limits:
          memory: 256M

  # ── Redis ──
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    ports:
      - "6379:6379"
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - app-network

  # ── Nginx Reverse Proxy ──
  nginx:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - certbot_data:/etc/letsencrypt:ro
      - certbot_www:/var/www/certbot:ro
    depends_on:
      - frontend
      - backend
    networks:
      - app-network

  # ── Certbot SSL ──
  certbot:
    image: certbot/certbot
    volumes:
      - certbot_data:/etc/letsencrypt
      - certbot_www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

volumes:
  postgres_data:
  redis_data:
  certbot_data:
  certbot_www:

networks:
  app-network:
    driver: bridge

Nginx Configuration

# nginx/conf.d/app.conf

upstream frontend {
    server frontend:3000;
}

upstream backend {
    server backend:3001;
}

# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

server {
    listen 80;
    server_name seudominio.com;
    
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    
    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    server_name seudominio.com;
    
    ssl_certificate /etc/letsencrypt/live/seudominio.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/seudominio.com/privkey.pem;
    
    # SSL hardening
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:10m;
    
    # Security headers
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    # Gzip
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml;
    gzip_min_length 1000;
    
    # Frontend
    location / {
        proxy_pass http://frontend;
        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;
    }
    
    # Backend API
    location /api/ {
        limit_req zone=api burst=20 nodelay;
        
        proxy_pass http://backend;
        proxy_http_version 1.1;
        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;
    }
    
    # Login rate limit mais agressivo
    location /api/v1/auth/login {
        limit_req zone=login burst=3 nodelay;
        
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
    
    # Bloqueia acesso direto ao Prisma Studio, etc
    location ~ /_(next|prisma) {
        deny all;
    }
}

CI/CD - GitHub Actions

# .github/workflows/deploy.yml
name: CI/CD Pipeline

on:
  push:
    branches: [main, staging]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  # ── Lint & Type Check ──
  quality:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run lint
      - run: npm run type-check

  # ── Unit Tests ──
  test-unit:
    needs: quality
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npm run test:coverage
      - uses: actions/upload-artifact@v4
        with:
          name: coverage-report
          path: coverage/

  # ── E2E Tests ──
  test-e2e:
    needs: quality
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npm run test:e2e
      - uses: actions/upload-artifact@v4
        if: failure()
        with:
          name: playwright-report
          path: playwright-report/

  # ── Security Audit ──
  security:
    needs: quality
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm audit --audit-level=high
      - uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          severity: 'CRITICAL,HIGH'

  # ── Build & Push Docker ──
  build:
    needs: [test-unit, test-e2e, security]
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4
      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: |
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
            ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

  # ── Deploy ──
  deploy-staging:
    needs: build
    if: github.ref == 'refs/heads/staging'
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Deploy to staging
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.STAGING_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          key: ${{ secrets.DEPLOY_KEY }}
          script: |
            cd /app
            docker compose pull
            docker compose up -d --force-recreate
            docker compose exec backend npx prisma migrate deploy
            docker system prune -f

  deploy-production:
    needs: build
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy to production
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.PROD_HOST }}
          username: ${{ secrets.DEPLOY_USER }}
          ke

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [felvieira](https://github.com/felvieira)
- **Source:** [felvieira/claude-skills-fv](https://github.com/felvieira/claude-skills-fv)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.