Merge fd6e99e18b into 337c48b0f0
This commit is contained in:
commit
6c1713bca0
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Backend
|
||||||
|
ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
APP_USE_HTTPS_REDIRECTION=false
|
||||||
|
|
||||||
|
# JWT
|
||||||
|
JWT_KEY=CHANGE_ME_TO_A_LONG_RANDOM_SECRET
|
||||||
|
JWT_ISSUER=LineGestao
|
||||||
|
JWT_AUDIENCE=LineGestao
|
||||||
|
|
||||||
|
# Seed admin (first login)
|
||||||
|
SEED_ADMIN_EMAIL=admin@seu-dominio.com
|
||||||
|
SEED_ADMIN_PASSWORD=CHANGE_ME_TO_A_STRONG_PASSWORD
|
||||||
|
|
||||||
|
# PostgreSQL
|
||||||
|
POSTGRES_DB=linegestao
|
||||||
|
POSTGRES_USER=linegestao_app
|
||||||
|
POSTGRES_PASSWORD=CHANGE_ME_TO_A_STRONG_PASSWORD
|
||||||
|
|
||||||
|
# Front-end URL used by CORS
|
||||||
|
FRONTEND_PUBLIC_URL=https://seu-dominio.com
|
||||||
|
|
||||||
|
# Domain / HTTPS (docker-compose.prod.yml with Caddy)
|
||||||
|
API_DOMAIN=api.seu-dominio.com
|
||||||
|
ACME_EMAIL=seu-email@seu-dominio.com
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
email {$ACME_EMAIL}
|
||||||
|
}
|
||||||
|
|
||||||
|
{$API_DOMAIN} {
|
||||||
|
encode zstd gzip
|
||||||
|
reverse_proxy api:8080
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
# Deploy rápido (API + Postgres)
|
||||||
|
|
||||||
|
## Erro: `no configuration file provided: not found`
|
||||||
|
Esse erro acontece quando o `docker compose` é executado em uma pasta sem `docker-compose.yml`.
|
||||||
|
|
||||||
|
Este repositório inclui `docker-compose.yml` na raiz do projeto.
|
||||||
|
|
||||||
|
## Opção 1: subir via IP (rápido)
|
||||||
|
|
||||||
|
1. Entre na pasta da API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/apps/line-gestao-api
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Crie o `.env` a partir do exemplo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Suba os containers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Verifique o status e logs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps
|
||||||
|
docker compose logs -f --tail=200
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Teste healthcheck da API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -I http://SEU_SERVIDOR:4000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Opção 2: subir já com domínio + HTTPS automático (Caddy)
|
||||||
|
|
||||||
|
### Pré-requisitos
|
||||||
|
- O DNS do domínio/subdomínio da API deve apontar para o IP do servidor (registro `A`).
|
||||||
|
- Portas 80 e 443 abertas no firewall/security group.
|
||||||
|
|
||||||
|
> Se você viu erro do tipo `client version 1.24 is too old` no Traefik, use este modo com Caddy: ele não depende da API Docker para criar rotas e evita esse problema.
|
||||||
|
|
||||||
|
### 1) Ajuste o `.env`
|
||||||
|
Na pasta da API:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/apps/line-gestao-api
|
||||||
|
cp .env.example .env
|
||||||
|
nano .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Preencha obrigatoriamente:
|
||||||
|
- `API_DOMAIN` (ex.: `api.seudominio.com`)
|
||||||
|
- `ACME_EMAIL` (email para emitir certificado)
|
||||||
|
- `FRONTEND_PUBLIC_URL` (URL pública do front)
|
||||||
|
- `JWT_KEY`, `SEED_ADMIN_*`, `POSTGRES_PASSWORD`
|
||||||
|
|
||||||
|
### 2) Suba em modo produção com Caddy
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) Verifique saúde e certificado
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml ps
|
||||||
|
docker compose -f docker-compose.prod.yml logs -f --tail=200
|
||||||
|
curl -i https://SEU_API_DOMAIN/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Checklist de confirmação (API realmente no ar)
|
||||||
|
Considere que o deploy está concluído quando **todos** os itens abaixo estiverem OK:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps
|
||||||
|
curl -i http://127.0.0.1:4000/health
|
||||||
|
curl -i http://SEU_IP_PUBLICO:4000/health
|
||||||
|
```
|
||||||
|
|
||||||
|
Para produção com domínio:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.prod.yml ps
|
||||||
|
curl -i https://SEU_API_DOMAIN/health
|
||||||
|
```
|
||||||
|
|
||||||
|
Resultado esperado:
|
||||||
|
- container `linegestao-api` com status `healthy`;
|
||||||
|
- container `linegestao-db` com status `healthy`;
|
||||||
|
- endpoint `/health` respondendo `HTTP/1.1 200 OK`.
|
||||||
|
|
||||||
|
## Atualizando um clone já existente no servidor
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/apps/line-gestao-api
|
||||||
|
git fetch --all --prune
|
||||||
|
git pull --rebase origin NOME_DA_BRANCH
|
||||||
|
```
|
||||||
|
|
||||||
|
Depois de atualizar, suba com o arquivo que você usa:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# modo IP
|
||||||
|
docker compose up -d --build
|
||||||
|
|
||||||
|
# modo domínio + HTTPS
|
||||||
|
docker compose -f docker-compose.prod.yml up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
## Observações
|
||||||
|
- O Postgres **não é exposto** para fora do Docker (sem `5432:5432`).
|
||||||
|
- No modo IP, a API sobe na porta `4000` do host (`4000:8080`).
|
||||||
|
- No modo domínio, a API fica atrás do Caddy em `443` (HTTPS).
|
||||||
|
- Defina valores fortes para `JWT_KEY`, `SEED_ADMIN_PASSWORD` e `POSTGRES_PASSWORD`.
|
||||||
|
|
@ -10,6 +10,10 @@ RUN dotnet publish "./line-gestao-api.csproj" -c Release -o /app/publish /p:UseA
|
||||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
|
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
ENV ASPNETCORE_URLS=http://+:8080
|
ENV ASPNETCORE_URLS=http://+:8080
|
||||||
ENV ASPNETCORE_ENVIRONMENT=Production
|
ENV ASPNETCORE_ENVIRONMENT=Production
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
services:
|
||||||
|
caddy:
|
||||||
|
image: caddy:2.10-alpine
|
||||||
|
container_name: linegestao-caddy
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
environment:
|
||||||
|
API_DOMAIN: ${API_DOMAIN:?API_DOMAIN is required}
|
||||||
|
ACME_EMAIL: ${ACME_EMAIL:?ACME_EMAIL is required}
|
||||||
|
volumes:
|
||||||
|
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
||||||
|
- caddy_data:/data
|
||||||
|
- caddy_config:/config
|
||||||
|
depends_on:
|
||||||
|
api:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: linegestao-db
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-linegestao}
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-linegestao_app}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
|
||||||
|
volumes:
|
||||||
|
- pg_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-linegestao_app} -d ${POSTGRES_DB:-linegestao}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
api:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: linegestao-api
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Production}
|
||||||
|
App__UseHttpsRedirection: ${APP_USE_HTTPS_REDIRECTION:-false}
|
||||||
|
ConnectionStrings__Default: Host=db;Port=5432;Database=${POSTGRES_DB:-linegestao};Username=${POSTGRES_USER:-linegestao_app};Password=${POSTGRES_PASSWORD}
|
||||||
|
Jwt__Key: ${JWT_KEY:?JWT_KEY is required}
|
||||||
|
Jwt__Issuer: ${JWT_ISSUER:-LineGestao}
|
||||||
|
Jwt__Audience: ${JWT_AUDIENCE:-LineGestao}
|
||||||
|
Seed__AdminEmail: ${SEED_ADMIN_EMAIL:?SEED_ADMIN_EMAIL is required}
|
||||||
|
Seed__AdminPassword: ${SEED_ADMIN_PASSWORD:?SEED_ADMIN_PASSWORD is required}
|
||||||
|
Cors__AllowedOrigins__0: ${FRONTEND_PUBLIC_URL:?FRONTEND_PUBLIC_URL is required}
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 20s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pg_data:
|
||||||
|
caddy_data:
|
||||||
|
caddy_config:
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: linegestao-db
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-linegestao}
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-linegestao_app}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD is required}
|
||||||
|
volumes:
|
||||||
|
- pg_data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-linegestao_app} -d ${POSTGRES_DB:-linegestao}"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
|
||||||
|
api:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
container_name: linegestao-api
|
||||||
|
restart: unless-stopped
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
ports:
|
||||||
|
- "4000:8080"
|
||||||
|
environment:
|
||||||
|
ASPNETCORE_ENVIRONMENT: ${ASPNETCORE_ENVIRONMENT:-Production}
|
||||||
|
App__UseHttpsRedirection: ${APP_USE_HTTPS_REDIRECTION:-false}
|
||||||
|
ConnectionStrings__Default: Host=db;Port=5432;Database=${POSTGRES_DB:-linegestao};Username=${POSTGRES_USER:-linegestao_app};Password=${POSTGRES_PASSWORD}
|
||||||
|
Jwt__Key: ${JWT_KEY:?JWT_KEY is required}
|
||||||
|
Jwt__Issuer: ${JWT_ISSUER:-LineGestao}
|
||||||
|
Jwt__Audience: ${JWT_AUDIENCE:-LineGestao}
|
||||||
|
Seed__AdminEmail: ${SEED_ADMIN_EMAIL:?SEED_ADMIN_EMAIL is required}
|
||||||
|
Seed__AdminPassword: ${SEED_ADMIN_PASSWORD:?SEED_ADMIN_PASSWORD is required}
|
||||||
|
Cors__AllowedOrigins__0: ${FRONTEND_PUBLIC_URL:?FRONTEND_PUBLIC_URL is required}
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
|
||||||
|
interval: 20s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
start_period: 20s
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
pg_data:
|
||||||
Loading…
Reference in New Issue