docs: add Docker Compose deployment and README
Add a single-service docker-compose setup with bind-mounted config / templates / apps / playbooks / data so users can iterate on inventory and intents without rebuilding the image. Dockerfile uses python:3.12-slim with tini for clean signal handling, and ships openssh-client for in- container troubleshooting. Health check hits the /health endpoint. README documents project background, the L1-L5 architecture, both local and Docker deployment paths, configuration keys, intent template extension, and the safety model. Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# VCS / 编辑器 / 工具
|
||||
.git/
|
||||
.gitignore
|
||||
.gitattributes
|
||||
.vscode/
|
||||
.idea/
|
||||
.claude/
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Python 缓存
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.egg-info/
|
||||
.venv/
|
||||
venv/
|
||||
.pytest_cache/
|
||||
.ruff_cache/
|
||||
.mypy_cache/
|
||||
|
||||
# 本地数据 / 密钥
|
||||
data/
|
||||
*.db
|
||||
*.sqlite*
|
||||
.env
|
||||
.env.local
|
||||
config/inventory.yaml
|
||||
|
||||
# 文档(保留 README 以便容器内可见,但构建时不需要)
|
||||
*.md
|
||||
|
||||
# 测试 & CI
|
||||
tests/
|
||||
.github/
|
||||
@@ -25,6 +25,9 @@ data/
|
||||
audit.log
|
||||
logs/
|
||||
|
||||
# Docker
|
||||
docker-compose.override.yml
|
||||
|
||||
# Inventory secrets (only ship the example)
|
||||
config/inventory.yaml
|
||||
!config/inventory.example.yaml
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
# syntax=docker/dockerfile:1.6
|
||||
FROM python:3.12-slim AS base
|
||||
|
||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||
PYTHONUNBUFFERED=1 \
|
||||
PIP_NO_CACHE_DIR=1 \
|
||||
PIP_DISABLE_PIP_VERSION_CHECK=1
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 基础系统依赖:
|
||||
# - gcc/libffi-dev : 编译某些 wheel(如 cryptography/asyncssh 依赖)
|
||||
# - openssh-client : 提供 ssh 客户端工具,便于排障
|
||||
# - tini : 优雅处理信号
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc \
|
||||
libffi-dev \
|
||||
openssh-client \
|
||||
tini \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 先安装依赖(pyproject + src 一起,以便 setuptools 发现包)
|
||||
COPY pyproject.toml ./
|
||||
COPY src/ ./src/
|
||||
RUN pip install .
|
||||
|
||||
# 复制运行时资源(这些目录在 compose 里默认会被卷挂载覆盖)
|
||||
COPY templates/ ./templates/
|
||||
COPY config/ ./config/
|
||||
COPY apps/ ./apps/
|
||||
COPY playbooks/ ./playbooks/
|
||||
|
||||
# data/ 用于审计日志 + SQLite,运行时挂载卷
|
||||
RUN mkdir -p /app/data
|
||||
|
||||
# 默认监听所有接口(容器内)
|
||||
ENV OPS_HOST=0.0.0.0 \
|
||||
OPS_PORT=8000
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
CMD ["ops", "serve"]
|
||||
@@ -0,0 +1,300 @@
|
||||
# AI App Ops Tools
|
||||
|
||||
> 面向运维工程师的 **AI 驱动自然语言运维终端** —— 用一句话统一操作 Linux、Windows 等异构主机。
|
||||
|
||||
[](https://www.python.org)
|
||||
[](LICENSE)
|
||||
|
||||
## 项目背景
|
||||
|
||||
日常运维中我们经常面对:
|
||||
|
||||
- **多种操作系统**:Windows / Ubuntu / CentOS / Debian / macOS …
|
||||
- **不同的命令体系**:`df -h` vs `Get-PSDrive`、`systemctl restart` vs `Restart-Service`、`apt` vs `yum` vs `dnf` …
|
||||
- **重复劳动**:日常巡检、批量诊断、应用部署,过程难以沉淀
|
||||
|
||||
本项目尝试用 **AI + 跨 OS 意图模板** 这一组合,把"记住命令"的负担交给工具,让运维人员只关心"做什么",并把每一次操作沉淀为可复用的知识资产。
|
||||
|
||||
## 核心特性
|
||||
|
||||
- 🗣️ **自然语言操作**:基于 Claude Function Calling,用一句话完成跨主机操作
|
||||
- 🛡️ **三级风险闸门**:`READ` 自动 / `WRITE` 需确认 / `DESTRUCTIVE` 默认禁用
|
||||
- 🌐 **统一异构 OS**:同一意图(如 `check_disk_usage`)在 Linux/Windows/macOS 下自动路由到不同实现
|
||||
- 📜 **意图模板库**:所有命令以 YAML 形式版本化管理,是项目的核心知识资产
|
||||
- 🔌 **多种连接器**:SSH(Linux/Unix)、WinRM(Windows)、Local(本机测试)
|
||||
- 📊 **全量审计日志**:谁、何时、用什么自然语言、对哪些主机执行了什么命令
|
||||
- 🧱 **分层架构**:从单条命令到应用部署,逐层演进无需重构
|
||||
|
||||
## 架构分层
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ L5 策略层 │ 灰度策略、变更窗口、AI 风险预判 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ L4 编排层 │ 多主机有序执行、依赖、健康检查门控 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ L3 应用层 │ 部署 / 升级 / 回滚 = 业务原子操作 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ L2 操作层 │ 装包 / 改配置 / 重启服务 / 拷文件 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ L1 命令层 │ df / ps / 跨 OS 命令模板 ← 当前阶段 │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
数据流:
|
||||
|
||||
```
|
||||
用户 NL 请求
|
||||
↓
|
||||
AI 编排 (Claude + Function Calling,只能调用已注册的意图)
|
||||
↓
|
||||
意图模板库 (按主机 OS 路由到对应实现)
|
||||
↓
|
||||
风险闸门 (READ/WRITE/DESTRUCTIVE)
|
||||
↓
|
||||
连接器 (SSH / WinRM / Local)
|
||||
↓
|
||||
审计日志 + 结果归一化 + AI 摘要
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
ai-app-ops-tools/
|
||||
├── config/
|
||||
│ ├── inventory.example.yaml # 主机清单模板
|
||||
│ └── settings.yaml # 运行时策略(含 destructive 关键字)
|
||||
├── templates/ # 意图模板库 ★ 核心知识资产
|
||||
│ ├── disk.yaml
|
||||
│ ├── system.yaml
|
||||
│ └── service.yaml
|
||||
├── apps/ # 预留:L3 应用台账
|
||||
├── playbooks/ # 预留:L3-L4 部署剧本
|
||||
├── src/ops_tools/
|
||||
│ ├── config.py # Pydantic Settings
|
||||
│ ├── inventory/ # 主机清单 + facts 探测
|
||||
│ ├── intents/ # 意图模板加载
|
||||
│ ├── connectors/ # local / ssh / winrm
|
||||
│ ├── executor/ # 风险闸门 + 执行 + 审计
|
||||
│ ├── audit/ # SQLite 审计日志
|
||||
│ ├── ai/ # Claude 编排(Function Calling)
|
||||
│ ├── api/ # HTTP API
|
||||
│ ├── main.py # FastAPI 入口
|
||||
│ └── cli.py # Typer CLI
|
||||
├── tests/
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml
|
||||
├── pyproject.toml
|
||||
└── .env.example
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 方式一:本地开发
|
||||
|
||||
#### 1. 准备 Python 环境(需要 Python ≥ 3.11)
|
||||
|
||||
```bash
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
#### 2. 准备配置
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# 编辑 .env,至少填入 ANTHROPIC_API_KEY
|
||||
|
||||
cp config/inventory.example.yaml config/inventory.yaml
|
||||
# 编辑 inventory.yaml 加入你的真实主机
|
||||
```
|
||||
|
||||
#### 3. 体验 CLI
|
||||
|
||||
```bash
|
||||
# 列出主机
|
||||
ops hosts
|
||||
|
||||
# 列出已注册的意图
|
||||
ops intents
|
||||
|
||||
# 在 localhost 上执行查磁盘
|
||||
ops run check_disk_usage localhost
|
||||
|
||||
# 写入类意图会被拦截,附命令预览
|
||||
ops run restart_service localhost --params '{"service": "Spooler"}'
|
||||
# 加 --confirm 才会真正执行
|
||||
ops run restart_service localhost --params '{"service": "Spooler"}' --confirm
|
||||
|
||||
# 自然语言对话(需 ANTHROPIC_API_KEY)
|
||||
ops chat "看一下 localhost 的磁盘和内存"
|
||||
```
|
||||
|
||||
#### 4. 启动 HTTP 服务
|
||||
|
||||
```bash
|
||||
ops serve
|
||||
# 访问 http://127.0.0.1:8000/docs 查看 OpenAPI 文档
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 方式二:Docker Compose 部署(推荐用于服务器侧)
|
||||
|
||||
#### 1. 准备配置文件
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
cp config/inventory.example.yaml config/inventory.yaml
|
||||
# 按需编辑两个文件
|
||||
```
|
||||
|
||||
#### 2. 构建 + 启动
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
容器启动后会自动:
|
||||
- 监听 `0.0.0.0:8000`(宿主机端口可在 `.env` 中通过 `OPS_PORT` 覆盖)
|
||||
- 将 `./config /templates /apps /playbooks /data` 以 bind mount 挂载进容器,**编辑这些文件无需重建镜像**
|
||||
- 把审计 + SQLite 数据持久化到宿主机的 `./data` 目录
|
||||
- 自带健康检查(`/health` 端点)
|
||||
|
||||
#### 3. 验证服务
|
||||
|
||||
```bash
|
||||
# 健康检查
|
||||
curl http://127.0.0.1:8000/health
|
||||
|
||||
# 列出主机
|
||||
curl http://127.0.0.1:8000/api/v1/hosts | jq
|
||||
|
||||
# 列出意图
|
||||
curl http://127.0.0.1:8000/api/v1/intents | jq
|
||||
|
||||
# 直接执行意图
|
||||
curl -X POST http://127.0.0.1:8000/api/v1/run \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"intent":"check_disk_usage","hosts":["localhost"]}'
|
||||
|
||||
# 自然语言对话
|
||||
curl -X POST http://127.0.0.1:8000/api/v1/chat \
|
||||
-H 'Content-Type: application/json' \
|
||||
-d '{"message":"看一下生产环境的磁盘使用率"}'
|
||||
```
|
||||
|
||||
#### 4. 进入容器执行 CLI
|
||||
|
||||
```bash
|
||||
docker compose exec ops ops hosts
|
||||
docker compose exec ops ops intents
|
||||
docker compose exec ops ops chat "重启 nginx 服务"
|
||||
```
|
||||
|
||||
#### 5. 常用运维命令
|
||||
|
||||
```bash
|
||||
docker compose logs -f ops # 看日志
|
||||
docker compose restart ops # 重启服务
|
||||
docker compose down # 停止
|
||||
docker compose up -d --build # 改代码后重建
|
||||
```
|
||||
|
||||
#### 关于 SSH 密钥
|
||||
|
||||
如果要从容器内部 SSH 到目标 Linux 主机,需要把宿主机的 SSH 密钥挂进容器。在 `docker-compose.yml` 中解开对应的 `volumes` 行:
|
||||
|
||||
```yaml
|
||||
# Linux / macOS
|
||||
- ${HOME}/.ssh:/root/.ssh:ro
|
||||
|
||||
# Windows (示例,按你的实际路径)
|
||||
- C:/Users/<your-name>/.ssh:/root/.ssh:ro
|
||||
```
|
||||
|
||||
> ⚠️ 生产环境建议使用 SSH agent forwarding、Vault、跳板机等更安全的方案,而不是直接挂载本地密钥。
|
||||
|
||||
#### 升级到 PostgreSQL(可选)
|
||||
|
||||
SQLite 适合单机 MVP;如果要多实例部署或大量审计日志,把 `docker-compose.yml` 中 `db` 服务的注释解开,并修改 `OPS_DB_URL`:
|
||||
|
||||
```env
|
||||
OPS_DB_URL=postgresql+asyncpg://ops:changeme@db:5432/ops
|
||||
```
|
||||
|
||||
并在 `pyproject.toml` 中加入 `asyncpg`。
|
||||
|
||||
## 配置说明
|
||||
|
||||
### `.env` 关键项
|
||||
|
||||
| 变量 | 说明 | 默认 |
|
||||
|---|---|---|
|
||||
| `ANTHROPIC_API_KEY` | Anthropic API Key(chat 功能必需) | 空 |
|
||||
| `OPS_MODEL_MAIN` | 主模型 | `claude-sonnet-4-6` |
|
||||
| `OPS_MODEL_FAST` | 轻量任务模型 | `claude-haiku-4-5-20251001` |
|
||||
| `OPS_DB_URL` | 审计数据库 URL | `sqlite+aiosqlite:///./data/ops.db` |
|
||||
| `OPS_AUTO_EXECUTE_WRITE` | WRITE 类是否自动执行 | `false` |
|
||||
| `OPS_ALLOW_DESTRUCTIVE` | 是否允许 DESTRUCTIVE | `false` |
|
||||
| `OPS_HOST` / `OPS_PORT` | API 监听地址 | `127.0.0.1` / `8000` |
|
||||
|
||||
### `config/inventory.yaml` 主机清单
|
||||
|
||||
支持 SSH(密钥 / 密码)、WinRM、Local 三种连接方式,详细字段见 `inventory.example.yaml`。密码字段支持 `${ENV_VAR}` 形式从环境变量插值,避免明文落盘。
|
||||
|
||||
### `config/settings.yaml` 运行时策略
|
||||
|
||||
- 默认超时
|
||||
- SSH / WinRM 传输参数
|
||||
- 风险策略(如自动升级为 DESTRUCTIVE 的关键字白名单)
|
||||
|
||||
## 扩展意图模板(核心知识沉淀)
|
||||
|
||||
在 `templates/` 下新建 YAML 即可。模板示例:
|
||||
|
||||
```yaml
|
||||
intents:
|
||||
- intent: check_listening_ports
|
||||
description: 查看本机监听端口
|
||||
risk_level: READ
|
||||
params: []
|
||||
implementations:
|
||||
linux:
|
||||
command: "ss -tlnp || netstat -tlnp"
|
||||
windows:
|
||||
command: "Get-NetTCPConnection -State Listen | Select-Object LocalAddress,LocalPort,OwningProcess | ConvertTo-Json"
|
||||
```
|
||||
|
||||
**设计原则**:
|
||||
1. **意图名要表达"意图",而不是命令** —— `check_listening_ports` ✅,`run_ss` ❌
|
||||
2. **风险等级保守标注** —— 不确定就标 `WRITE`,确认行为安全后再降级
|
||||
3. **参数显式声明** —— 模板里通过 `params` 列出,便于 AI 理解和参数校验
|
||||
|
||||
每加一个意图,AI 都能立刻自然语言调用 —— **意图模板库就是你的运维知识图谱**。
|
||||
|
||||
## 安全模型
|
||||
|
||||
| 设计 | 防护目标 |
|
||||
|---|---|
|
||||
| LLM 不能生成 shell,只能调用已注册意图 | 防幻觉、防注入 |
|
||||
| 参数通过 `shlex.quote` 转义 | 命令注入 |
|
||||
| 三级风险闸门 + 渲染后再分级 | 误操作放大 |
|
||||
| 全量审计日志(含原始 NL 输入) | 责任追溯 |
|
||||
| `inventory.yaml` 被 git 忽略 | 凭据泄漏 |
|
||||
| 密码字段支持 `${ENV_VAR}` 插值 | 明文落盘 |
|
||||
|
||||
> ⚠️ 当前版本面向受信任的内部使用场景;如对外暴露 API 必须叠加认证(OIDC / mTLS)和网络隔离。
|
||||
|
||||
## 路线图
|
||||
|
||||
- [x] **L1 命令层** — 跨 OS 自然语言查询(MVP,当前阶段)
|
||||
- [ ] **L2 操作层** — 服务启停、装包、改配置(部分已就位)
|
||||
- [ ] **L3 应用层** — 单应用部署 / 升级 / 回滚(应用台账 + 部署剧本)
|
||||
- [ ] **L4 编排层** — 灰度、滚动、健康检查门控、多应用依赖
|
||||
- [ ] **L5 策略层** — 变更窗口、AI 变更风险预判
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
@@ -0,0 +1,49 @@
|
||||
services:
|
||||
ops:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: ai-app-ops-tools:latest
|
||||
container_name: ai-app-ops-tools
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${OPS_PORT:-8000}:8000"
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
# 容器内固定监听 0.0.0.0;对外端口通过上面的 ports 映射
|
||||
OPS_HOST: "0.0.0.0"
|
||||
OPS_PORT: "8000"
|
||||
# SQLite 数据库路径与卷挂载点一致
|
||||
OPS_DB_URL: "sqlite+aiosqlite:////app/data/ops.db"
|
||||
volumes:
|
||||
# 配置、模板、台账、剧本都用 bind mount,方便不重启即可编辑
|
||||
- ./config:/app/config
|
||||
- ./templates:/app/templates
|
||||
- ./apps:/app/apps
|
||||
- ./playbooks:/app/playbooks
|
||||
# 审计日志 + SQLite 持久化
|
||||
- ./data:/app/data
|
||||
# SSH 密钥(按需启用;Windows 上路径需自行调整)
|
||||
# - ${HOME}/.ssh:/root/.ssh:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3)\""]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
# 未来如需切换到 PostgreSQL,可解开下面的注释并修改 OPS_DB_URL
|
||||
# db:
|
||||
# image: postgres:16-alpine
|
||||
# container_name: ai-app-ops-tools-db
|
||||
# restart: unless-stopped
|
||||
# environment:
|
||||
# POSTGRES_USER: ops
|
||||
# POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-changeme}
|
||||
# POSTGRES_DB: ops
|
||||
# volumes:
|
||||
# - pgdata:/var/lib/postgresql/data
|
||||
#
|
||||
# volumes:
|
||||
# pgdata:
|
||||
Reference in New Issue
Block a user