diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..98f74c1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM python:3.12-slim + +WORKDIR /app + +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY app/ ./app/ + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8720", "--log-level", "info"] diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/db.py b/app/db.py new file mode 100644 index 0000000..dd4a356 --- /dev/null +++ b/app/db.py @@ -0,0 +1,22 @@ +import os +import pymysql + + +def _params() -> dict: + return { + "host": os.environ["MYSQL_HOST"], + "port": int(os.environ.get("MYSQL_PORT", 3306)), + "user": os.environ["MYSQL_USER"], + "password": os.environ["MYSQL_PASSWORD"], + "database": os.environ["MYSQL_DATABASE"], + "connect_timeout": 3, + } + + +def check_db() -> bool: + try: + conn = pymysql.connect(**_params()) + conn.close() + return True + except Exception: + return False diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..e516e6f --- /dev/null +++ b/app/main.py @@ -0,0 +1,34 @@ +import logging +from contextlib import asynccontextmanager + +from fastapi import FastAPI + +from app.db import check_db + +logger = logging.getLogger("pops") + + +@asynccontextmanager +async def lifespan(app: FastAPI): + if check_db(): + logger.info("Database connection OK") + else: + logger.warning("Database unreachable — check MYSQL_* environment variables") + yield + + +app = FastAPI(title="POPS", lifespan=lifespan) + + +@app.get("/") +def root(): + return {"message": "Hello from POPS"} + + +@app.get("/health") +def health(): + db_ok = check_db() + return { + "status": "ok" if db_ok else "degraded", + "db": "connected" if db_ok else "unreachable", + } diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..df519fc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ +services: + db: + image: mysql:8.2 + restart: unless-stopped + env_file: .env + volumes: + - mysql_data:/var/lib/mysql + - ./db.sql:/docker-entrypoint-initdb.d/01_schema.sql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent"] + interval: 10s + timeout: 5s + retries: 10 + start_period: 30s + + app: + build: . + ports: + - "8720:8720" + env_file: .env + environment: + MYSQL_HOST: db # override localhost → compose service name + depends_on: + db: + condition: service_healthy + restart: unless-stopped + +volumes: + mysql_data: diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b15558d --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +fastapi==0.115.6 +uvicorn[standard]==0.34.0 +pymysql==1.1.1