feat(runpod): scaffold reproducible RunPod ComfyUI setup
This commit is contained in:
@@ -17,6 +17,17 @@ The format is inspired by Keep a Changelog and SemVer.
|
||||
- `.github/PULL_REQUEST_TEMPLATE.md`
|
||||
- `.github/ISSUE_TEMPLATE/release_checklist.md`
|
||||
- `docs/RELEASE_NOTES_TEMPLATE.md`
|
||||
- RunPod_Comfy implementation scaffold:
|
||||
- `Runpod_Comfy/README.md`
|
||||
- `Runpod_Comfy/docker/Dockerfile`
|
||||
- `Runpod_Comfy/docker/start.sh`
|
||||
- `Runpod_Comfy/scripts/bootstrap.sh`
|
||||
- `Runpod_Comfy/scripts/install_custom_nodes.sh`
|
||||
- `Runpod_Comfy/scripts/download_models.sh`
|
||||
- `Runpod_Comfy/config/comfyui.lock`
|
||||
- `Runpod_Comfy/config/custom_nodes.lock.json`
|
||||
- `Runpod_Comfy/config/models.json`
|
||||
- `Runpod_Comfy/docs/DEPLOY_RUNPOD.md`
|
||||
|
||||
## [0.1.0] - 2026-02-14
|
||||
|
||||
|
||||
@@ -22,6 +22,13 @@ The code for the Easy Resize node is inspired by the Resize Image V2 node from C
|
||||
- **Error Handling**: Fallbacks for missing/invalid JSON in Wan 2.2 Easy Prompt; validation for aspect ratios and divisibility in Easy Resize.
|
||||
- **Compatibility**: Works with ComfyUI-Manager for easy installation via Git URL. No additional dependencies beyond standard Python and ComfyUI libraries.
|
||||
|
||||
## RunPod
|
||||
|
||||
A dedicated RunPod setup scaffold is available in `Runpod_Comfy/`.
|
||||
|
||||
- Entry guide: `Runpod_Comfy/README.md`
|
||||
- Deploy notes: `Runpod_Comfy/docs/DEPLOY_RUNPOD.md`
|
||||
|
||||
## Release & Stability
|
||||
|
||||
For production usage, install a pinned stable tag/commit instead of following moving branch heads.
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# Runpod_Comfy
|
||||
|
||||
Production-oriented scaffold for running ComfyUI on RunPod with pinned versions.
|
||||
|
||||
## Goals
|
||||
|
||||
- Reproducible ComfyUI runtime
|
||||
- Clear version pinning for ComfyUI + custom nodes
|
||||
- Optional model bootstrap from URLs
|
||||
- Easy promotion from test to stable
|
||||
|
||||
## Structure
|
||||
|
||||
- `docker/` → image/runtime entrypoint
|
||||
- `config/` → lock files and model manifests
|
||||
- `scripts/` → bootstrap installers
|
||||
- `docs/` → requirements and references
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1) Pin ComfyUI version
|
||||
|
||||
Edit `config/comfyui.lock`:
|
||||
|
||||
```ini
|
||||
COMFYUI_REPO=https://github.com/comfyanonymous/ComfyUI.git
|
||||
COMFYUI_REF=master
|
||||
```
|
||||
|
||||
Set `COMFYUI_REF` to a commit SHA for stability.
|
||||
|
||||
### 2) Add custom nodes
|
||||
|
||||
Edit `config/custom_nodes.lock.json`.
|
||||
|
||||
### 3) Add models (optional)
|
||||
|
||||
Edit `config/models.json`.
|
||||
|
||||
### 4) Build image
|
||||
|
||||
```bash
|
||||
docker build -t comfyui-koolook:runpod-v1 -f Runpod_Comfy/docker/Dockerfile .
|
||||
```
|
||||
|
||||
### 5) Run locally (smoke test)
|
||||
|
||||
```bash
|
||||
docker run --rm -it -p 8188:8188 \
|
||||
-e COMFYUI_WORKDIR=/workspace/ComfyUI \
|
||||
comfyui-koolook:runpod-v1
|
||||
```
|
||||
|
||||
## Runtime env vars
|
||||
|
||||
- `COMFYUI_PORT` (default: `8188`)
|
||||
- `COMFYUI_WORKDIR` (default: `/workspace/ComfyUI`)
|
||||
- `RUNPOD_VOLUME_ROOT` (default: `/workspace`)
|
||||
- `HF_TOKEN` (optional for gated HuggingFace models)
|
||||
- `CIVITAI_TOKEN` (optional)
|
||||
|
||||
## Notes
|
||||
|
||||
- This scaffold is intentionally conservative and explicit.
|
||||
- For production users, pin refs to commits/tags before release.
|
||||
@@ -0,0 +1,3 @@
|
||||
# Pin ComfyUI source and ref for reproducible builds
|
||||
COMFYUI_REPO=https://github.com/comfyanonymous/ComfyUI.git
|
||||
COMFYUI_REF=master
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"nodes": [
|
||||
{
|
||||
"id": "comfyui-koolook",
|
||||
"repo": "https://github.com/malkuthro/ComfyUI-Koolook.git",
|
||||
"ref": "main",
|
||||
"target_dir": "ComfyUI-Koolook",
|
||||
"install": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": 1,
|
||||
"models": [
|
||||
{
|
||||
"name": "example_sdxl_checkpoint",
|
||||
"url": "https://example.com/path/to/model.safetensors",
|
||||
"dest": "models/checkpoints/model.safetensors",
|
||||
"sha256": "",
|
||||
"enabled": false
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
FROM runpod/pytorch:2.6.0-py3.11-cuda12.4.1-devel-ubuntu22.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
COMFYUI_PORT=8188 \
|
||||
COMFYUI_WORKDIR=/workspace/ComfyUI \
|
||||
RUNPOD_VOLUME_ROOT=/workspace
|
||||
|
||||
WORKDIR /opt/bootstrap
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
git curl ca-certificates jq \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY Runpod_Comfy /opt/bootstrap/Runpod_Comfy
|
||||
|
||||
RUN chmod +x /opt/bootstrap/Runpod_Comfy/scripts/*.sh /opt/bootstrap/Runpod_Comfy/docker/start.sh
|
||||
|
||||
EXPOSE 8188
|
||||
|
||||
ENTRYPOINT ["/opt/bootstrap/Runpod_Comfy/docker/start.sh"]
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=/opt/bootstrap/Runpod_Comfy
|
||||
WORKDIR="${COMFYUI_WORKDIR:-/workspace/ComfyUI}"
|
||||
PORT="${COMFYUI_PORT:-8188}"
|
||||
|
||||
"$ROOT/scripts/bootstrap.sh"
|
||||
|
||||
cd "$WORKDIR"
|
||||
|
||||
exec python3 main.py --listen 0.0.0.0 --port "$PORT"
|
||||
@@ -0,0 +1,34 @@
|
||||
# Deploy on RunPod
|
||||
|
||||
## 1) Build and push image
|
||||
|
||||
Use GitHub Container Registry or Docker Hub.
|
||||
|
||||
Example (GHCR):
|
||||
|
||||
```bash
|
||||
docker build -t ghcr.io/malkuthro/comfyui-koolook:runpod-v1 -f Runpod_Comfy/docker/Dockerfile .
|
||||
docker push ghcr.io/malkuthro/comfyui-koolook:runpod-v1
|
||||
```
|
||||
|
||||
## 2) Create RunPod template
|
||||
|
||||
- Container image: `ghcr.io/malkuthro/comfyui-koolook:runpod-v1`
|
||||
- Exposed HTTP port: `8188`
|
||||
- Volume mount: `/workspace` (recommended)
|
||||
|
||||
## 3) Optional env vars
|
||||
|
||||
- `COMFYUI_PORT=8188`
|
||||
- `COMFYUI_WORKDIR=/workspace/ComfyUI`
|
||||
- `HF_TOKEN=...` (if needed)
|
||||
- `CIVITAI_TOKEN=...` (if needed)
|
||||
|
||||
## 4) First boot expectations
|
||||
|
||||
On first start:
|
||||
- ComfyUI is cloned at pinned ref from `config/comfyui.lock`
|
||||
- custom nodes are installed from `config/custom_nodes.lock.json`
|
||||
- models are downloaded from `config/models.json` (enabled entries only)
|
||||
|
||||
Subsequent starts reuse existing files from volume storage.
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=/opt/bootstrap/Runpod_Comfy
|
||||
WORKDIR="${COMFYUI_WORKDIR:-/workspace/ComfyUI}"
|
||||
mkdir -p "$WORKDIR"
|
||||
|
||||
source "$ROOT/config/comfyui.lock"
|
||||
|
||||
if [[ ! -f "$WORKDIR/main.py" ]]; then
|
||||
echo "[bootstrap] Cloning ComfyUI from $COMFYUI_REPO"
|
||||
git clone "$COMFYUI_REPO" "$WORKDIR"
|
||||
fi
|
||||
|
||||
cd "$WORKDIR"
|
||||
|
||||
echo "[bootstrap] Checking out ComfyUI ref: $COMFYUI_REF"
|
||||
git fetch --all --tags || true
|
||||
git checkout "$COMFYUI_REF"
|
||||
|
||||
python3 -m pip install --upgrade pip
|
||||
python3 -m pip install -r requirements.txt
|
||||
|
||||
"$ROOT/scripts/install_custom_nodes.sh"
|
||||
"$ROOT/scripts/download_models.sh"
|
||||
|
||||
echo "[bootstrap] done"
|
||||
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=/opt/bootstrap/Runpod_Comfy
|
||||
WORKDIR="${COMFYUI_WORKDIR:-/workspace/ComfyUI}"
|
||||
LOCK="$ROOT/config/models.json"
|
||||
|
||||
if [[ ! -f "$LOCK" ]]; then
|
||||
echo "[models] lock file not found: $LOCK"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
COUNT=$(jq '.models | length' "$LOCK")
|
||||
for ((i=0; i<COUNT; i++)); do
|
||||
ENABLED=$(jq -r ".models[$i].enabled // true" "$LOCK")
|
||||
[[ "$ENABLED" != "true" ]] && continue
|
||||
|
||||
NAME=$(jq -r ".models[$i].name" "$LOCK")
|
||||
URL=$(jq -r ".models[$i].url" "$LOCK")
|
||||
DEST_REL=$(jq -r ".models[$i].dest" "$LOCK")
|
||||
SHA256=$(jq -r ".models[$i].sha256 // \"\"" "$LOCK")
|
||||
|
||||
DEST="$WORKDIR/$DEST_REL"
|
||||
mkdir -p "$(dirname "$DEST")"
|
||||
|
||||
if [[ -f "$DEST" ]]; then
|
||||
echo "[models] exists: $NAME ($DEST_REL), skipping"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "[models] downloading: $NAME"
|
||||
curl -L --fail "$URL" -o "$DEST"
|
||||
|
||||
if [[ -n "$SHA256" ]]; then
|
||||
echo "$SHA256 $DEST" | sha256sum -c -
|
||||
fi
|
||||
done
|
||||
|
||||
echo "[models] done"
|
||||
@@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=/opt/bootstrap/Runpod_Comfy
|
||||
WORKDIR="${COMFYUI_WORKDIR:-/workspace/ComfyUI}"
|
||||
NODES_DIR="$WORKDIR/custom_nodes"
|
||||
LOCK="$ROOT/config/custom_nodes.lock.json"
|
||||
|
||||
mkdir -p "$NODES_DIR"
|
||||
|
||||
if [[ ! -f "$LOCK" ]]; then
|
||||
echo "[custom_nodes] lock file not found: $LOCK"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
COUNT=$(jq '.nodes | length' "$LOCK")
|
||||
for ((i=0; i<COUNT; i++)); do
|
||||
REPO=$(jq -r ".nodes[$i].repo" "$LOCK")
|
||||
REF=$(jq -r ".nodes[$i].ref" "$LOCK")
|
||||
TARGET=$(jq -r ".nodes[$i].target_dir" "$LOCK")
|
||||
|
||||
[[ -z "$TARGET" || "$TARGET" == "null" ]] && TARGET=$(basename "$REPO" .git)
|
||||
|
||||
DST="$NODES_DIR/$TARGET"
|
||||
|
||||
if [[ ! -d "$DST/.git" ]]; then
|
||||
echo "[custom_nodes] cloning $REPO -> $DST"
|
||||
git clone "$REPO" "$DST"
|
||||
fi
|
||||
|
||||
pushd "$DST" >/dev/null
|
||||
git fetch --all --tags || true
|
||||
git checkout "$REF"
|
||||
|
||||
if [[ -f requirements.txt ]]; then
|
||||
python3 -m pip install -r requirements.txt || true
|
||||
fi
|
||||
|
||||
popd >/dev/null
|
||||
done
|
||||
|
||||
echo "[custom_nodes] done"
|
||||
Reference in New Issue
Block a user