NVIDIA GPU에서 llama.cpp + OpenClaw AI 비서를 실행하는 컨테이너 오케스트레이션.
Container orchestration for running OpenClaw AI assistant with a self-hosted llama.cpp backend on NVIDIA GPUs.
┌──────────────────────────────────────────────────┐
│ democlaw-net │
│ │
│ ┌───────────┐ ┌──────────────────┐ │
│ │ llama.cpp │ │ OpenClaw │ │
│ │ :8000 │◄───────────│ :18789 │ │
│ │ (LLM/GPU) │ │ (AI dashboard) │ │
│ └───────────┘ └──────────────────┘ │
│ │ │
│ ┌─────────────────────────┘ │
│ │ MCP sidecar containers (optional) │
│ ▼ │
│ ┌────────────┐ ┌────────────┐ │
│ │ MarkItDown │ │ your-mcp │ ... │
│ │ MCP :3001 │ │ :4000 │ │
│ └────────────┘ └────────────┘ │
└──────────────────────────────────────────────────┘
| Container | Purpose | Host Port |
|---|---|---|
| llama.cpp | Gemma 4 E4B GGUF via OpenAI-compatible API (CUDA) | localhost:8000 |
| OpenClaw | AI assistant web dashboard (headless) | localhost:18789 |
| OpenClaw | Supergateway SSE endpoint | localhost:18791 |
| MCP sidecars | Optional tool servers (e.g., MarkItDown) | user-defined |
| Minimum | Recommended | |
|---|---|---|
| GPU | NVIDIA 8 GB VRAM (RTX 3070, RTX 4060 Ti) | 12 GB+ VRAM |
| NVIDIA Driver | 520+ (CUDA 11.8) | 560+ (CUDA 12.x) |
| RAM | 16 GB | 32 GB+ |
| Disk | 15 GB free | 30 GB+ free |
| Linux | Windows 11 | |
|---|---|---|
| OS | Ubuntu 22.04+, Debian 12+, Fedora 38+, RHEL 9+ | Windows 11 (22H2+) |
| Container Runtime | Docker 20.10+ or Podman 4.1+ | Docker Desktop (WSL2 backend) |
| GPU Support | NVIDIA Container Toolkit | Docker Desktop GPU support (built-in) |
| Shell | bash 4.0+ (pre-installed) | Git Bash (included with Git for Windows) |
| curl | pre-installed | pre-installed (Windows 11) |
CUDA Toolkit은 호스트에 설치할 필요 없습니다. llama.cpp 컨테이너 이미지에 포함되어 있습니다.
You do NOT need the CUDA Toolkit on the host. It is bundled inside the llama.cpp container image.
git clone https://github.com/JinwangMok/democlaw.git
cd democlaw
# (Optional) Copy and edit environment config
cp .env.example .env
# (Optional) Pre-download the model to see progress (~5.7 GB, first run only)
./scripts/download-model.sh
# Start the full stack. Weights are cached under ./.data on first run and
# reused on every subsequent run (no re-download).
# - Windows / RTX: llama.cpp Gemma 4 E4B GGUF
# - DGX Spark: vLLM NVFP4A16 Gemma 4 26B A4B MoE (jinwangmok/democlaw-spark-gemma4)
./scripts/start.sh
# Open the dashboard URL printed at the end
# Click "Connect" on first visit (auto-approved within ~2 seconds)git clone https://github.com/JinwangMok/democlaw.git
cd democlaw
# Start the full stack
scripts\start.bat
# Open the dashboard URL printed at the end# GPU check
nvidia-smi
# LLM API (use curl.exe on Windows PowerShell)
curl http://localhost:8000/v1/models
# OpenClaw dashboard — open in browser
# http://localhost:18789 (or the tokenized URL from start output)# Linux
./scripts/stop.sh
# Windows
scripts\stop.bat셸 스크립트를 직접 실행하는 것이 기본이지만, make가 설치되어 있다면 짧은 명령으로도 동일한 작업을 수행할 수 있습니다.
Shell scripts are the primary interface, but if make is available you can use shorthand commands instead:
| make | Shell equivalent | Description |
|---|---|---|
make start |
./scripts/start.sh |
전체 스택 시작 |
make stop |
./scripts/stop.sh |
전체 스택 중지 |
make restart |
stop → start | 스택 재시작 |
make build |
— | 컨테이너 이미지 빌드 (llama.cpp + OpenClaw) |
make build NO_CACHE=1 |
— | 캐시 없이 클린 빌드 |
make status |
— | 컨테이너 상태 확인 |
make logs |
— | 최근 50줄 로그 출력 (SERVICE=llamacpp|openclaw) |
make shell SERVICE=openclaw |
— | 컨테이너 셸 접속 |
make benchmark |
./scripts/benchmark-tps.sh |
LLM 처리량 벤치마크 |
make validate |
./scripts/validate-e2e.sh |
E2E 검증 파이프라인 |
make clean |
— | 컨테이너 + 이미지 제거 (모델 캐시 보존) |
make help |
— | 전체 타겟 목록 출력 |
# 예시: podman 사용 시
make start CONTAINER_RUNTIME=podmanNote:
make가 없어도scripts/디렉토리의 셸 스크립트로 동일하게 사용할 수 있습니다. Makefile은 편의용 래퍼입니다.
스택을 시작한 후 (./scripts/start.sh 또는 scripts\start.bat), 브라우저에서 대시보드 URL을 열고 Chat에서 다음과 같이 활용할 수 있습니다.
After starting the stack, open the dashboard URL in your browser and try these in the Chat:
출근 전 날씨를 확인하고 우산이 필요한지 물어봅니다.
서울 오늘 날씨 어때? 우산 가져가야 할까?
에이전트가 web_search 도구로 실시간 날씨를 검색하고, 비 예보 여부와 우산 조언을 한국어로 답변합니다.
업계 최신 동향을 빠르게 파악합니다.
2026년 3월 AI 업계 최신 뉴스 3개를 검색해서 요약해줘. 각 뉴스의 핵심을 한 줄로.
에이전트가 web_search로 최신 기사를 검색하고, 각 뉴스를 한 줄로 요약합니다.
업무 자동화용 스크립트를 작성합니다.
Write a Python function that calculates compound interest.
Parameters: principal, annual_rate, years, compounds_per_year.
Include an example usage.
에이전트가 함수 코드와 사용 예시를 생성합니다.
OpenClaw 에이전트는 다음 도구를 기본 탑재하고 있습니다:
| Tool | Description |
|---|---|
web_search |
웹 검색 (날씨, 뉴스, 정보 조회) |
web_fetch |
URL 내용 가져오기 (컨테이너 네트워크 환경에 따라 제한될 수 있음) |
read / write |
워크스페이스 파일 읽기/쓰기 |
openclaw skills list 명령으로 사용 가능한 스킬을 확인할 수 있습니다. 기본 제공 스킬 중 별도 설정 없이 사용 가능한 것들:
| Skill | Description |
|---|---|
weather |
날씨 및 기상 예보 (API 키 불필요) |
healthcheck |
시스템 보안 점검 |
skill-creator |
커스텀 스킬 생성/편집 |
Note: 대부분의 번들 스킬 (Slack, GitHub, Notion 등)은 별도 CLI 설치 및 인증이 필요합니다.
openclaw skills list에서 "△ needs setup"으로 표시됩니다.
첫 번째 디바이스 페어링은 컨테이너 내부에서 자동 승인됩니다. 이후 추가 디바이스는 호스트에서 승인해야 합니다.
The first device pairing is auto-approved inside the container. Additional devices must be approved from the host.
# Linux — interactive mode (list + select)
./scripts/device-approve.sh
# Linux — list pending devices only
./scripts/device-approve.sh --list
# Linux — approve a specific device by ID
./scripts/device-approve.sh <device-id># Windows
scripts\device-approve.bat
scripts\device-approve.bat --list
scripts\device-approve.bat <device-id>Discord 봇에 DM을 보내면 페어링 코드가 발급됩니다. 이 코드는 openclaw devices list가 아닌 openclaw pairing 시스템으로 관리되므로, 별도 명령으로 승인해야 합니다.
When you DM the Discord bot, it issues a pairing code. This code is managed by the openclaw pairing system (separate from openclaw devices), so use the --pairing flag to approve it.
# Linux
./scripts/device-approve.sh --pairing discord <CODE>
# Windows
scripts\device-approve.bat --pairing discord <CODE>또는 컨테이너에서 직접 실행할 수도 있습니다:
Or run directly inside the container:
docker exec democlaw-openclaw openclaw pairing approve discord <CODE>The OpenClaw container is a headless environment with developer tools pre-installed:
| Tool | Status | Notes |
|---|---|---|
| Python 3.13 | Pre-installed (via uv) | pip and python3 available immediately |
| npm | Pre-installed (Node.js 22) | Available immediately |
| Homebrew | Pre-installed | brew install <package> available immediately |
| sudo | NOPASSWD | sudo works without password prompts |
The OpenClaw agent runs in bypassPermissions mode (configured via ~/.claude/settings.json), meaning all tool calls are auto-approved without user confirmation. This is designed for autonomous container operation.
DemoClaw supports multimodal vision via Gemma 4's image understanding capability. Vision is enabled by default.
When the stack starts, download-model.sh (and the llama.cpp entrypoint) automatically downloads the multimodal projector file (mmproj-BF16.gguf) alongside the main GGUF weights. llama.cpp loads the projector at startup, enabling image inputs to the model.
| Variable | Default | Description |
|---|---|---|
ENABLE_VISION |
1 |
Set to 0 to skip the mmproj download and disable vision |
MMPROJ_FILE |
mmproj-BF16.gguf |
Filename of the multimodal projector to download |
IMAGE_TOKENS |
256 |
Token budget per image (--image-max-tokens in llama.cpp) |
UBATCH_SIZE |
512 |
Micro-batch size (--ubatch-size); increase for faster vision inference |
# In .env
ENABLE_VISION=0With vision disabled, the mmproj file is not downloaded and llama.cpp starts in text-only mode, reducing VRAM usage.
OpenClaw는 MCP 서버를 통해 외부 도구를 사용할 수 있습니다. DemoClaw는 supergateway를 사용하여 별도 컨테이너의 SSE MCP 서버를 OpenClaw에 연결합니다.
OpenClaw (stdio) → supergateway (SSE→stdio bridge) → MCP sidecar container (SSE)
MarkItDown은 PDF, DOCX, HTML 등을 Markdown으로 변환하는 MCP 서버입니다. 공식 Docker Hub 이미지 mcp/markitdown을 사용합니다.
# Linux
docker run -d \
--name markitdown \
--network democlaw-net \
--network-alias markitdown \
--restart unless-stopped \
-p 3001:3001 \
mcp/markitdown --http --host 0.0.0.0 --port 3001# Windows
docker run -d --name markitdown --network democlaw-net --network-alias markitdown --restart unless-stopped -p 3001:3001 mcp/markitdown --http --host 0.0.0.0 --port 3001- 브라우저에서 OpenClaw 대시보드를 엽니다.
- Settings > Infrastructure > Mcp 탭 (오른쪽 끝으로 스크롤).
- MCP Servers > + Add Entry 클릭.
- 다음 정보를 입력합니다:
- Name:
markitdown - Command:
supergateway - Args:
--sse와http://markitdown:3001/sse(각각 별도 항목으로 + Add)
- Name:
- Save 클릭 → 게이트웨이가 자동 재시작됩니다.
- 약 20초 후 토큰 URL로 다시 접속합니다.
새 세션에서 다음과 같이 사용합니다:
Call convert_to_markdown with uri http://info.cern.ch
에이전트가 convert_to_markdown MCP 도구를 호출하여 웹 페이지를 마크다운으로 변환합니다.
Note: HTTPS URL은 컨테이너 환경에 따라 SSL 인증서 오류가 발생할 수 있습니다. HTTP URL을 사용하세요.
다른 SSE MCP 서버도 같은 패턴으로 연결할 수 있습니다.
docker run -d \
--name my-mcp-server \
--network democlaw-net \
--network-alias my-mcp \
-p 4000:4000 \
my-org/my-mcp-image --http --host 0.0.0.0 --port 4000Infrastructure > Mcp > + Add Entry:
- Name:
my-mcp - Command:
supergateway - Args:
--sse+http://my-mcp:4000/sse
Save 후 자동 재시작.
┌─────────────────────────────────────────────────────┐
│ democlaw-net │
│ │
│ ┌───────────────────────────────┐ │
│ │ OpenClaw container │ │
│ │ │ │
│ │ openclaw-gateway │ │
│ │ └─ supergateway (stdio) ──┼──► markitdown │
│ │ └─ supergateway (stdio) ──┼──► my-mcp │
│ └───────────────────────────────┘ │
│ │
│ ┌────────────┐ ┌────────────┐ │
│ │ markitdown │ │ my-mcp │ │
│ │ SSE :3001 │ │ SSE :4000 │ │
│ └────────────┘ └────────────┘ │
└─────────────────────────────────────────────────────┘
등록된 MCP 서버는 웹 UI에서 확인할 수 있습니다:
- Settings > Infrastructure > Mcp 탭 (오른쪽 끝)
- MCP Servers 섹션에서 등록된 서버 확인
Note: 웹 UI에서 Save하면 게이트웨이가 재시작됩니다. 약 20초 후 토큰 URL로 다시 접속하세요.
기본적으로 OpenClaw의 설정, 디바이스 페어링, 인증 정보는 컨테이너 내부에만 저장됩니다. 컨테이너를 재시작하면 모든 상태가 초기화됩니다.
By default, OpenClaw settings, device pairings, and credentials are stored inside the container. Restarting the container resets all state.
OPENCLAW_DATA_DIR을 설정하면 이 데이터를 호스트에 영속화할 수 있습니다.
Set OPENCLAW_DATA_DIR to persist this data on the host.
cp .env.example .env # if not already done.env 파일에서 / In your .env file:
OPENCLAW_DATA_DIR=/path/to/openclaw-dataWindows:
OPENCLAW_DATA_DIR=C:\Users\YourName\.openclaw-data
-
start.sh/start.bat이OPENCLAW_DATA_DIR을 감지하면 해당 디렉토리를 컨테이너의/home/openclaw/.openclaw에 읽기/쓰기 모드로 마운트합니다. -
변수가 설정되지 않으면 마운트 없이 실행됩니다 (기본 동작, 모든 상태는 일시적).
-
지정된 디렉토리가 존재하지 않으면 자동 생성됩니다.
-
When
OPENCLAW_DATA_DIRis set,start.sh/start.batmounts it to/home/openclaw/.openclawin read-write mode. -
When unset, no mount occurs and all state is ephemeral (default behavior).
-
If the directory does not exist, it is created automatically.
컨테이너를 재시작해도 다음 항목이 유지됩니다:
The following data is preserved across container restarts:
| Data | Description |
|---|---|
devices/ |
Device and Discord pairing info |
credentials/ |
Authentication tokens |
openclaw.json |
Settings (MCP servers, agents, etc.) |
identity/ |
Instance identity |
OpenClaw 컨테이너의 워크스페이스를 호스트 디렉토리와 연결하려면 .env에 OPENCLAW_WORKSPACE_DIR을 설정합니다.
To mount a host directory into the OpenClaw container at /app/workspace:
cp .env.example .env.env 파일에서 다음 줄의 주석을 해제하고 경로를 지정합니다:
# Host directory to mount into OpenClaw container at /app/workspace
OPENCLAW_WORKSPACE_DIR=/path/to/your/workspaceWindows:
OPENCLAW_WORKSPACE_DIR=C:\Users\YourName\workspace
start.sh/start.bat이OPENCLAW_WORKSPACE_DIR환경변수를 감지하면 해당 디렉토리를 OpenClaw 컨테이너의/app/workspace에 읽기/쓰기 모드로 마운트합니다.- 변수가 설정되지 않으면 볼륨 마운트 없이 실행됩니다 (기본 동작).
- 지정된 디렉토리가 존재하지 않으면 경고를 출력하고 마운트를 건너뜁니다.
Every pull request runs the following GitHub Actions jobs:
| Job | Tool | What it checks |
|---|---|---|
shellcheck |
ShellCheck | Shell script correctness |
hadolint |
Hadolint | Dockerfile best practices |
docker-build |
Docker Buildx | Image builds successfully |
smoke-test |
docker compose | Stack starts and LLM API responds |
healthcheck |
curl | /health endpoint returns 200 |
A daily cron workflow checks for new llama.cpp and OpenClaw releases. When an upgrade is detected it:
- Updates the version pins in
Dockerfile/docker-compose.yml. - Opens an auto-PR with the diff.
- Merges the PR automatically once all CI checks pass.
- Pushes the new image to Docker Hub.
| Secret | Description |
|---|---|
DOCKERHUB_USERNAME |
Docker Hub account username |
DOCKERHUB_TOKEN |
Docker Hub access token (read/write) |
Set these under Settings > Secrets and variables > Actions in your fork before enabling the auto-upgrade workflow.
All settings are configurable via environment variables. Copy .env.example to .env and edit:
cp .env.example .envKey settings:
| Variable | Default | Description |
|---|---|---|
CONTAINER_RUNTIME |
auto-detect | Force docker or podman |
MODEL_REPO |
unsloth/gemma-4-E4B-it-GGUF |
HuggingFace model repo |
MODEL_FILE |
gemma-4-E4B-it-Q4_K_M.gguf |
GGUF model filename |
CTX_SIZE |
131072 |
Context length (tokens) |
LLAMACPP_PORT |
8000 |
llama.cpp API port |
OPENCLAW_PORT |
18789 |
OpenClaw dashboard port |
MODEL_DIR |
./.data |
Host model cache directory (project-local, persistent across start.sh runs) |
VLLM_IMAGE |
docker.io/jinwangmok/democlaw-spark-gemma4:latest |
vLLM container image (DGX Spark NVFP4A16) |
VLLM_HF_REPO |
bg-digitalservices/Gemma-4-26B-A4B-it-NVFP4A16 |
HuggingFace repo cloned into .data/ on DGX Spark |
OPENCLAW_DATA_DIR |
(unset) | Host directory to persist OpenClaw settings/pairings |
OPENCLAW_WORKSPACE_DIR |
(unset) | Host directory to mount into OpenClaw |
ENABLE_VISION |
1 |
Set to 0 to disable multimodal vision and skip mmproj download |
MMPROJ_FILE |
mmproj-BF16.gguf |
Multimodal projector filename |
IMAGE_TOKENS |
256 |
Token budget per image |
UBATCH_SIZE |
512 |
Micro-batch size for inference |
See .env.example for the full list.
democlaw/
├── llamacpp/ # llama.cpp container (Dockerfile, entrypoint, healthcheck)
├── openclaw/ # OpenClaw container (Dockerfile, entrypoint, healthcheck)
├── markitdown/ # MarkItDown MCP server (standalone example sidecar)
├── config/
│ └── mcporter.json # MCP server registry (volume-mounted into OpenClaw)
├── scripts/
│ ├── start.sh # Full stack startup (Linux)
│ ├── start.bat # Full stack startup (Windows)
│ ├── stop.sh # Stack teardown (Linux)
│ ├── stop.bat # Stack teardown (Windows)
│ ├── device-approve.sh # Approve pending devices from host (Linux)
│ ├── device-approve.bat # Approve pending devices from host (Windows)
│ ├── download-model.sh # Pre-download model weights
│ └── reference/
│ └── image.sh # Image pull-or-build library (sourced by start.sh)
├── examples/skills/ # Custom OpenClaw skill templates
├── docs/ # API and config reference
├── .env.example # Environment configuration template
└── Makefile # make 숏컷 (start/stop/build/logs 등 → scripts/ 래퍼)
MIT