Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,24 @@ RUN apt-get update \
libgomp1 \
&& rm -rf /var/lib/apt/lists/* \
&& groupadd --system app \
&& useradd --system --gid app --home-dir /home/app --create-home app
&& useradd --system --gid app --home-dir /home/app --create-home app \
&& mkdir -p /app \
&& chown app:app /app

WORKDIR /app

COPY --from=uv /uv /uvx /bin/
COPY --from=uv --chown=app:app /uv /uvx /bin/

# Resolve dependências antes do código para aproveitar o cache de camadas.
COPY pyproject.toml uv.lock README.md ./
COPY --chown=app:app pyproject.toml uv.lock README.md ./
RUN uv sync --frozen --no-dev --group inference --no-install-project

COPY --chown=app:app src ./src
COPY --chown=app:app config ./config
COPY --chown=app:app scripts ./scripts
RUN uv sync --frozen --no-dev --group inference

COPY docker/entrypoint.sh /usr/local/bin/medtrack-entrypoint
COPY --chown=app:app docker/entrypoint.sh /usr/local/bin/medtrack-entrypoint
RUN chmod 755 /usr/local/bin/medtrack-entrypoint

ENV MEDTRACK_FETCH_MODEL_ON_START=false \
Expand All @@ -44,7 +46,7 @@ ENV MEDTRACK_FETCH_MODEL_ON_START=false \
EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=5s --start-period=45s --retries=3 \
CMD python -c "from urllib.request import urlopen; urlopen('http://127.0.0.1:8000/healthz', timeout=3)"
CMD python -c "import os; from urllib.request import urlopen; urlopen(f\"http://127.0.0.1:{os.environ.get('PORT', '8000')}/healthz\", timeout=3)"

ENTRYPOINT ["/usr/local/bin/medtrack-entrypoint"]
CMD ["sh", "-c", "uvicorn medtrack_ai.api.main:app --host 0.0.0.0 --port ${PORT:-8000}"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ descritos em [docs/CI_CD.md](docs/CI_CD.md).
| Artefato e versão do modelo | [docs/models/README.md](docs/models/README.md) |
| Contêiner local | [docs/CONTAINER.md](docs/CONTAINER.md) |
| CI/CD e versionamento | [docs/CI_CD.md](docs/CI_CD.md) |
| Deploy de staging | [docs/RAILWAY.md](docs/RAILWAY.md) |
| Deploy em nuvem | [docs/CLOUD_DEPLOYMENT.md](docs/CLOUD_DEPLOYMENT.md) |
| Decisões arquiteturais | [docs/adr/README.md](docs/adr/README.md) |
| Governança | [docs/GOVERNANCE.md](docs/GOVERNANCE.md) |

Expand Down
4 changes: 2 additions & 2 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ set -eu
artifact_directory="$(dirname "${MEDTRACK_MODEL_URI}")"
easyocr_directory="${EASYOCR_MODULE_PATH:-/home/app/.EasyOCR}"

# Volumes Railway são montados no início do container. Preparamos permissões
# como root e reexecutamos o entrypoint com o usuário sem privilégios.
# Volumes são montados no início do contêiner. Preparamos as permissões como
# root e reexecutamos o entrypoint com o usuário sem privilégios.
if [ "$(id -u)" = "0" ]; then
mkdir -p "${artifact_directory}" "${easyocr_directory}"
chown -R app:app "${artifact_directory}" "${easyocr_directory}"
Expand Down
54 changes: 54 additions & 0 deletions docs/CLOUD_DEPLOYMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Deploy em plataforma de nuvem

Este repositório pode ser implantado em uma plataforma que execute imagens
Docker, como Render ou outro provedor compatível. A plataforma deve construir o
`Dockerfile` da raiz e não deve substituir o `ENTRYPOINT` nem o `CMD` da imagem.

## Configuração do serviço

1. Crie um serviço web a partir deste repositório.
2. Selecione o runtime Docker e a branch que será implantada.
3. Não configure um comando de início personalizado. O `CMD` da imagem inicia o
Uvicorn usando a variável `PORT`, com fallback local para `8000`.
4. Configure a verificação HTTP de saúde em `GET /healthz`.
5. Se o modelo precisar persistir entre implantações, monte um volume em
`/data`.

## Variáveis de ambiente

Configure os valores adequados ao ambiente pela interface segura do provedor:

```dotenv
MEDTRACK_ENV=staging
MEDTRACK_LOG_LEVEL=INFO
MEDTRACK_MODEL_URI=/data/models/medtrack-yolo/v1.0.0/best.pt
MEDTRACK_MODEL_VERSION=v1.0.0
MEDTRACK_MODEL_MANIFEST=config/models/medtrack-yolo-v1.0.0.json
MEDTRACK_FETCH_MODEL_ON_START=true
MEDTRACK_DEVICE=cpu
MEDTRACK_MAX_IMAGE_DIMENSION=1024
MEDTRACK_YOLO_CONFIDENCE=0.5
EASYOCR_MODULE_PATH=/data/easyocr
MEDTRACK_CORS_ORIGINS=
```

Não copie um arquivo `.env` com segredos para o Git. A variável
`MEDTRACK_MODEL_URI` é obrigatória para o entrypoint preparar o diretório do
modelo antes de reduzir seus privilégios para o usuário `app`.

## Saúde e prontidão

- `GET /healthz` confirma que o processo HTTP está em execução e deve ser usado
como healthcheck da plataforma.
- `GET /readyz` confirma que o modelo foi carregado e que o serviço está pronto
para inferência.

Após o deploy, substitua `URL` pelo domínio fornecido pela plataforma:

```powershell
Invoke-WebRequest https://URL/healthz
Invoke-WebRequest https://URL/readyz
```

Os logs são enviados para stdout. Antes de promover uma versão, valide os dois
endpoints e confirme que o provedor preservou o volume do modelo.
3 changes: 2 additions & 1 deletion docs/CONTAINER.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ use `$PWD.Path` para fornecer o caminho absoluto.
- O Compose é CPU. Uma variante GPU só será criada após a escolha da plataforma
de deploy e do runtime NVIDIA.

Para deploy de staging na Railway, consulte [RAILWAY.md](RAILWAY.md).
Para deploy em um provedor de nuvem, consulte
[CLOUD_DEPLOYMENT.md](CLOUD_DEPLOYMENT.md).
2 changes: 1 addition & 1 deletion docs/INVENTARIO_ATUAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Data do levantamento: 22 de julho de 2026.
| Utilitários | `src/utils/` | Sanitização de texto e ferramenta de rotulagem. |
| Dados | `dataset/` e fonte externa indicada no README | Dataset e pesos são locais e ignorados; apenas a configuração de treino é versionada. |
| Contêiner | `Dockerfile` | Instala `requirements.txt` e inicia `src.api.api:app`, mas não recebe o modelo. |
| Testes | `tests/test_api.py` | Mistura teste HTTP e modelo real; cria artefato local; alguns casos são ignorados quando não há imagem. |
| Testes | `../tests/integration/test_api.py` | Mistura teste HTTP e modelo real; cria artefato local; alguns casos são ignorados quando não há imagem. |

## Contrato HTTP observado (baseline)

Expand Down
73 changes: 0 additions & 73 deletions docs/RAILWAY.md

This file was deleted.

4 changes: 2 additions & 2 deletions docs/TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ somente os níveis rápidos; testes que requerem artefato real são opt-in.
| Nível | Localização | Dependências | Quando executar |
| --- | --- | --- | --- |
| Unitário | `tests/unit/` | Nenhuma rede, peso ou GPU | Todo commit e pull request |
| Integração | `tests/test_api.py` | FastAPI e adaptador falso | Todo commit e pull request |
| Manifesto | `tests/test_model_manifest.py` | Arquivos pequenos | Todo commit e pull request |
| Integração | `../tests/integration/test_api.py` | FastAPI e adaptador falso | Todo commit e pull request |
| Manifesto | `../tests/unit/test_model_manifest.py` | Arquivos pequenos | Todo commit e pull request |
| Smoke de artefato | `tests/model/` | Peso local já verificado | Antes de deploy ou promoção |
| Inferência real | futuro fixture de imagens aprovada | Peso + grupo `inference` | Pipeline manual dedicado |

Expand Down
8 changes: 0 additions & 8 deletions railway.toml

This file was deleted.

Empty file removed tests/__init__.py
Empty file.
File renamed without changes.
File renamed without changes.
Loading