feat(image-render): main + Dockerfile + compose entry (port 18714)
This commit is contained in:
@@ -95,3 +95,30 @@ services:
|
|||||||
interval: 60s
|
interval: 60s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
|
|
||||||
|
image-render:
|
||||||
|
build:
|
||||||
|
context: ./image-render
|
||||||
|
container_name: image-render
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "18714:8000"
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Seoul
|
||||||
|
- REDIS_URL=${REDIS_URL:-redis://192.168.45.54:6379}
|
||||||
|
- NAS_BASE_URL=${NAS_BASE_URL:-http://192.168.45.54:18802}
|
||||||
|
- INTERNAL_API_KEY=${INTERNAL_API_KEY:-}
|
||||||
|
- OPENAI_API_KEY=${OPENAI_API_KEY:-}
|
||||||
|
- GEMINI_API_KEY=${GEMINI_API_KEY:-}
|
||||||
|
- COMFYUI_URL=${COMFYUI_URL:-http://host.docker.internal:8188}
|
||||||
|
- FLUX_BLOCK_TRADING_HOURS=${FLUX_BLOCK_TRADING_HOURS:-1}
|
||||||
|
- IMAGE_MEDIA_ROOT=${IMAGE_MEDIA_ROOT:-/mnt/nas/webpage/data/image}
|
||||||
|
extra_hosts:
|
||||||
|
- "host.docker.internal:host-gateway"
|
||||||
|
volumes:
|
||||||
|
- /mnt/nas/webpage/data/image:/mnt/nas/webpage/data/image
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"]
|
||||||
|
interval: 60s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
|||||||
16
services/image-render/Dockerfile
Normal file
16
services/image-render/Dockerfile
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
FROM python:3.12-slim-bookworm
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir --timeout 600 --retries 5 -r requirements.txt
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"]
|
||||||
18
services/image-render/env.example
Normal file
18
services/image-render/env.example
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Redis (NAS)
|
||||||
|
REDIS_URL=redis://192.168.45.54:6379
|
||||||
|
|
||||||
|
# NAS image-lab webhook
|
||||||
|
NAS_BASE_URL=http://192.168.45.54:18802
|
||||||
|
INTERNAL_API_KEY=replace-me
|
||||||
|
|
||||||
|
# API provider keys (worker reports failed if missing)
|
||||||
|
OPENAI_API_KEY=
|
||||||
|
GEMINI_API_KEY=
|
||||||
|
# Seedance key not used by image-render
|
||||||
|
|
||||||
|
# FLUX local
|
||||||
|
COMFYUI_URL=http://host.docker.internal:8188
|
||||||
|
FLUX_BLOCK_TRADING_HOURS=1
|
||||||
|
|
||||||
|
# NAS SMB mount target (image-render writes to this, NAS reads via /media/image/)
|
||||||
|
IMAGE_MEDIA_ROOT=/mnt/nas/webpage/data/image
|
||||||
36
services/image-render/main.py
Normal file
36
services/image-render/main.py
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
"""image-render FastAPI entry — health + lifespan (worker loop spawn)."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
|
from fastapi import FastAPI
|
||||||
|
|
||||||
|
import worker
|
||||||
|
|
||||||
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s %(message)s")
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def lifespan(app: FastAPI):
|
||||||
|
worker_task = asyncio.create_task(worker.worker_loop())
|
||||||
|
logger.info("image-render lifespan 시작")
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
worker_task.cancel()
|
||||||
|
try:
|
||||||
|
await worker_task
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
pass
|
||||||
|
logger.info("image-render lifespan 종료")
|
||||||
|
|
||||||
|
|
||||||
|
app = FastAPI(lifespan=lifespan)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/health")
|
||||||
|
def health():
|
||||||
|
return {"ok": True, "service": "image-render"}
|
||||||
9
services/image-render/requirements.txt
Normal file
9
services/image-render/requirements.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
fastapi==0.115.6
|
||||||
|
uvicorn[standard]==0.34.0
|
||||||
|
requests==2.32.3
|
||||||
|
redis>=5.0
|
||||||
|
httpx>=0.27
|
||||||
|
openai>=1.50.0
|
||||||
|
pytest>=8.0
|
||||||
|
pytest-asyncio>=0.24
|
||||||
|
respx>=0.21
|
||||||
Reference in New Issue
Block a user