⚡ AutomationsAI|Portal de Cursos →

Verificando acesso...

MÓDULO 2.2

🚀 Setup com Docker Compose

Subir o Postiz do zero em 50 minutos: ambiente, compose.yml, variáveis, primeiro boot, diagnóstico e smoke test.

6
Tópicos
50
Minutos
Intermediário
Nível
Prático
Tipo
1

📋 Preparando o ambiente

Antes de qualquer docker compose up, confirme que o host tem o que precisa: Docker Engine 24+ e Compose v2. Compose v1 (docker-compose com hífen) está deprecado e não suporta features que o Postiz usa.

Rode os dois comandos abaixo. Se falhar, instale via docs oficiais — nunca via apt install docker.io em distros antigas, vem desatualizado.

# Verificar runtime
docker --version
# Docker version 27.3.1, build ce12230

docker compose version
# Docker Compose version v2.29.7

# Criar diretório de trabalho
mkdir -p ~/postiz && cd ~/postiz
mkdir -p data/postgres data/uploads
touch docker-compose.yml .env .env.example

💡 Dica prática

Adicione seu usuário ao grupo docker (sudo usermod -aG docker $USER) e faça logout. Isso evita ter que escrever sudo antes de cada comando — e impede o reflexo perigoso de rodar containers como root.

Conceitos-chave

Docker Engine

Runtime de containers que executa as imagens.

Compose v2

Plugin nativo (docker compose, sem hífen).

Isolamento

Cada serviço roda em seu container com FS e rede isolados.

Idempotência

Rodar up várias vezes converge ao mesmo estado.

2

📄 Escrevendo o docker-compose.yml

O stack mínimo do Postiz tem três serviços: a aplicação Postiz (Node + Next), o Postgres (persistência de posts/contas) e o Redis (filas BullMQ que disparam o agendamento). Sem o Redis nada agenda; sem o Postgres nada persiste.

Use volumes nomeados (não bind mounts para dados de banco) e uma network interna para que Postgres/Redis nunca fiquem expostos no host.

# ~/postiz/docker-compose.yml
services:
  postiz:
    image: ghcr.io/gitroomhq/postiz-app:latest
    container_name: postiz
    restart: unless-stopped
    env_file: .env
    ports:
      - "5000:5000"
    volumes:
      - postiz-uploads:/uploads
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks: [postiz-net]

  postgres:
    image: postgres:16-alpine
    container_name: postiz-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: postiz
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: postiz
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postiz"]
      interval: 5s
      timeout: 5s
      retries: 10
    networks: [postiz-net]

  redis:
    image: redis:7-alpine
    container_name: postiz-redis
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      retries: 10
    networks: [postiz-net]

volumes:
  postgres-data:
  postiz-uploads:

networks:
  postiz-net:
    driver: bridge

Dica prática

Note o depends_on: condition: service_healthy. Sem isso, o Postiz tenta rodar migrations antes do Postgres aceitar conexão e morre no primeiro boot — o erro mais comum em setup novo.

Conceitos-chave

services

Cada bloco vira um container independente.

volumes

Persistem dados além do ciclo de vida do container.

networks

Bridge interna isola Postgres/Redis do host.

depends_on

Garante ordem de boot via healthcheck.

3

🔐 Variáveis de ambiente (.env)

O Postiz lê configuração via variáveis de ambiente — não tem arquivo de config. As essenciais para subir o stack são URLs (backend/frontend), conexões (Postgres/Redis), o JWT_SECRET e, opcionalmente, storage + Resend para e-mails.

# ~/postiz/.env (NUNCA commitar)
# URLs públicas — ajuste se for usar domínio
MAIN_URL=http://localhost:5000
FRONTEND_URL=http://localhost:5000
NEXT_PUBLIC_BACKEND_URL=http://localhost:5000/api
BACKEND_INTERNAL_URL=http://localhost:3000

# Segredo de assinatura JWT — GERE UM NOVO
JWT_SECRET=cole_aqui_o_resultado_de_openssl_rand_hex_64

# Banco e fila (host = nome do serviço no compose)
POSTGRES_PASSWORD=troque_essa_senha_forte
DATABASE_URL=postgresql://postiz:troque_essa_senha_forte@postgres:5432/postiz
REDIS_URL=redis://redis:6379

# Storage (local p/ começar; S3/R2 em prod)
STORAGE_PROVIDER=local

# E-mail transacional (opcional no dev)
RESEND_API_KEY=re_xxx_opcional_no_dev

Gere o JWT_SECRET com entropia real. Nunca invente uma string "parece aleatória" — o segredo assina os tokens de sessão de TODAS as contas conectadas.

# 64 bytes hex = 512 bits de entropia
openssl rand -hex 64

✓ O que FAZER

  • Manter .env.example no repo com chaves vazias.
  • Adicionar .env ao .gitignore imediatamente.
  • Usar nomes de serviço (postgres, redis) como host nas URLs.
  • Rotacionar JWT_SECRET se houver suspeita de vazamento.

✗ O que NÃO fazer

  • Commitar .env no git — mesmo "só por um minuto".
  • Reaproveitar JWT_SECRET entre projetos.
  • Apontar DATABASE_URL para localhost dentro do container.
  • Hardcodar segredos no docker-compose.yml.

Conceitos-chave

Secrets

Valores sensíveis nunca no código-fonte.

12-factor

Config via ambiente, código mesmo entre dev/prod.

env_file

Compose injeta as vars no container automaticamente.

Entropia

Aleatoriedade real, gerada por CSPRNG do SO.

4

▶️ Primeiro docker compose up

Com o .env preenchido e o docker-compose.yml salvo, o boot inicial é uma sequência de seis passos. Não pule a verificação de logs — é onde aparecem os erros silenciosos de configuração.

1

Baixar imagens

Pré-baixar evita race entre pull e start no up.

docker compose pull
2

Subir em background

A flag -d destaca os containers do terminal.

docker compose up -d
3

Acompanhar boot

No primeiro boot, ver os logs do Postiz é obrigatório — migrations rodam aqui.

docker compose logs -f postiz
4

Confirmar containers

Os três serviços devem aparecer com status Up e healthcheck healthy.

docker compose ps
5

Aguardar healthcheck

Postgres leva 5-15s. Redis quase instantâneo. Postiz só sobe depois.

docker compose ps --format "{{.Name}}\t{{.Status}}"
6

Abrir no browser

Se a tela de signup aparecer, o stack está saudável.

xdg-open http://localhost:5000

⏱️ Dica prática

Use -d para detach, mas sempre acompanhe logs -f postiz no primeiro boot. As migrations do Prisma rolam aqui e qualquer erro de DATABASE_URL aparece nos primeiros 10 segundos.

Conceitos-chave

Detached mode

Containers seguem rodando após fechar o terminal.

Logs

Stream do stdout/stderr dos containers.

Healthcheck

Sonda que confirma o serviço pronto para tráfego.

Port mapping

5000:5000 expõe a porta do container no host.

5

🔍 Diagnóstico quando algo dá errado

Quase todo problema de setup do Postiz cai em quatro famílias. Antes de googlar o stack trace, leia os logs — eles dizem qual família é.

📊 Problemas comuns no primeiro boot

  • Porta 5000 ocupada: outro serviço já segura a porta. Confirme com lsof -i :5000 e mude o mapeamento para 8080:5000.
  • Postgres não sobe: volume corrompido de boot anterior ou senha trocada. docker compose logs postgres mostra o motivo exato.
  • Redis connection refused: a aplicação está num network diferente ou REDIS_URL aponta para localhost em vez de redis.
  • Permission denied em volume: bind mount com dono errado. Use volume nomeado ou faça chown com o UID do container.
# Logs de um serviço específico (últimas 100 linhas)
docker compose logs --tail=100 postiz

# Status detalhado de todos os containers
docker compose ps -a

# Entrar no Postgres para inspecionar
docker exec -it postiz-postgres psql -U postiz -d postiz -c "\dt"

# Testar conexão Redis de dentro do container Postiz
docker exec -it postiz sh -c "nc -zv redis 6379"

# Reset completo (APAGA volumes — só em dev!)
docker compose down -v

✓ O que FAZER

  • Ler os logs SEMPRE antes de googlar o erro.
  • Usar down -v para reset completo em dev.
  • Conferir docker compose config para ver o YAML resolvido.
  • Isolar o problema: subir Postgres sozinho, depois Redis, depois Postiz.

✗ O que NÃO fazer

  • Apagar volumes em produção sem backup recente.
  • Rodar containers como root (user: root).
  • "Restart até funcionar" sem ler nenhuma linha de log.
  • Editar .env e esquecer de up -d de novo.

Conceitos-chave

logs

Stdout/stderr do processo principal do container.

exec

Roda um comando dentro de um container ativo.

Exit codes

0 ok; 1+ erro; 137 = OOM kill.

Troubleshooting

Isolar variáveis, reproduzir, ler logs, hipótese.

6

✅ Verificando que subiu

"Container Up" não é o mesmo que "aplicação funciona". Faça um smoke test de seis pontos antes de declarar vitória.

1

Browser em http://localhost:5000

A página deve carregar — não um erro de conexão recusada, não um 502, não branco.

2

Tela de signup aparece

Sem ela, o frontend não conseguiu falar com o backend — confirme NEXT_PUBLIC_BACKEND_URL.

3

Criar conta admin

O primeiro usuário cadastrado vira admin. Se o POST falhar, o problema é Postgres (escrita).

4

Login funciona

Token JWT é gerado e persistido em cookie. Sessão deve sobreviver a F5.

5

UI carrega completa

Dashboard sem ícones quebrados e sem chamadas 500 no DevTools / Network.

6

Endpoint de health

Resposta 200 OK indica que app + DB + Redis estão saudáveis.

# Smoke test rápido via CLI
curl -i http://localhost:5000/api/health
# HTTP/1.1 200 OK
# {"status":"ok","db":"up","redis":"up"}

💾 Dica prática

Configure backup do volume postgres-data ANTES de adicionar contas reais de redes sociais. Os tokens OAuth ficam ali e regenerá-los é trabalhoso. docker run --rm -v postiz_postgres-data:/data -v $(pwd):/backup alpine tar czf /backup/pg-$(date +%F).tar.gz /data.

Conceitos-chave

Smoke test

Verificação rápida de que o sistema sobe e responde.

Health check

Endpoint que reporta saúde de dependências.

Primeiro acesso

Conta admin inicial — proteja com senha forte.

Próximos passos

Domínio, HTTPS, backup, primeira integração.

🎯 Resumo do Módulo

Ambiente preparado — Docker 24+ e Compose v2 confirmados, diretório ~/postiz criado.
docker-compose.yml escrito — três serviços (Postiz, Postgres, Redis), volumes nomeados e network isolada.
.env configurado — URLs, JWT_SECRET gerado com openssl rand, secrets fora do git.
Primeiro boot executadopull, up -d, logs acompanhados e containers healthy.
Diagnóstico dominado — sabe identificar porta ocupada, falha de DB, network e permissões.
Smoke test validado — signup, login, dashboard e /api/health respondendo 200.

Próximo Módulo:

2.3 — Configuração inicial e primeira conta conectada