Tema
Deploy com Docker
Implante o Capyshop em producao usando Docker Compose com a imagem de container pre-construida e PostgreSQL com pgvector.
Pre-requisitos
- Docker Engine 20+
- Docker Compose v2+
1. Criar um Arquivo Docker Compose
Crie um docker-compose.yml no seu diretorio de deploy:
yaml
services:
postgres:
image: pgvector/pgvector:pg17
restart: always
environment:
POSTGRES_USER: capyshop
POSTGRES_PASSWORD: changeme
POSTGRES_DB: capyshop
volumes:
- postgres_data:/var/lib/postgresql/data
app:
image: capyshop/capyshop:latest
restart: unless-stopped
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://capyshop:changeme@postgres:5432/capyshop
- BETTER_AUTH_SECRET=<generate-with-openssl-rand-base64-32>
- MASTER_SECRET=<generate-with-openssl-rand-base64-32>
- TRUSTED_ORIGINS=https://mystore.com
- BASE_URL=https://mystore.com
volumes:
- ./data:/app/data
depends_on:
- postgres
volumes:
postgres_data:Substitua os valores de exemplo:
| Variable | Descricao |
|---|---|
BETTER_AUTH_SECRET | Chave secreta para assinatura de sessao. Gere com openssl rand -base64 32. |
MASTER_SECRET | Segredo mestre da aplicacao para criptografia. Gere com openssl rand -base64 32. |
POSTGRES_USER | Nome de usuario do PostgreSQL (deve ser igual em postgres e DATABASE_URL). |
POSTGRES_PASSWORD | Senha do PostgreSQL (deve ser igual em postgres e DATABASE_URL). |
POSTGRES_DB | Nome do banco de dados PostgreSQL (deve ser igual em postgres e DATABASE_URL). |
TRUSTED_ORIGINS | Lista de origens confiaveis separadas por virgula para protecao CSRF e redirecionamentos OAuth (ex: https://mystore.com). |
BASE_URL | URL publica da loja, usada em e-mails, SEO e sitemaps (ex: https://mystore.com). |
Opcional: Configuracao de SMTP via Variaveis de Ambiente
Por padrao, as credenciais SMTP sao gerenciadas em Configuracoes → Email no painel administrativo. Se preferir configurar o SMTP no momento do deploy, voce pode definir as variaveis de ambiente abaixo. Quando definidas, elas sobrescrevem os valores do painel e os campos correspondentes no formulario de Email ficam desabilitados.
yaml
environment:
# ...outras variaveis
- SMTP_HOST=smtp.sendgrid.net
- SMTP_PORT=587
- SMTP_USER=apikey
- SMTP_PASSWORD=sua-senha-smtp| Variable | Descricao |
|---|---|
SMTP_HOST | Hostname do servidor de e-mail (ex: smtp.sendgrid.net). |
SMTP_PORT | Porta do servidor. Geralmente 587 para TLS ou 465 para SSL. Deve ser inteiro em [1, 65535]. |
SMTP_USER | Nome de usuario de login SMTP. |
SMTP_PASSWORD | Senha de login SMTP. Armazenada em texto puro no ambiente — nao passa pela camada de criptografia do banco. |
Cada variavel e independente. Se apenas SMTP_HOST estiver definida, os outros tres campos SMTP permanecem editaveis na interface administrativa e sao lidos do banco de dados.
Opcional: Armazenamento de Assets em S3
Por padrao, imagens carregadas e outros assets sao armazenados no disco local em data/files/. Para enviar uploads para um bucket compativel com S3 e servi-los a partir de um CDN, defina o modo de armazenamento como s3 e configure as credenciais do bucket.
yaml
environment:
# ...outras vars
- ASSETS_STORAGE_MODE=s3
- ASSETS_S3_ENDPOINT=https://s3.amazonaws.com
- ASSETS_S3_REGION=us-east-1
- ASSETS_S3_BUCKET=my-store-assets
- ASSETS_S3_ACCESS_KEY_ID=AKIA...
- ASSETS_S3_SECRET_ACCESS_KEY=...
- ASSETS_PUBLIC_BASE_URL=https://cdn.mystore.com
- ASSETS_MAX_BYTES=10gb| Variavel | Descricao |
|---|---|
ASSETS_STORAGE_MODE | local (padrao) ou s3. Quando s3, as seis vars ASSETS_S3_* e ASSETS_PUBLIC_BASE_URL sao obrigatorias. |
ASSETS_S3_ENDPOINT | Endpoint da API S3 (ex: https://s3.amazonaws.com, ou a URL do seu provedor para Cloudflare R2, Backblaze B2, MinIO, etc.). |
ASSETS_S3_REGION | Regiao do bucket (ex: us-east-1, auto para R2). |
ASSETS_S3_BUCKET | Nome do bucket. |
ASSETS_S3_ACCESS_KEY_ID | Access key com permissoes de leitura/escrita no bucket. |
ASSETS_S3_SECRET_ACCESS_KEY | Secret access key. |
ASSETS_PUBLIC_BASE_URL | URL publica base que a loja usa para carregar os assets (ex: o seu dominio CDN apontado para o bucket). |
ASSETS_MAX_BYTES | Limite cumulativo opcional de armazenamento entre todos os ficheiros. Aceita 10gb, 500mb ou contagem bruta de bytes. Aplica-se em modo local e s3. Os limites por upload (5 MB imagem / 50 MB video) permanecem inalterados. |
Ao migrar uma loja existente de local para s3, execute o script de migracao incluido uma vez dentro de um contentor em deploy para enviar os ficheiros existentes ao bucket e pre-gerar as variantes WebP:
bash
docker exec -it <container> node build/scripts/migrate-assets-to-s3.mjsO script e idempotente — executa-lo novamente e seguro e ignora o trabalho que ja foi concluido. Se os seus originais existentes estao no host (por exemplo, /docker/<store>/app_data/files/), monte esse caminho em /app/data/files dentro do contentor para que o script possa carrega-los; caso contrario, ele recorrera ao que ja estiver no bucket.
2. Iniciar a Aplicacao
bash
docker compose up -dIsso inicia dois servicos:
- postgres — PostgreSQL 17 com pgvector (
pgvector/pgvector:pg17), escutando na porta5432. - app — O container da aplicacao (
capyshop/capyshop:latest), exposto na porta3000.
Na inicializacao, o container da aplicacao executa automaticamente as migracoes do banco de dados (prisma migrate deploy) antes de iniciar o servidor.
3. Verificar
bash
# Verificar se ambos os containers estao rodando
docker compose ps
# Verificar logs da aplicacao
docker compose logs appA aplicacao deve estar acessivel em http://<seu-host>:3000.
Proxy Reverso
Para deploys em producao com HTTPS, coloque um proxy reverso (como Traefik, Caddy ou nginx) na frente da aplicacao. O proxy reverso cuida da terminacao TLS e encaminha o trafego para a porta 3000.
Habilitando Compressao Gzip com Traefik
Se voce utiliza o Traefik como proxy reverso, habilite a compressao gzip para reduzir o tamanho das respostas e melhorar a velocidade de carregamento — um fator no ranqueamento dos mecanismos de busca. Adicione as seguintes labels ao servico app no seu docker-compose.yml:
yaml
labels:
- "traefik.http.middlewares.compress.compress.minresponsebodybytes=256"
- "traefik.http.routers.STORE_NAME-app.middlewares=compress"Substitua STORE_NAME pelo nome do router Traefik da sua loja. A primeira label define um middleware de compressao que aplica gzip em todas as respostas maiores que 256 bytes. A segunda label associa esse middleware ao router da sua loja.
Volumes
| Volume / Mount | Finalidade |
|---|---|
postgres_data | Persiste os dados do PostgreSQL entre reinicializacoes do container. |
./data:/app/data | Persiste arquivos enviados e dados da aplicacao entre reinicializacoes. |
Compilar a Partir do Codigo-Fonte
Se voce preferir compilar a imagem por conta propria em vez de usar a pre-construida:
bash
docker build -t capyshop .O Dockerfile usa um build multi-stage:
- Instala todas as dependencias e compila a aplicacao.
- Copia apenas as dependencias de producao e o resultado do build para a imagem final.
- Executa
prisma migrate deploye depois inicia o servidor na porta3000.
Para usar sua imagem personalizada, atualize o campo image no seu docker-compose.yml, ou execute de forma independente:
bash
docker run -p 3000:3000 \
-e DATABASE_URL=postgresql://user:pass@host:5432/db \
-e BETTER_AUTH_SECRET=your-secret \
-e MASTER_SECRET=your-secret \
capyshopSolucao de Problemas
| Erro | Causa | Correcao |
|---|---|---|
app encerra imediatamente | Variaveis de ambiente ausentes ou invalidas | Verifique docker compose logs app e confirme todas as variaveis de ambiente obrigatorias |
ECONNREFUSED para o postgres | A aplicacao iniciou antes do banco estar pronto | Reinicie a aplicacao: docker compose restart app |
P3009 - failed migrations | Uma migracao anterior deixou estado inconsistente | Execute DROP TABLE IF EXISTS _prisma_migrations CASCADE; no banco de dados e reinicie |
type "vector" does not exist | Extensao pgvector nao criada | A imagem pgvector/pgvector:pg17 ja inclui, mas execute CREATE EXTENSION IF NOT EXISTS vector; se estiver usando outra imagem |
Porta 3000 ja em uso | Outro processo esta usando a porta | Pare o processo conflitante ou altere o mapeamento de porta no docker-compose.yml |
| Arquivos enviados perdidos apos reinicio | Volume ./data nao montado | Certifique-se de que a secao volumes inclui ./data:/app/data |