From 7b53e6fd75259ea1cfaddc39ae0cd42c9f15074e Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Wed, 25 Feb 2026 15:36:36 -0800 Subject: [PATCH] =?UTF-8?q?feat:=20Podman=20support=20=E2=80=94=20auto-det?= =?UTF-8?q?ect=20COMPOSE,=20CDI=20GPU=20override,=20podman-compose=20in=20?= =?UTF-8?q?setup.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 30 ++++++++++++++++++++++++------ compose.podman-gpu.yml | 35 +++++++++++++++++++++++++++++++++++ docs/backlog.md | 2 +- setup.sh | 40 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 compose.podman-gpu.yml diff --git a/Makefile b/Makefile index f3694a8..1e5a1f7 100644 --- a/Makefile +++ b/Makefile @@ -6,23 +6,41 @@ PROFILE ?= remote PYTHON ?= python3 -setup: ## Install dependencies (Docker, NVIDIA toolkit) +# Auto-detect container engine: prefer docker compose, fall back to podman +COMPOSE ?= $(shell \ + command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1 \ + && echo "docker compose" \ + || (command -v podman >/dev/null 2>&1 \ + && podman compose version >/dev/null 2>&1 \ + && echo "podman compose" \ + || echo "podman-compose")) + +# GPU profiles on Podman require a CDI override (rootless Podman can't use driver: nvidia) +# Generate CDI spec first: sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml +COMPOSE_FILES := -f compose.yml +ifneq (,$(findstring podman,$(COMPOSE))) + ifneq (,$(findstring gpu,$(PROFILE))) + COMPOSE_FILES := -f compose.yml -f compose.podman-gpu.yml + endif +endif + +setup: ## Install dependencies (Docker or Podman + NVIDIA toolkit) @bash setup.sh preflight: ## Check ports + system resources; write .env @$(PYTHON) scripts/preflight.py start: preflight ## Preflight check then start Peregrine (PROFILE=remote|cpu|single-gpu|dual-gpu) - docker compose --profile $(PROFILE) up -d + $(COMPOSE) $(COMPOSE_FILES) --profile $(PROFILE) up -d stop: ## Stop all Peregrine services - docker compose down + $(COMPOSE) down restart: preflight ## Preflight check then restart all services - docker compose down && docker compose --profile $(PROFILE) up -d + $(COMPOSE) down && $(COMPOSE) $(COMPOSE_FILES) --profile $(PROFILE) up -d logs: ## Tail app logs - docker compose logs -f app + $(COMPOSE) logs -f app test: ## Run the test suite $(PYTHON) -m pytest tests/ -v @@ -30,7 +48,7 @@ test: ## Run the test suite clean: ## Remove containers, images, and data volumes (DESTRUCTIVE) @echo "WARNING: This will delete all Peregrine containers and data." @read -p "Type 'yes' to confirm: " confirm && [ "$$confirm" = "yes" ] - docker compose down --rmi local --volumes + $(COMPOSE) down --rmi local --volumes help: ## Show this help @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ diff --git a/compose.podman-gpu.yml b/compose.podman-gpu.yml new file mode 100644 index 0000000..46d5465 --- /dev/null +++ b/compose.podman-gpu.yml @@ -0,0 +1,35 @@ +# compose.podman-gpu.yml — Podman GPU override +# +# Replaces Docker-specific `driver: nvidia` reservations with CDI device specs +# for rootless Podman. Apply automatically via `make start PROFILE=single-gpu` +# when podman/podman-compose is detected, or manually: +# podman-compose -f compose.yml -f compose.podman-gpu.yml --profile single-gpu up -d +# +# Prerequisites: +# sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml +# (requires nvidia-container-toolkit >= 1.14) +# +services: + ollama-gpu: + devices: + - nvidia.com/gpu=0 + deploy: + resources: + reservations: + devices: [] + + vision: + devices: + - nvidia.com/gpu=0 + deploy: + resources: + reservations: + devices: [] + + vllm: + devices: + - nvidia.com/gpu=1 + deploy: + resources: + reservations: + devices: [] diff --git a/docs/backlog.md b/docs/backlog.md index 6f2d0ab..53da425 100644 --- a/docs/backlog.md +++ b/docs/backlog.md @@ -43,7 +43,7 @@ Unscheduled ideas and deferred features. Roughly grouped by area. ## Container Runtime -- **Podman support** — Update `Makefile` to auto-detect `docker compose` vs `podman-compose` (e.g. `COMPOSE ?= $(shell command -v docker 2>/dev/null && echo "docker compose" || echo "podman-compose")`). Note in README that rootless Podman requires CDI GPU device spec (`nvidia.com/gpu=all`) instead of `runtime: nvidia` in `compose.yml`. +- ~~**Podman support**~~ — ✅ Done: `Makefile` auto-detects `docker compose` / `podman compose` / `podman-compose`; `compose.podman-gpu.yml` CDI override for GPU profiles; `setup.sh` detects existing Podman and skips Docker install. - **FastAPI migration path** — When concurrent-user scale demands it: port Streamlit pages to FastAPI + React/HTMX, keep `scripts/` layer unchanged, replace daemon threads with Celery + Redis. The `scripts/` separation already makes this clean. --- diff --git a/setup.sh b/setup.sh index 6d41f9c..02248ac 100755 --- a/setup.sh +++ b/setup.sh @@ -64,6 +64,35 @@ install_git() { success "git installed." } +# ── Podman detection ─────────────────────────────────────────────────────────── +# If Podman is already present, skip Docker entirely and ensure podman-compose is available. +check_podman() { + if ! cmd_exists podman; then return 1; fi + success "Podman detected ($(podman --version)) — skipping Docker install." + # Ensure a compose provider is available + if podman compose version &>/dev/null 2>&1; then + success "podman compose available." + elif cmd_exists podman-compose; then + success "podman-compose available." + else + info "Installing podman-compose…" + case "$DISTRO_FAMILY" in + debian) $SUDO apt-get install -y podman-compose 2>/dev/null \ + || pip3 install --user podman-compose ;; + fedora) $SUDO dnf install -y podman-compose 2>/dev/null \ + || pip3 install --user podman-compose ;; + arch) $SUDO pacman -Sy --noconfirm podman-compose 2>/dev/null \ + || pip3 install --user podman-compose ;; + macos) brew install podman-compose 2>/dev/null \ + || pip3 install --user podman-compose ;; + esac + success "podman-compose installed." + fi + warn "GPU profiles (single-gpu, dual-gpu) require CDI setup:" + warn " sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml" + return 0 +} + # ── Docker ───────────────────────────────────────────────────────────────────── install_docker_linux_debian() { $SUDO apt-get update -q @@ -196,9 +225,12 @@ main() { echo "" install_git - install_docker - check_compose - install_nvidia_toolkit + # Podman takes precedence if already installed; otherwise install Docker + if ! check_podman; then + install_docker + check_compose + install_nvidia_toolkit + fi setup_env echo "" @@ -207,7 +239,7 @@ main() { echo -e " ${GREEN}Next steps:${NC}" echo -e " 1. Edit ${YELLOW}.env${NC} to set your preferred ports and model paths" echo -e " 2. Start Peregrine:" - echo -e " ${YELLOW}docker compose --profile remote up -d${NC}" + echo -e " ${YELLOW}make start${NC} (auto-detects Docker or Podman)" echo -e " 3. Open ${YELLOW}http://localhost:8501${NC} — the setup wizard will guide you" echo "" if groups "$USER" 2>/dev/null | grep -q docker; then