From c711d99fbcad7c79dd5546d0b5f9459ebee36c7f Mon Sep 17 00:00:00 2001 From: CM Consultor Date: Sun, 9 Aug 2026 02:57:51 +0000 Subject: [PATCH] refactor: split Dockerfile into Dockerfile.api + Dockerfile.web for Swarm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove multi-stage Dockerfile (não compatível com Swarm) - Dockerfile.api: imagem standalone para API FastAPI - Dockerfile.web: imagem standalone para Streamlit - docker-compose.yml: aponta para os Dockerfiles separados - README.md: instruções de build individual + deploy Swarm --- Dockerfile | 38 -------------------------------------- Dockerfile.api | 24 ++++++++++++++++++++++++ Dockerfile.web | 21 +++++++++++++++++++++ README.md | 42 +++++++++++++++++++++++++++++------------- docker-compose.yml | 6 ++++-- 5 files changed, 78 insertions(+), 53 deletions(-) delete mode 100644 Dockerfile create mode 100644 Dockerfile.api create mode 100644 Dockerfile.web diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 1e868af..0000000 --- a/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -# ── Estágio 1: base ───────────────────────────────────────────────── -FROM python:3.12-slim AS base - -WORKDIR /app - -ENV PYTHONUNBUFFERED=1 \ - PYTHONDONTWRITEBYTECODE=1 \ - PIP_NO_CACHE_DIR=1 - -# Pillow wheel manylinux já inclui as libs necessárias (libjpeg, zlib, etc). -# Nenhum pacote do sistema é necessário para pypdf + Pillow + Streamlit. - -COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt - -# ── Estágio 2: API ────────────────────────────────────────────────── -FROM base AS api - -COPY . . - -EXPOSE 8555 - -HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD python -c "import http.client; conn=http.client.HTTPConnection('localhost:8555'); conn.request('GET','/health'); r=conn.getresponse(); exit(0 if r.status==200 else 1)" - -CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8555"] - -# ── Estágio 3: Streamlit Web ──────────────────────────────────────── -FROM base AS web - -COPY . . - -EXPOSE 8550 - -HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ - CMD python -c "import http.client; conn=http.client.HTTPConnection('localhost:8550'); conn.request('GET','/'); r=conn.getresponse(); exit(0 if r.status==200 else 1)" - -CMD ["streamlit", "run", "app.py", "--server.port", "8550", "--server.address", "0.0.0.0", "--server.headless", "true"] \ No newline at end of file diff --git a/Dockerfile.api b/Dockerfile.api new file mode 100644 index 0000000..6565867 --- /dev/null +++ b/Dockerfile.api @@ -0,0 +1,24 @@ +# Imagem única para API FastAPI — pronta para Docker Swarm. +# Build: docker build -t pdf-toolkit-api:1.0.0 -f Dockerfile.api . +FROM python:3.12-slim + +WORKDIR /app + +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PIP_NO_CACHE_DIR=1 + +# Pillow wheel manylinux já inclui libjpeg, zlib, etc. +# Nenhuma dep de sistema necessária. + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +EXPOSE 8555 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD python -c "import http.client; conn=http.client.HTTPConnection('localhost:8555'); conn.request('GET','/health'); r=conn.getresponse(); exit(0 if r.status==200 else 1)" + +CMD ["uvicorn", "api:app", "--host", "0.0.0.0", "--port", "8555"] \ No newline at end of file diff --git a/Dockerfile.web b/Dockerfile.web new file mode 100644 index 0000000..7be4853 --- /dev/null +++ b/Dockerfile.web @@ -0,0 +1,21 @@ +# Imagem única para Streamlit — pronta para Docker Swarm. +# Build: docker build -t pdf-toolkit-web:1.0.0 -f Dockerfile.web . +FROM python:3.12-slim + +WORKDIR /app + +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PIP_NO_CACHE_DIR=1 + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +EXPOSE 8550 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \ + CMD python -c "import http.client; conn=http.client.HTTPConnection('localhost:8550'); conn.request('GET','/'); r=conn.getresponse(); exit(0 if r.status==200 else 1)" + +CMD ["streamlit", "run", "app.py", "--server.port", "8550", "--server.address", "0.0.0.0", "--server.headless", "true"] \ No newline at end of file diff --git a/README.md b/README.md index d0bb284..7512814 100644 --- a/README.md +++ b/README.md @@ -144,14 +144,12 @@ curl -X POST http://localhost:8555/compress \ ## 🐳 Docker -### Com docker-compose (recomendado) +### docker-compose (desenvolvimento local) ```bash -# 1. Copie e configure o .env -cp .env.example .env -# Edite .env com sua API Key +cp .env.example .env # configure sua API Key +sed -i 's/PDFTOOLKIT_API_KEY=.*/PDFTOOLKIT_API_KEY=minha-chave/' .env -# 2. Inicie os serviços docker compose up -d --build # Acesse: @@ -160,24 +158,42 @@ docker compose up -d --build # - Swagger: http://localhost:8555/docs ``` -### Build manual +### Build individual para Swarm / registry + +Cada serviço tem seu próprio `Dockerfile` independente: ```bash # API -docker build --target api -t pdf-toolkit-api . -docker run -p 8555:8555 --env-file .env pdf-toolkit-api +docker build -t gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-api:1.0.0 -f Dockerfile.api . +docker push gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-api:1.0.0 # Web -docker build --target web -t pdf-toolkit-web . -docker run -p 8550:8550 --env-file .env pdf-toolkit-web +docker build -t gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-web:1.0.0 -f Dockerfile.web . +docker push gitea.cmconsultor.com.br/cmconsultor/pdf-toolkit-web:1.0.0 +``` + +### Deploy no Docker Swarm + +```yaml +# pdf-toolkit-stack.yml +docker stack deploy -c docker-compose.yml pdf-toolkit +``` + +Ou use imagens previamente buildadas (recomendado para Swarm): + +```bash +# Ajuste o docker-compose.yml para usar as imagens do registry +docker stack deploy -c docker-compose.yml pdf-toolkit ``` ### Estrutura dos containers -- **api**: FastAPI + uvicorn, porta 8555 -- **web**: Streamlit, porta 8550, depende do serviço `api` +Cada container é uma **imagem independente** otimizada para deploy individual: + +- **`pdf-toolkit-api`**: FastAPI + uvicorn, porta 8555 +- **`pdf-toolkit-web`**: Streamlit, porta 8550, depende do serviço `api` - Volume compartilhado `uploads` para arquivos temporários -- Healthcheck em ambos os containers +- Healthcheck embutido em ambos os containers --- diff --git a/docker-compose.yml b/docker-compose.yml index 1d15cc9..c91169e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,8 @@ services: api: build: context: . - target: api + dockerfile: Dockerfile.api + image: pdf-toolkit-api:latest container_name: pdf-toolkit-api restart: unless-stopped ports: @@ -28,7 +29,8 @@ services: web: build: context: . - target: web + dockerfile: Dockerfile.web + image: pdf-toolkit-web:latest container_name: pdf-toolkit-web restart: unless-stopped ports: