deploy: Dockerfile, Compose pro Rolle, LiteLLM, Prometheus/Alertmanager, Canary-Prober, n8n-Workflows
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
LLAMACPP_REF=b6000
|
||||
CUDA_VERSION=12.4.0
|
||||
CUDA_DOCKER_ARCH=52;61
|
||||
MODELS_DIR=/srv/models
|
||||
EMBED_GGUF=Qwen3-Embedding-0.6B-Q8_0.gguf
|
||||
EMBED_POOLING=last
|
||||
RERANK_GGUF=bge-reranker-v2-m3-Q8_0.gguf
|
||||
CHAT_GGUF=Qwen3-4B-Q4_K_M.gguf
|
||||
@@ -0,0 +1,86 @@
|
||||
# Rollen "gpu-embed" und "gpu-small" (VMs mit Quadro P2000 / M4000): llama.cpp-Server.
|
||||
# Maxwell (sm_52) und Pascal (sm_61) brauchen CUDA 12.x – daher eigener Build mit festen Architekturen.
|
||||
# Profile: embed (Embedding + Rerank), chat (Verifier/Signatur), z. B. `docker compose --profile embed up -d`
|
||||
name: knaster-gpu-llamacpp
|
||||
|
||||
x-llamacpp: &llamacpp
|
||||
build:
|
||||
context: https://github.com/ggml-org/llama.cpp.git#${LLAMACPP_REF:-b6000}
|
||||
dockerfile: .devops/cuda.Dockerfile
|
||||
target: server
|
||||
args:
|
||||
CUDA_VERSION: ${CUDA_VERSION:-12.4.0}
|
||||
CUDA_DOCKER_ARCH: ${CUDA_DOCKER_ARCH:-52;61}
|
||||
image: knaster/llamacpp-server:${LLAMACPP_REF:-b6000}-cu12
|
||||
restart: unless-stopped
|
||||
labels: {autoheal: "true"}
|
||||
volumes:
|
||||
- ${MODELS_DIR:-/srv/models}:/models:ro
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices: [{driver: nvidia, count: 1, capabilities: [gpu]}]
|
||||
|
||||
services:
|
||||
llamacpp-embed:
|
||||
<<: *llamacpp
|
||||
container_name: llamacpp-embed
|
||||
profiles: ["embed"]
|
||||
command: ["-m", "/models/${EMBED_GGUF:-Qwen3-Embedding-0.6B-Q8_0.gguf}", "--embedding",
|
||||
"--pooling", "${EMBED_POOLING:-last}", "-c", "8192", "-ub", "8192", "-ngl", "99",
|
||||
"--alias", "embed-default", "--metrics", "--host", "0.0.0.0", "--port", "8081"]
|
||||
ports: ["8081:8081"]
|
||||
healthcheck: &hc
|
||||
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8081/health"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
|
||||
llamacpp-rerank:
|
||||
<<: *llamacpp
|
||||
container_name: llamacpp-rerank
|
||||
profiles: ["embed"]
|
||||
command: ["-m", "/models/${RERANK_GGUF:-bge-reranker-v2-m3-Q8_0.gguf}", "--reranking", "-c", "8192",
|
||||
"-ub", "8192", "-ngl", "99", "--alias", "rerank-default", "--metrics", "--host", "0.0.0.0",
|
||||
"--port", "8082"]
|
||||
ports: ["8082:8082"]
|
||||
healthcheck:
|
||||
<<: *hc
|
||||
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8082/health"]
|
||||
|
||||
llamacpp-chat:
|
||||
<<: *llamacpp
|
||||
container_name: llamacpp-chat
|
||||
profiles: ["chat"]
|
||||
command: ["-m", "/models/${CHAT_GGUF:-Qwen3-4B-Q4_K_M.gguf}", "-c", "8192", "-ngl", "99",
|
||||
"--alias", "verifier-small", "--metrics", "--host", "0.0.0.0", "--port", "8080"]
|
||||
ports: ["8080:8080"]
|
||||
healthcheck:
|
||||
<<: *hc
|
||||
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/health"]
|
||||
|
||||
gpu-exporter:
|
||||
image: utkuozdemir/nvidia_gpu_exporter:1.2.1
|
||||
restart: unless-stopped
|
||||
ports: ["9835:9835"]
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices: [{driver: nvidia, count: all, capabilities: [gpu, utility]}]
|
||||
|
||||
node-exporter:
|
||||
image: prom/node-exporter:v1.8.1
|
||||
restart: unless-stopped
|
||||
command: ["--path.rootfs=/host", "--collector.textfile.directory=/textfile"]
|
||||
pid: host
|
||||
volumes:
|
||||
- /:/host:ro,rslave
|
||||
- /var/lib/node_exporter/textfile:/textfile:ro
|
||||
ports: ["9100:9100"]
|
||||
|
||||
autoheal:
|
||||
image: willfarrell/autoheal:1.2.0
|
||||
restart: unless-stopped
|
||||
environment: {AUTOHEAL_CONTAINER_LABEL: autoheal}
|
||||
volumes: ["/var/run/docker.sock:/var/run/docker.sock"]
|
||||
@@ -0,0 +1,9 @@
|
||||
SLOT_ALIAS=tier1-general
|
||||
VLLM_MODEL=Qwen/Qwen3-14B-AWQ
|
||||
MAX_MODEL_LEN=32768
|
||||
GPU_MEM_UTIL=0.90
|
||||
MAX_LORAS=4
|
||||
MAX_LORA_RANK=64
|
||||
MODELS_DIR=/srv/models
|
||||
ADAPTERS_DIR=/srv/adapters
|
||||
HF_TOKEN=
|
||||
@@ -0,0 +1,62 @@
|
||||
# Rolle "gpu-main" / "gpu-flex" (VM mit durchgereichter RTX 4000 Ada): vLLM mit Multi-LoRA.
|
||||
name: knaster-gpu-vllm
|
||||
|
||||
services:
|
||||
vllm:
|
||||
image: vllm/vllm-openai:${VLLM_TAG:-v0.10.0} # Engine-Updates laufen als Lifecycle-Kandidat
|
||||
container_name: vllm
|
||||
restart: unless-stopped
|
||||
labels: {autoheal: "true"}
|
||||
ipc: host
|
||||
env_file: .env
|
||||
environment:
|
||||
VLLM_ALLOW_RUNTIME_LORA_UPDATING: "True" # Adapter per /v1/load_lora_adapter nachladen
|
||||
command:
|
||||
- --model=${VLLM_MODEL:?VLLM_MODEL fehlt}
|
||||
- --served-model-name=${SLOT_ALIAS:?SLOT_ALIAS fehlt}
|
||||
- --max-model-len=${MAX_MODEL_LEN:-32768}
|
||||
- --gpu-memory-utilization=${GPU_MEM_UTIL:-0.90}
|
||||
- --enable-lora
|
||||
- --max-loras=${MAX_LORAS:-4}
|
||||
- --max-lora-rank=${MAX_LORA_RANK:-64}
|
||||
- --host=0.0.0.0
|
||||
- --port=8000
|
||||
volumes:
|
||||
- ${MODELS_DIR:-/srv/models}:/root/.cache/huggingface
|
||||
- ${ADAPTERS_DIR:-/srv/adapters}:/adapters:ro
|
||||
ports: ["8000:8000"]
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices: [{driver: nvidia, count: 1, capabilities: [gpu]}]
|
||||
healthcheck:
|
||||
test: ["CMD", "python3", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=4)"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 300s # Laden großer Modelle
|
||||
|
||||
gpu-exporter:
|
||||
image: utkuozdemir/nvidia_gpu_exporter:1.2.1
|
||||
restart: unless-stopped
|
||||
ports: ["9835:9835"]
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
devices: [{driver: nvidia, count: all, capabilities: [gpu, utility]}]
|
||||
|
||||
node-exporter:
|
||||
image: prom/node-exporter:v1.8.1
|
||||
restart: unless-stopped
|
||||
command: ["--path.rootfs=/host", "--collector.textfile.directory=/textfile"]
|
||||
pid: host
|
||||
volumes:
|
||||
- /:/host:ro,rslave
|
||||
- /var/lib/node_exporter/textfile:/textfile:ro
|
||||
ports: ["9100:9100"]
|
||||
|
||||
autoheal:
|
||||
image: willfarrell/autoheal:1.2.0
|
||||
restart: unless-stopped
|
||||
environment: {AUTOHEAL_CONTAINER_LABEL: autoheal, AUTOHEAL_START_PERIOD: "300"}
|
||||
volumes: ["/var/run/docker.sock:/var/run/docker.sock"]
|
||||
@@ -0,0 +1,18 @@
|
||||
KNASTER_VERSION=dev
|
||||
KNASTER_SITE=knaster
|
||||
KNASTER_API_TOKEN=change-me
|
||||
KNASTER_DRY_RUN=true
|
||||
KNASTER_CANARY_INTERVAL=60
|
||||
POSTGRES_PASSWORD=change-me
|
||||
LITELLM_API_KEY=change-me
|
||||
LITELLM_MASTER_KEY=change-me
|
||||
OPENROUTER_API_KEY=
|
||||
RERANK_URL=http://gpu-embed-1:8082
|
||||
NOTIFY_WEBHOOK_URL=
|
||||
KNASTER_JOB_WEBHOOK_URL=
|
||||
PORTAINER_HOST=
|
||||
PORTAINER_KEY=
|
||||
PROXMOX_URL=
|
||||
PROXMOX_TOKEN_ID=
|
||||
PROXMOX_TOKEN_SECRET=
|
||||
KNASTER_WEBHOOK_AUTH=Bearer change-me
|
||||
@@ -0,0 +1,104 @@
|
||||
# Rolle "infra" (LXC/VM auf einem i7-Node): Router, LiteLLM, Postgres, Monitoring.
|
||||
# Start: cp .env.example .env && docker compose up -d
|
||||
name: knaster-infra
|
||||
|
||||
x-restart: &restart
|
||||
restart: unless-stopped
|
||||
labels: {autoheal: "true"}
|
||||
|
||||
services:
|
||||
router:
|
||||
<<: *restart
|
||||
build:
|
||||
context: ../../..
|
||||
dockerfile: deploy/docker/router.Dockerfile
|
||||
image: knaster/router:${KNASTER_VERSION:-dev}
|
||||
env_file: .env
|
||||
environment:
|
||||
KNASTER_DB_URL: postgresql+psycopg://knaster:${POSTGRES_PASSWORD:?POSTGRES_PASSWORD fehlt}@postgres:5432/knaster
|
||||
KNASTER_SITE_DIR: /app/sites/${KNASTER_SITE:-knaster}
|
||||
LITELLM_BASE_URL: http://litellm:4000
|
||||
ports: ["8080:8080"]
|
||||
depends_on:
|
||||
postgres: {condition: service_healthy}
|
||||
litellm: {condition: service_started}
|
||||
|
||||
litellm:
|
||||
<<: *restart
|
||||
image: ghcr.io/berriai/litellm:${LITELLM_TAG:-main-stable} # vor Deployment auf feste Version pinnen
|
||||
command: ["--config", "/app/config.yaml", "--port", "4000"]
|
||||
env_file: .env
|
||||
volumes:
|
||||
- ../../litellm/config.yaml:/app/config.yaml:ro
|
||||
ports: ["4000:4000"]
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:4000/health/liveliness', timeout=4)"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
postgres:
|
||||
<<: *restart
|
||||
image: pgvector/pgvector:pg16
|
||||
environment:
|
||||
POSTGRES_USER: knaster
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?POSTGRES_PASSWORD fehlt}
|
||||
POSTGRES_DB: knaster
|
||||
volumes:
|
||||
- postgres:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U knaster -d knaster"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
prometheus:
|
||||
<<: *restart
|
||||
image: prom/prometheus:v2.53.0
|
||||
command:
|
||||
- --config.file=/etc/prometheus/prometheus.yml
|
||||
- --storage.tsdb.retention.time=15d
|
||||
- --web.enable-lifecycle
|
||||
volumes:
|
||||
- ../../prometheus:/etc/prometheus:ro
|
||||
- prometheus:/prometheus
|
||||
ports: ["9090:9090"]
|
||||
|
||||
alertmanager:
|
||||
<<: *restart
|
||||
image: prom/alertmanager:v0.27.0
|
||||
command: ["--config.file=/etc/alertmanager/alertmanager.yml"]
|
||||
volumes:
|
||||
- ../../alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
|
||||
- ./secrets/router_token:/etc/alertmanager/router_token:ro
|
||||
ports: ["9093:9093"]
|
||||
|
||||
grafana:
|
||||
<<: *restart
|
||||
image: grafana/grafana:11.1.0
|
||||
profiles: ["dashboards"]
|
||||
volumes:
|
||||
- grafana:/var/lib/grafana
|
||||
ports: ["3000:3000"]
|
||||
|
||||
pve-exporter:
|
||||
<<: *restart
|
||||
image: prompve/prometheus-pve-exporter:${PVE_EXPORTER_TAG:-latest} # vor Deployment pinnen
|
||||
profiles: ["proxmox"]
|
||||
volumes:
|
||||
- ./secrets/pve.yml:/etc/prometheus/pve.yml:ro
|
||||
ports: ["9221:9221"]
|
||||
|
||||
autoheal:
|
||||
restart: unless-stopped
|
||||
image: willfarrell/autoheal:1.2.0
|
||||
environment:
|
||||
AUTOHEAL_CONTAINER_LABEL: autoheal
|
||||
AUTOHEAL_INTERVAL: "15"
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
|
||||
volumes:
|
||||
postgres: {}
|
||||
prometheus: {}
|
||||
grafana: {}
|
||||
Reference in New Issue
Block a user