sha256:11fd48bd73c899d5bcb4a7728810dbe7ae910e20f0db9e1fe799080bacefe38a
Last pushed
10 days by marlussantiago
Type
Compose
Manifest digest
sha256:11fd48bd73c899d5bcb4a7728810dbe7ae910e20f0db9e1fe799080bacefe38a
# Stack completa (publicada como artefato OCI no Docker Hub — ver scripts/publish.sh).
# ESTE ARQUIVO É PÚBLICO: nenhum segredo aqui. Segredos vêm só do .env (veja .env.example);
# os obrigatórios usam ${VAR:?} e o compose recusa subir sem eles.
# GLPI de teste (local): docker-compose.glpi.yml.
# Ambiente do Chatwoot (idêntico para web e worker)
x-chatwoot-env: &chatwoot-env
NODE_ENV: production
RAILS_ENV: production
INSTALLATION_ENV: docker
FRONTEND_URL: ${CHATWOOT_FRONTEND_URL:-http://localhost:3001}
SECRET_KEY_BASE: ${CHATWOOT_SECRET_KEY_BASE:?defina CHATWOOT_SECRET_KEY_BASE no .env (openssl rand -hex 64)}
DEFAULT_LOCALE: ${CHATWOOT_DEFAULT_LOCALE:-pt_BR}
ENABLE_ACCOUNT_SIGNUP: ${CHATWOOT_ENABLE_ACCOUNT_SIGNUP:-true}
# TLS é terminado no nginx; o Rails recebe HTTP + X-Forwarded-Proto
FORCE_SSL: "false"
RAILS_MAX_THREADS: ${CHATWOOT_RAILS_MAX_THREADS:-5}
RAILS_LOG_TO_STDOUT: "true"
LOG_LEVEL: ${CHATWOOT_LOG_LEVEL:-info}
ACTIVE_STORAGE_SERVICE: local
SAFE_FETCH_ALLOW_PRIVATE_NETWORK: "true"
# Limite do widget (5 aberturas/hora por IP sem conversa). Em dev, "false" evita o 429 ao recarregar a página
ENABLE_RACK_ATTACK_WIDGET_API: ${CHATWOOT_RACK_ATTACK_WIDGET:-true}
# Banco (local: support-db; externo: DB_HOST + role com search_path no schema do Chatwoot)
POSTGRES_HOST: ${DB_HOST:-support-db}
POSTGRES_PORT: ${DB_PORT:-5432}
POSTGRES_USERNAME: ${CHATWOOT_DB_USER:-${POSTGRES_USER:-support_user}}
POSTGRES_PASSWORD: ${CHATWOOT_DB_PASSWORD:-${POSTGRES_PASSWORD:-support_pass}}
POSTGRES_DATABASE: ${CHATWOOT_DB_NAME:-chatwoot_production}
# Redis (db 1; a Support API usa o db 0)
REDIS_URL: redis://support-redis:6379/1
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
# E-mail (convites, recuperação de senha, notificações).
# Sem SMTP_ADDRESS o Chatwoot usa sendmail, que não existe no container: nenhum e-mail sai.
MAILER_SENDER_EMAIL: ${CHATWOOT_MAILER_SENDER_EMAIL:-Suporte <suporte@localhost>}
SMTP_ADDRESS: ${SMTP_ADDRESS:-}
SMTP_PORT: ${SMTP_PORT:-587}
SMTP_DOMAIN: ${SMTP_DOMAIN:-}
SMTP_USERNAME: ${SMTP_USERNAME:-}
SMTP_PASSWORD: ${SMTP_PASSWORD:-}
SMTP_AUTHENTICATION: ${SMTP_AUTHENTICATION:-login}
SMTP_ENABLE_STARTTLS_AUTO: ${SMTP_ENABLE_STARTTLS_AUTO:-true}
services:
# ----------------------------------------------------
# Nginx: única porta pública (80 -> 443). Roteia por subdomínio:
# CHATWOOT_DOMAIN Chatwoot (+ /tascom-api/ Theme Studio, /tascom-painel/ Dashboard App)
# API_DOMAIN Support API
# MONITOR_DOMAIN Monitor (opcional; exige MONITOR_TOKEN)
# GLPI_DOMAIN GLPI de teste (opcional)
# ----------------------------------------------------
nginx:
image: marlussantiago/support-nginx:latest
build:
context: ./nginx
container_name: support-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
environment:
CHATWOOT_DOMAIN: ${CHATWOOT_DOMAIN:-chat.localhost}
API_DOMAIN: ${API_DOMAIN:-api.localhost}
MONITOR_DOMAIN: ${MONITOR_DOMAIN:-}
GLPI_DOMAIN: ${GLPI_DOMAIN:-}
CERT_NAME: ${CERT_NAME:-support}
volumes:
- certbot_conf:/etc/letsencrypt:ro
- certbot_www:/var/www/certbot:ro
depends_on:
- chatwoot
- api
- dashboard-app
- theme-studio
- monitor
networks:
- internal-net
# ----------------------------------------------------
# Certbot (Let's Encrypt automático): na subida emite/expande o certificado para
# os domínios públicos acima (desafio HTTP pelo nginx na porta 80) e renova a cada 12h.
# O nginx detecta o certificado novo em até 1 min e recarrega sozinho.
# Requer: DNS dos domínios apontando para o servidor, portas 80/443 abertas e LETSENCRYPT_EMAIL.
# ----------------------------------------------------
certbot:
image: marlussantiago/support-certbot:latest
build:
context: ./certbot
container_name: support-certbot
restart: unless-stopped
environment:
CHATWOOT_DOMAIN: ${CHATWOOT_DOMAIN:-chat.localhost}
API_DOMAIN: ${API_DOMAIN:-api.localhost}
MONITOR_DOMAIN: ${MONITOR_DOMAIN:-}
GLPI_DOMAIN: ${GLPI_DOMAIN:-}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL:-}
LETSENCRYPT_STAGING: ${LETSENCRYPT_STAGING:-0}
CERT_NAME: ${CERT_NAME:-support}
volumes:
- certbot_conf:/etc/letsencrypt
- certbot_www:/var/www/certbot
depends_on:
- nginx
networks:
- internal-net
api:
image: marlussantiago/support-api:latest
build:
context: ./api
container_name: glpi-api
restart: unless-stopped
ports:
- target: 3100
published: "${API_PORT:-3100}"
host_ip: 127.0.0.1
environment:
NODE_ENV: production
PORT: 3100
LOG_LEVEL: ${LOG_LEVEL:-info}
# GLPI (produção: GLPI externo; teste: docker-compose.glpi.yml)
GLPI_URL: ${GLPI_URL:-http://glpi:80/apirest.php}
GLPI_WEB_URL: ${GLPI_WEB_URL:-http://localhost:8080}
GLPI_APP_TOKEN: ${GLPI_APP_TOKEN:-}
GLPI_USERNAME: ${GLPI_USERNAME:-glpi}
GLPI_PASSWORD: ${GLPI_PASSWORD:-}
GLPI_USER_TOKEN: ${GLPI_USER_TOKEN:-}
# Persistência
DATABASE_URL: postgresql://${API_DB_USER:-${POSTGRES_USER:-support_user}}:${API_DB_PASSWORD:-${POSTGRES_PASSWORD:-support_pass}}@${DB_HOST:-support-db}:${DB_PORT:-5432}/${POSTGRES_DB:-support_db}?schema=${API_DB_SCHEMA:-public}
# Banco do Chatwoot (a API lê/atualiza conversas direto), com a mesma role do Chatwoot
CHATWOOT_DATABASE_URL: postgresql://${CHATWOOT_DB_USER:-${POSTGRES_USER:-support_user}}:${CHATWOOT_DB_PASSWORD:-${POSTGRES_PASSWORD:-support_pass}}@${DB_HOST:-support-db}:${DB_PORT:-5432}/${CHATWOOT_DB_NAME:-chatwoot_production}
REDIS_HOST: support-redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
# Chatwoot
CHATWOOT_BASE_URL: ${CHATWOOT_BASE_URL:-http://chatwoot:3000}
CHATWOOT_API_TOKEN: ${CHATWOOT_API_TOKEN:-}
CHATWOOT_WEBHOOK_SECRET: ${CHATWOOT_WEBHOOK_SECRET:-}
CHATWOOT_DB_NAME: ${CHATWOOT_DB_NAME:-chatwoot_production}
CHATWOOT_SUPPORT_INBOX_ID: ${CHATWOOT_SUPPORT_INBOX_ID:-1}
DISABLE_SIGNATURE_VERIFICATION: ${DISABLE_SIGNATURE_VERIFICATION:-false}
TRANSCRIPT_INCLUDE_PRIVATE_NOTES: ${TRANSCRIPT_INCLUDE_PRIVATE_NOTES:-false}
# Chave do Dashboard App do Chatwoot
DASHBOARD_APP_KEY: ${DASHBOARD_APP_KEY:?defina DASHBOARD_APP_KEY no .env (openssl rand -hex 24)}
depends_on:
support-db:
condition: service_healthy
required: false
support-redis:
condition: service_healthy
networks:
- internal-net
# ----------------------------------------------------
# PostgreSQL local da Support API (v2) e do Chatwoot (profile "local-db").
# Com banco externo (DB_HOST), tire "local-db" do COMPOSE_PROFILES.
# ----------------------------------------------------
support-db:
image: pgvector/pgvector:pg16
container_name: support-postgres
restart: unless-stopped
profiles: ["local-db"]
ports:
- target: 5432
published: "${POSTGRES_PORT:-5434}"
host_ip: 127.0.0.1
# Credenciais só são aplicadas na criação do volume support_pgdata
environment:
POSTGRES_USER: ${POSTGRES_USER:-support_user}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-support_pass}
POSTGRES_DB: ${POSTGRES_DB:-support_db}
volumes:
- support_pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-support_user} -d ${POSTGRES_DB:-support_db}"]
interval: 5s
timeout: 5s
retries: 10
networks:
- internal-net
# ----------------------------------------------------
# Redis para Filas Assíncronas (BullMQ) e Chatwoot
# ----------------------------------------------------
support-redis:
image: redis:7-alpine
container_name: support-redis
restart: unless-stopped
ports:
- target: 6379
published: "${REDIS_PORT:-6380}"
host_ip: 127.0.0.1
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
# Exige senha apenas quando REDIS_PASSWORD estiver definido
command: ["sh", "-c", "exec redis-server $${REDIS_PASSWORD:+--requirepass \"$$REDIS_PASSWORD\"}"]
volumes:
- support_redisdata:/data
healthcheck:
test: ["CMD-SHELL", "redis-cli $${REDIS_PASSWORD:+-a \"$$REDIS_PASSWORD\" --no-auth-warning} ping | grep -q PONG"]
interval: 5s
timeout: 5s
retries: 10
networks:
- internal-net
# ----------------------------------------------------
# Chatwoot Web & API (Atendimento Omnichannel N1)
# ----------------------------------------------------
chatwoot:
image: chatwoot/chatwoot:latest
container_name: chatwoot-web
restart: unless-stopped
ports:
- target: 3000
published: "${CHATWOOT_PORT:-3001}"
host_ip: 127.0.0.1
environment: *chatwoot-env
entrypoint: docker/entrypoints/rails.sh
# db:chatwoot_prepare é idempotente: cria o banco + seed na primeira subida
# (volume vazio) e apenas aplica migrations pendentes nas seguintes.
command: ["sh", "-c", "bundle exec rails db:chatwoot_prepare && exec bundle exec rails s -p 3000 -b 0.0.0.0"]
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000/api"]
interval: 10s
timeout: 5s
start_period: 180s
retries: 30
depends_on:
support-db:
condition: service_healthy
required: false
support-redis:
condition: service_healthy
# O theme-studio cria o volume tascom_theme com dono "node" (precisa subir antes)
theme-studio:
condition: service_started
volumes:
- chatwoot_data:/app/storage
# Tema Tascom (loader.js, theme.css, studio.html, logos), gravado pelo theme-studio
- tascom_theme:/app/public/tascom:ro
networks:
- internal-net
# ----------------------------------------------------
# Chatwoot Worker (Processamento em segundo plano)
# ----------------------------------------------------
chatwoot-worker:
image: chatwoot/chatwoot:latest
container_name: chatwoot-worker
restart: unless-stopped
environment: *chatwoot-env
entrypoint: docker/entrypoints/rails.sh
command: ["bundle", "exec", "sidekiq", "-C", "config/sidekiq.yml"]
depends_on:
chatwoot:
condition: service_healthy
support-db:
condition: service_healthy
required: false
support-redis:
condition: service_healthy
volumes:
- chatwoot_data:/app/storage
networks:
- internal-net
# ----------------------------------------------------
# Dashboard App "Chamados GLPI" (aba dentro da conversa do Chatwoot)
# Só a tela: repassa as chamadas para /dashboard-app/api da Support API.
# URL no Chatwoot: https://<CHATWOOT_DOMAIN>/tascom-painel/dashboard-app?key=<DASHBOARD_APP_KEY>
# ----------------------------------------------------
dashboard-app:
image: marlussantiago/support-dashboard-app:latest
build:
context: ./dashboard-app
container_name: tascom-dashboard-app
restart: unless-stopped
ports:
- target: 8080
published: "${DASHBOARD_APP_PORT:-3015}"
host_ip: 127.0.0.1
environment:
BACKEND_URL: http://api:3100/dashboard-app/api
BACKEND_TIMEOUT: 120
depends_on:
- api
networks:
- internal-net
# ----------------------------------------------------
# Theme Studio (tema, marca e scripts do painel do Chatwoot)
# Página: https://<CHATWOOT_DOMAIN>/tascom/studio.html — API: /tascom-api/ (nginx)
# ----------------------------------------------------
theme-studio:
image: marlussantiago/support-theme-studio:latest
build:
context: ./theme-studio
container_name: tascom-theme-studio
restart: unless-stopped
ports:
- target: 3014
published: "${STUDIO_PORT:-3014}"
host_ip: 127.0.0.1
environment:
PORT: 3014
# Origem do Chatwoot autorizada a chamar a API (via nginx é mesma origem)
ALLOWED_ORIGIN: ${CHATWOOT_FRONTEND_URL:-http://localhost:3001}
STUDIO_TOKEN: ${STUDIO_TOKEN:?defina STUDIO_TOKEN no .env (openssl rand -hex 24)}
# Mesmo banco/Redis do Chatwoot (installation_configs + cache GlobalConfig)
POSTGRES_HOST: ${DB_HOST:-support-db}
POSTGRES_PORT: ${DB_PORT:-5432}
POSTGRES_DATABASE: ${CHATWOOT_DB_NAME:-chatwoot_production}
POSTGRES_USERNAME: ${CHATWOOT_DB_USER:-${POSTGRES_USER:-support_user}}
POSTGRES_PASSWORD: ${CHATWOOT_DB_PASSWORD:-${POSTGRES_PASSWORD:-support_pass}}
REDIS_URL: redis://support-redis:6379/1
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
volumes:
- tascom_theme:/data
depends_on:
support-db:
condition: service_healthy
required: false
support-redis:
condition: service_healthy
networks:
- internal-net
# ----------------------------------------------------
# Monitor (painel de saúde de todo o ambiente + /metrics Prometheus)
# Painel: https://<MONITOR_DOMAIN> (nginx, com MONITOR_TOKEN) ou http://localhost:${MONITOR_PORT:-3016}
# Lê o Docker pelo socket (read-only)
# ----------------------------------------------------
monitor:
image: marlussantiago/support-monitor:latest
build:
context: ./monitor
container_name: support-monitor
restart: unless-stopped
ports:
- target: 3016
published: "${MONITOR_PORT:-3016}"
host_ip: 127.0.0.1
environment:
MONITOR_ENV_NAME: ${MONITOR_ENV_NAME:-local}
MONITOR_TOKEN: ${MONITOR_TOKEN:-}
MONITOR_WEBHOOK_URL: ${MONITOR_WEBHOOK_URL:-}
MONITOR_ALERT_DEGRADED: ${MONITOR_ALERT_DEGRADED:-false}
MONITOR_INTERVAL: ${MONITOR_INTERVAL:-15}
MONITOR_FAIL_THRESHOLD: ${MONITOR_FAIL_THRESHOLD:-2}
MONITOR_TLS_ALLOW_SELF_SIGNED: ${MONITOR_TLS_ALLOW_SELF_SIGNED:-false}
MONITOR_EXPECTED_SERVICES: ${MONITOR_EXPECTED_SERVICES:-nginx,certbot,api,chatwoot,chatwoot-worker,dashboard-app,theme-studio,support-redis,monitor}
# Borda HTTPS: verifica nginx -> app e o certificado de cada domínio
CHATWOOT_DOMAIN: ${CHATWOOT_DOMAIN:-chat.localhost}
API_DOMAIN: ${API_DOMAIN:-api.localhost}
MONITOR_DOMAIN: ${MONITOR_DOMAIN:-}
GLPI_DOMAIN: ${GLPI_DOMAIN:-}
# Banco (role com pg_monitor + SELECT nas tabelas de negócio; ver .env.example)
PG_HOST: ${DB_HOST:-support-db}
PG_PORT: ${DB_PORT:-5432}
PG_USER: ${MONITOR_DB_USER:-${POSTGRES_USER:-support_user}}
PG_PASSWORD: ${MONITOR_DB_PASSWORD:-${POSTGRES_PASSWORD:-support_pass}}
API_DB_NAME: ${POSTGRES_DB:-support_db}
API_DB_SCHEMA: ${API_DB_SCHEMA:-public}
CHATWOOT_DB_NAME: ${CHATWOOT_DB_NAME:-chatwoot_production}
CHATWOOT_DB_SCHEMA: ${CHATWOOT_DB_SCHEMA:-public}
REDIS_HOST: support-redis
REDIS_PORT: 6379
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- monitor_data:/data
networks:
- internal-net
volumes:
tascom_theme:
support_pgdata:
support_redisdata:
chatwoot_data:
certbot_conf:
certbot_www:
monitor_data:
networks:
internal-net:
driver: bridge
services:
api:
image: docker.io/marlussantiago/support-api:latest@sha256:86727fd96b0a46f8e54d8650aca98d350aa7776b046e93cf7910bfe30092e82c
certbot:
image: docker.io/marlussantiago/support-certbot:latest@sha256:77e5cd9a38089fa0c4caf983f321de5bbc53115443c925a8c88fb5f7a7b528a3
chatwoot:
image: docker.io/chatwoot/chatwoot:latest@sha256:a4b7eea7353a9b585d0f29f2c57c7549710db961b119f7f1561b2fe964f48f65
chatwoot-worker:
image: docker.io/chatwoot/chatwoot:latest@sha256:a4b7eea7353a9b585d0f29f2c57c7549710db961b119f7f1561b2fe964f48f65
dashboard-app:
image: docker.io/marlussantiago/support-dashboard-app:latest@sha256:e22bf4b8ddbdfb1a7aa63c754e52f90b3f6b8c2a626be65f47314ca77dce9063
monitor:
image: docker.io/marlussantiago/support-monitor:latest@sha256:34376d8a686eb06185759dc7c21c42928a94a93c77eeaa1e3feb418b33903ab6
nginx:
image: docker.io/marlussantiago/support-nginx:latest@sha256:59a5de3285af6b23227f0f1747b4cf6a68d122aac56e18b5053f9229d948cafb
support-db:
image: docker.io/pgvector/pgvector:pg16@sha256:7b822b0aac60967beb1ea5e576b8602c94c300a157d187f385ae3e0da199b90a
support-redis:
image: docker.io/library/redis:7-alpine@sha256:858f009f9709ce576febc734aa78b8f6d624b82571f9ddb6bda4377c833b3499
theme-studio:
image: docker.io/marlussantiago/support-theme-studio:latest@sha256:0460aaa72a1d8e65d1742dd025165f0e05807881c2679f0912d00fba12e21d80
docker compose -f oci://marlussantiago/support-agent:latest upUse the above command to pull and run the Compose file. Learn more.
Redis is the world’s fastest data platform for caching, vector search, and NoSQL databases.
Pulls
1B+
Stars
13624
Last Updated
2 days
Open-source vector similarity search for Postgres
Pulls
100M+
Stars
112
Last Updated
23 days
The modern, open source, self-hosted customer support platform. Alternative to Intercom and Zendesk.
Pulls
10M+
Stars
109
Last Updated
about 11 hours