automated update: 2026-06-10 19:47:45
This commit is contained in:
@@ -0,0 +1,9 @@
|
|||||||
|
.git
|
||||||
|
.env
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
||||||
|
.venv
|
||||||
|
.if_cache
|
||||||
|
frigate_train
|
||||||
|
*.md
|
||||||
|
|
||||||
+13
-13
@@ -2,49 +2,49 @@ FROM nvidia/cuda:12.4.1-runtime-ubuntu22.04
|
|||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# Install core dependencies
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
software-properties-common \
|
software-properties-common \
|
||||||
&& add-apt-repository ppa:deadsnakes/ppa -y \
|
&& add-apt-repository ppa:deadsnakes/ppa -y \
|
||||||
&& apt-get update && apt-get install -y --no-install-recommends \
|
&& apt-get update && apt-get install -y --no-install-recommends \
|
||||||
python3.12 \
|
python3.12 python3.12-venv python3.12-dev \
|
||||||
python3.12-venv \
|
libgl1 libglib2.0-0 libxext6 git curl g++ tini \
|
||||||
python3.12-dev \
|
|
||||||
libgl1 \
|
|
||||||
libglib2.0-0 \
|
|
||||||
libxext6 \
|
|
||||||
git \
|
|
||||||
curl \
|
|
||||||
g++ \
|
|
||||||
tini \
|
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& ln -sf /usr/bin/python3.12 /usr/bin/python \
|
&& ln -sf /usr/bin/python3.12 /usr/bin/python \
|
||||||
&& ln -sf /usr/bin/python3.12 /usr/bin/python3
|
&& ln -sf /usr/bin/python3.12 /usr/bin/python3
|
||||||
|
|
||||||
|
# Install uv and move to path
|
||||||
RUN curl -LsSf https://astral.sh/uv/install.sh | sh \
|
RUN curl -LsSf https://astral.sh/uv/install.sh | sh \
|
||||||
&& cp /root/.local/bin/uv /usr/local/bin/uv \
|
&& cp /root/.local/bin/uv /usr/local/bin/uv \
|
||||||
&& chmod 755 /usr/local/bin/uv
|
&& chmod 755 /usr/local/bin/uv
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Clone, sync, and add dependencies
|
||||||
RUN git clone --depth 1 https://github.com/sudolulo/if_curator_headless.git . \
|
RUN git clone --depth 1 https://github.com/sudolulo/if_curator_headless.git . \
|
||||||
&& uv sync --extra gpu \
|
&& uv sync --extra gpu \
|
||||||
&& uv add croniter \
|
&& uv add croniter \
|
||||||
&& uv cache clean
|
&& uv cache clean
|
||||||
|
|
||||||
|
# Copy scripts and modified CLI
|
||||||
COPY entrypoint.sh scheduler.py /app/
|
COPY entrypoint.sh scheduler.py /app/
|
||||||
|
COPY cli.py /app/if_curator/cli.py
|
||||||
RUN chmod +x /app/entrypoint.sh
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
|
# Setup non-root user and persistent model paths
|
||||||
RUN groupadd -g 568 apps \
|
RUN groupadd -g 568 apps \
|
||||||
&& useradd -u 568 -g apps -m -s /bin/bash appuser \
|
&& useradd -u 568 -g apps -m -s /bin/bash appuser \
|
||||||
&& chown -R appuser:apps /app
|
&& mkdir -p /models/.insightface /models/huggingface \
|
||||||
|
&& chown -R appuser:apps /app /models
|
||||||
|
|
||||||
USER appuser
|
USER appuser
|
||||||
|
|
||||||
|
# Baked-in configurations: User only needs to mount /models
|
||||||
ENV FORCE_CPU=false \
|
ENV FORCE_CPU=false \
|
||||||
HF_HOME=/models/huggingface \
|
HF_HOME=/models/huggingface \
|
||||||
INSIGHTFACE_HOME=/models/insightface
|
INSIGHTFACE_HOME=/models
|
||||||
|
|
||||||
HEALTHCHECK --interval=1h --timeout=10s --start-period=60s --retries=3 \
|
HEALTHCHECK --interval=5m --timeout=10s --start-period=600s --retries=3 \
|
||||||
CMD test -f /app/entrypoint.sh || exit 1
|
CMD test -f /app/entrypoint.sh || exit 1
|
||||||
|
|
||||||
ENTRYPOINT ["tini", "--", "/app/entrypoint.sh"]
|
ENTRYPOINT ["tini", "--", "/app/entrypoint.sh"]
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# --- Configuration ---
|
||||||
|
IMAGE_NAME="ghcr.io/sudolulo/if-curator-headless"
|
||||||
|
TAG="latest"
|
||||||
|
COMMIT_MSG="automated update: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
|
|
||||||
|
# --- 1. Git Commit & Push ---
|
||||||
|
echo "💾 Committing changes to Git..."
|
||||||
|
git add .
|
||||||
|
if ! git diff-index --quiet HEAD --; then
|
||||||
|
git commit -m "$COMMIT_MSG"
|
||||||
|
git push
|
||||||
|
echo "✅ Changes pushed to GitHub."
|
||||||
|
else
|
||||||
|
echo "ℹ️ No changes to commit."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- 2. Build Docker ---
|
||||||
|
echo "🔧 Building image (no cache)..."
|
||||||
|
docker build --no-cache -t ${IMAGE_NAME}:${TAG} .
|
||||||
|
|
||||||
|
# --- 3. Push to GHCR ---
|
||||||
|
echo "📤 Pushing to GHCR..."
|
||||||
|
docker push ${IMAGE_NAME}:${TAG}
|
||||||
|
|
||||||
|
# --- 4. Success UI ---
|
||||||
|
echo ""
|
||||||
|
echo " ╔══════════════════════════════════════════════════╗"
|
||||||
|
echo " ║ ║"
|
||||||
|
echo " ║ ✅ GIT & DOCKER DEPLOY COMPLETE ║"
|
||||||
|
echo " ║ ║"
|
||||||
|
echo " ╚══════════════════════════════════════════════════╝"
|
||||||
|
echo ""
|
||||||
|
|
||||||
+5
-5
@@ -7,16 +7,16 @@ export PYTHONUNBUFFERED=1
|
|||||||
check_models() {
|
check_models() {
|
||||||
echo "📦 Checking models..."
|
echo "📦 Checking models..."
|
||||||
|
|
||||||
if [ -d "/models/insightface/models/buffalo_l" ]; then
|
if [ -d "/models/.insightface/models/buffalo_l" ]; then
|
||||||
echo " ✅ InsightFace Buffalo_L: downloaded"
|
echo " ✅ InsightFace Buffalo_L: present"
|
||||||
else
|
else
|
||||||
echo " ⬇️ InsightFace Buffalo_L: downloading (~300MB)..."
|
echo " ⬇️ InsightFace Buffalo_L: not found — will download on first run (~300MB)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -d "/models/huggingface/hub" ] && [ "$(find /models/huggingface/hub -maxdepth 1 -type d 2>/dev/null | wc -l)" -gt 1 ]; then
|
if [ -d "/models/huggingface/hub" ] && [ "$(find /models/huggingface/hub -maxdepth 1 -type d 2>/dev/null | wc -l)" -gt 1 ]; then
|
||||||
echo " ✅ HuggingFace models: downloaded"
|
echo " ✅ HuggingFace models: present"
|
||||||
else
|
else
|
||||||
echo " ⬇️ HuggingFace models: downloading (SigLIP ~1GB, YOLOv9c ~500MB)..."
|
echo " ⬇️ HuggingFace models: not found — will download on first run (SigLIP ~1GB, YOLOv9c ~500MB)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🚀 Starting if-curator..."
|
echo "🚀 Starting if-curator..."
|
||||||
|
|||||||
+17
-51
@@ -1,9 +1,4 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
|
||||||
Simple in-container scheduler using croniter + sleep.
|
|
||||||
No cron daemon, no sudo, no root needed.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
@@ -18,39 +13,25 @@ except ImportError:
|
|||||||
|
|
||||||
SCHEDULE = os.environ["CRON_SCHEDULE"]
|
SCHEDULE = os.environ["CRON_SCHEDULE"]
|
||||||
MODELS_DIR = os.environ.get("HF_HOME", "/models/huggingface")
|
MODELS_DIR = os.environ.get("HF_HOME", "/models/huggingface")
|
||||||
INSIGHTFACE_DIR = os.environ.get("INSIGHTFACE_HOME", "/models/insightface")
|
# Changed to /models to match the updated INSIGHTFACE_HOME pointing to /models
|
||||||
|
INSIGHTFACE_BASE = os.environ.get("INSIGHTFACE_HOME", "/models")
|
||||||
|
|
||||||
# Ensure all subprocess output appears in docker logs
|
|
||||||
RUN_ENV = {**os.environ, "PYTHONUNBUFFERED": "1"}
|
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)
|
||||||
|
|
||||||
check_models() {
|
hf_hub = Path(MODELS_DIR) / "hub"
|
||||||
echo "📦 Checking models..."
|
if hf_hub.exists() and any(hf_hub.iterdir()):
|
||||||
|
print(" ✅ HuggingFace models: present", flush=True)
|
||||||
if [ -d "/models/insightface/models/buffalo_l" ]; then
|
else:
|
||||||
echo " ✅ InsightFace Buffalo_L: present"
|
print(" ⬇️ HuggingFace models: not found — will download", flush=True)
|
||||||
else
|
print("🚀 Starting if-curator...", flush=True)
|
||||||
echo " ⬇️ InsightFace Buffalo_L: not found — will download on first run (~300MB)"
|
|
||||||
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..."
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def calc_time_display(seconds):
|
|
||||||
"""Convert seconds to human-readable time."""
|
|
||||||
hours = int(seconds // 3600)
|
|
||||||
minutes = int((seconds % 3600) // 60)
|
|
||||||
if hours > 0:
|
|
||||||
return f"{hours}h {minutes}m"
|
|
||||||
return f"{minutes}m"
|
|
||||||
|
|
||||||
|
|
||||||
NOW = time.time()
|
NOW = time.time()
|
||||||
cron = croniter(SCHEDULE, NOW)
|
cron = croniter(SCHEDULE, NOW)
|
||||||
@@ -61,22 +42,7 @@ while True:
|
|||||||
if now >= next_run:
|
if now >= next_run:
|
||||||
print(f"\n▶ [{time.strftime('%Y-%m-%d %H:%M:%S')}] Starting if-curator...", flush=True)
|
print(f"\n▶ [{time.strftime('%Y-%m-%d %H:%M:%S')}] Starting if-curator...", flush=True)
|
||||||
check_models()
|
check_models()
|
||||||
result = subprocess.run(
|
subprocess.run(["uv", "run", "if-curator"], env=RUN_ENV)
|
||||||
["uv", "run", "if-curator"],
|
|
||||||
env=RUN_ENV,
|
|
||||||
)
|
|
||||||
if result.returncode == 0:
|
|
||||||
print("✅ Run complete.", flush=True)
|
|
||||||
else:
|
|
||||||
print(f"⚠️ Run exited with code {result.returncode}", flush=True)
|
|
||||||
|
|
||||||
next_run = cron.get_next(float)
|
next_run = cron.get_next(float)
|
||||||
wait = next_run - time.time()
|
time.sleep(60)
|
||||||
if wait > 0:
|
|
||||||
print(f"▶ Next run: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(next_run))} (in {calc_time_display(wait)})", flush=True)
|
|
||||||
continue
|
|
||||||
|
|
||||||
wait = next_run - now
|
|
||||||
print(f"▶ Next run: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(next_run))} (in {calc_time_display(wait)})", flush=True)
|
|
||||||
time.sleep(min(wait, 3600))
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user