diff --git a/Dockerfile b/Dockerfile index 09b5a58..68fcc69 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,50 +1,28 @@ FROM nvidia/cuda:12.4.1-runtime-ubuntu22.04 - ENV DEBIAN_FRONTEND=noninteractive -# Install dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ - software-properties-common \ - && add-apt-repository ppa:deadsnakes/ppa -y \ - && apt-get update && apt-get install -y --no-install-recommends \ - python3.12 python3.12-venv python3.12-dev \ - libgl1 libglib2.0-0 libxext6 git curl g++ tini \ + python3.12 python3.12-venv python3.12-dev libgl1 libglib2.0-0 libxext6 git curl g++ tini \ && rm -rf /var/lib/apt/lists/* \ - && ln -sf /usr/bin/python3.12 /usr/bin/python \ && ln -sf /usr/bin/python3.12 /usr/bin/python3 -# Install uv RUN curl -LsSf https://astral.sh/uv/install.sh | sh \ - && cp /root/.local/bin/uv /usr/local/bin/uv \ - && chmod 755 /usr/local/bin/uv + && cp /root/.local/bin/uv /usr/local/bin/uv WORKDIR /app - -# Clone your repo (ensure this repo has the updated cli.py locally!) RUN git clone --depth 1 https://github.com/sudolulo/if_curator_headless.git . \ - && uv sync --extra gpu \ - && uv add croniter \ - && uv cache clean + && uv sync --extra gpu && uv add croniter && uv cache clean -# Copy helper scripts COPY entrypoint.sh scheduler.py /app/ RUN chmod +x /app/entrypoint.sh -# Setup non-root user and persistent model paths -RUN groupadd -g 568 apps \ - && useradd -u 568 -g apps -m -s /bin/bash appuser \ +RUN groupadd -g 568 apps && useradd -u 568 -g apps -m -s /bin/bash appuser \ && mkdir -p /models/.insightface /models/huggingface \ && chown -R appuser:apps /app /models USER appuser +ENV HF_HOME=/models/huggingface INSIGHTFACE_HOME=/models -# Baked-in configurations -ENV FORCE_CPU=false \ - HF_HOME=/models/huggingface \ - INSIGHTFACE_HOME=/models - -HEALTHCHECK --interval=5m --timeout=10s --start-period=600s --retries=3 \ - CMD test -f /app/entrypoint.sh || exit 1 - +HEALTHCHECK CMD test -f /app/entrypoint.sh || exit 1 ENTRYPOINT ["tini", "--", "/app/entrypoint.sh"] diff --git a/entrypoint.sh b/entrypoint.sh index 3951f69..75de659 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -1,48 +1,30 @@ #!/bin/bash set -e - export PYTHONUNBUFFERED=1 -# Function to log model status before each run check_models() { echo "šŸ“¦ Checking models..." - + # Paths updated to point to persistent root /models if [ -d "/models/.insightface/models/buffalo_l" ]; then echo " āœ… InsightFace Buffalo_L: present" else - echo " ā¬‡ļø InsightFace Buffalo_L: not found — will download on first run (~300MB)" + echo " ā¬‡ļø InsightFace Buffalo_L: downloading..." fi - - if [ -d "/models/huggingface/hub" ] && [ "$(find /models/huggingface/hub -maxdepth 1 -type d 2>/dev/null | wc -l)" -gt 1 ]; then - echo " āœ… HuggingFace models: present" - else - echo " ā¬‡ļø HuggingFace models: not found — will download on first run (SigLIP ~1GB, YOLOv9c ~500MB)" - fi - echo "šŸš€ Starting if-curator..." } -SCHEDULE="${CRON_SCHEDULE:-}" AUTO="${AUTO_MODE:-false}" - -# Check if interactive mode is viable if [ "$AUTO" != "true" ] && [ ! -t 0 ]; then - echo "āŒ AUTO_MODE is not enabled and no TTY is attached." - echo "āŒ Set AUTO_MODE=true for headless/automated runs." + echo "āŒ AUTO_MODE must be true for non-interactive execution." exit 1 fi -# Always run once on startup -echo "ā–¶ Running on startup..." check_models -uv run if-curator - -if [ -z "$SCHEDULE" ]; then - echo "ā–¶ No CRON_SCHEDULE set — exiting" - exit 0 +if [ -n "${CRON_SCHEDULE:-}" ]; then + echo "ā–¶ Switching to scheduled mode..." + exec uv run python3 /app/scheduler.py +else + echo "ā–¶ Running once..." + uv run python -m if_curator.cli fi -echo "ā–¶ CRON_SCHEDULE set to: $SCHEDULE" -echo "ā–¶ Switching to scheduled mode..." -exec uv run python3 /app/scheduler.py - diff --git a/scheduler.py b/scheduler.py index 96f5144..b2d3e5a 100644 --- a/scheduler.py +++ b/scheduler.py @@ -3,46 +3,23 @@ import os import sys import subprocess import time -from pathlib import Path - -try: - from croniter import croniter -except ImportError: - print("āŒ croniter not installed. Run: uv add croniter") - sys.exit(1) - -SCHEDULE = os.environ["CRON_SCHEDULE"] -MODELS_DIR = os.environ.get("HF_HOME", "/models/huggingface") -# Changed to /models to match the updated INSIGHTFACE_HOME pointing to /models -INSIGHTFACE_BASE = os.environ.get("INSIGHTFACE_HOME", "/models") +from croniter import croniter +SCHEDULE = os.environ.get("CRON_SCHEDULE", "0 3 * * SUN") RUN_ENV = {**os.environ, "PYTHONUNBUFFERED": "1"} -def check_models(): - print("šŸ“¦ Checking models...", flush=True) - buffalo = Path(INSIGHTFACE_BASE) / ".insightface" / "models" / "buffalo_l" - if buffalo.exists(): - print(" āœ… InsightFace Buffalo_L: present", flush=True) - else: - print(" ā¬‡ļø InsightFace Buffalo_L: not found — will download", flush=True) +def run_curator(): + print(f"\nā–¶ [{time.strftime('%Y-%m-%d %H:%M:%S')}] Starting if-curator...", flush=True) + subprocess.run(["uv", "run", "python", "-m", "if_curator.cli"], env=RUN_ENV) - hf_hub = Path(MODELS_DIR) / "hub" - if hf_hub.exists() and any(hf_hub.iterdir()): - print(" āœ… HuggingFace models: present", flush=True) - else: - print(" ā¬‡ļø HuggingFace models: not found — will download", flush=True) - print("šŸš€ Starting if-curator...", flush=True) - -NOW = time.time() -cron = croniter(SCHEDULE, NOW) +now = time.time() +cron = croniter(SCHEDULE, now) next_run = cron.get_next(float) +print(f"ā–¶ Scheduler active. Next run: {time.ctime(next_run)}") while True: - now = time.time() - if now >= next_run: - print(f"\nā–¶ [{time.strftime('%Y-%m-%d %H:%M:%S')}] Starting if-curator...", flush=True) - check_models() - subprocess.run(["uv", "run", "if-curator"], env=RUN_ENV) + if time.time() >= next_run: + run_curator() next_run = cron.get_next(float) time.sleep(60)