feat: Podman support — auto-detect COMPOSE, CDI GPU override, podman-compose in setup.sh

This commit is contained in:
pyr0ball 2026-02-25 15:36:36 -08:00
parent 11d4f9a8b6
commit 41aef225cd
4 changed files with 96 additions and 11 deletions

View file

@ -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) | \

35
compose.podman-gpu.yml Normal file
View file

@ -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: []

View file

@ -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.
---

View file

@ -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