Skip to content

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:

VariableDescricao
BETTER_AUTH_SECRETChave secreta para assinatura de sessao. Gere com openssl rand -base64 32.
MASTER_SECRETSegredo mestre da aplicacao para criptografia. Gere com openssl rand -base64 32.
POSTGRES_USERNome de usuario do PostgreSQL (deve ser igual em postgres e DATABASE_URL).
POSTGRES_PASSWORDSenha do PostgreSQL (deve ser igual em postgres e DATABASE_URL).
POSTGRES_DBNome do banco de dados PostgreSQL (deve ser igual em postgres e DATABASE_URL).
TRUSTED_ORIGINSLista de origens confiaveis separadas por virgula para protecao CSRF e redirecionamentos OAuth (ex: https://mystore.com).
BASE_URLURL 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
VariableDescricao
SMTP_HOSTHostname do servidor de e-mail (ex: smtp.sendgrid.net).
SMTP_PORTPorta do servidor. Geralmente 587 para TLS ou 465 para SSL. Deve ser inteiro em [1, 65535].
SMTP_USERNome de usuario de login SMTP.
SMTP_PASSWORDSenha 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
VariavelDescricao
ASSETS_STORAGE_MODElocal (padrao) ou s3. Quando s3, as seis vars ASSETS_S3_* e ASSETS_PUBLIC_BASE_URL sao obrigatorias.
ASSETS_S3_ENDPOINTEndpoint da API S3 (ex: https://s3.amazonaws.com, ou a URL do seu provedor para Cloudflare R2, Backblaze B2, MinIO, etc.).
ASSETS_S3_REGIONRegiao do bucket (ex: us-east-1, auto para R2).
ASSETS_S3_BUCKETNome do bucket.
ASSETS_S3_ACCESS_KEY_IDAccess key com permissoes de leitura/escrita no bucket.
ASSETS_S3_SECRET_ACCESS_KEYSecret access key.
ASSETS_PUBLIC_BASE_URLURL publica base que a loja usa para carregar os assets (ex: o seu dominio CDN apontado para o bucket).
ASSETS_MAX_BYTESLimite 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.mjs

O 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 -d

Isso inicia dois servicos:

  • postgres — PostgreSQL 17 com pgvector (pgvector/pgvector:pg17), escutando na porta 5432.
  • app — O container da aplicacao (capyshop/capyshop:latest), exposto na porta 3000.

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 app

A 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 / MountFinalidade
postgres_dataPersiste os dados do PostgreSQL entre reinicializacoes do container.
./data:/app/dataPersiste 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:

  1. Instala todas as dependencias e compila a aplicacao.
  2. Copia apenas as dependencias de producao e o resultado do build para a imagem final.
  3. Executa prisma migrate deploy e depois inicia o servidor na porta 3000.

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 \
  capyshop

Solucao de Problemas

ErroCausaCorrecao
app encerra imediatamenteVariaveis de ambiente ausentes ou invalidasVerifique docker compose logs app e confirme todas as variaveis de ambiente obrigatorias
ECONNREFUSED para o postgresA aplicacao iniciou antes do banco estar prontoReinicie a aplicacao: docker compose restart app
P3009 - failed migrationsUma migracao anterior deixou estado inconsistenteExecute DROP TABLE IF EXISTS _prisma_migrations CASCADE; no banco de dados e reinicie
type "vector" does not existExtensao pgvector nao criadaA imagem pgvector/pgvector:pg17 ja inclui, mas execute CREATE EXTENSION IF NOT EXISTS vector; se estiver usando outra imagem
Porta 3000 ja em usoOutro processo esta usando a portaPare o processo conflitante ou altere o mapeamento de porta no docker-compose.yml
Arquivos enviados perdidos apos reinicioVolume ./data nao montadoCertifique-se de que a secao volumes inclui ./data:/app/data