# 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.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](https://traefik.io/), [Caddy](https://caddyserver.com/) 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:

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

| 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`                                                                 |
