基于Docker的MCP服务器磁盘监控实践
1. 项目概述
最近在技术社区中经常看到关于MCP Server的讨论,作为一个长期关注容器化和AI技术的开发者,我决定亲自动手实践一下MCP Server的搭建过程。由于资源限制,本次先实现一个基础的磁盘监控服务,后续再扩展LLM模型应用部分。
这个项目的主要目标是构建一个基于Docker的MCP服务器镜像,提供以下核心功能:
- 通过RESTful API接口查询服务器磁盘列表
- 检查指定磁盘的SMART健康状态
- 提供完整的Python客户端实现
- 支持SSE(Server-Sent Events)传输模式
选择Docker作为部署方式主要基于以下考虑:
- 环境隔离:避免污染主机环境
- 可移植性:一次构建,随处运行
- 资源控制:方便限制CPU/内存使用
- 快速部署:简化依赖管理流程
2. 环境准备
2.1 系统要求
推荐使用以下操作系统环境:
- EulerOS 2.x/22.03 LTS:项目主要在该环境下测试
- Ubuntu 20.04+:apt包管理更简单
- CentOS 7/8:与EulerOS兼容性好
硬件要求:
- CPU:x86_64架构,至少2核
- 内存:建议4GB以上
- 存储:/var目录至少20GB空间(Docker默认存储位置)
2.2 Docker安装
2.2.1 添加Docker仓库
对于基于RPM的系统(如EulerOS/CentOS):
# 添加官方Docker仓库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo对于EulerOS需要额外适配版本:
# EulerOS 2.x(对应CentOS 7) sudo sed -i 's/$releasever/7/g' /etc/yum.repos.d/docker-ce.repo # EulerOS 22.03 LTS(对应CentOS 8) sudo sed -i 's/$releasever/8/g' /etc/yum.repos.d/docker-ce.repo2.2.2 清理并重建缓存
sudo yum clean all sudo yum makecache2.2.3 安装Docker引擎
sudo yum install -y docker-ce docker-ce-cli containerd.io验证安装:
docker --version # 预期输出:Docker version 20.10.17, build 100c7012.2.4 启动Docker服务
sudo systemctl start docker sudo systemctl enable docker sudo systemctl status docker注意:如果使用非root用户操作Docker,需要将用户加入docker组:
sudo usermod -aG docker $USER newgrp docker
2.3 存储配置优化
默认情况下Docker将镜像存储在/var/lib/docker,如果该分区空间不足,可以考虑以下方案:
方案一:修改Docker存储路径
# 停止Docker服务 sudo systemctl stop docker # 创建新存储目录 sudo mkdir -p /data/docker # 修改配置文件 sudo tee /etc/docker/daemon.json <<EOF { "data-root": "/data/docker" } EOF # 迁移现有数据(如有) sudo rsync -avx /var/lib/docker/ /data/docker/ # 重启服务 sudo systemctl start docker方案二:挂载新硬盘到/var(适用于大容量存储需求)
操作步骤:
- 识别新磁盘设备(如/dev/nvme6n1)
- 创建分区和文件系统:
sudo parted /dev/nvme6n1 mklabel gpt sudo parted -a opt /dev/nvme6n1 mkpart primary ext4 0% 100% sudo mkfs.ext4 /dev/nvme6n1p1 - 临时挂载并迁移数据:
sudo mkdir /mnt/newvar sudo mount /dev/nvme6n1p1 /mnt/newvar sudo rsync -avx /var/ /mnt/newvar/ sudo mv /var /var.old sudo mkdir /var sudo umount /mnt/newvar sudo mount /dev/nvme6n1p1 /var - 配置永久挂载:
echo '/dev/nvme6n1p1 /var ext4 defaults 0 0' | sudo tee -a /etc/fstab sudo mount -a
3. 项目文件准备
3.1 项目结构设计
创建标准项目目录结构:
mcp-disk-monitor/ ├── Dockerfile # 容器构建定义 ├── requirements.txt # Python依赖 ├── mcp_server.py # 服务端主程序 └── mcp_client.py # 客户端测试工具3.2 依赖管理
requirements.txt内容:
fastmcp>=0.1.0 # MCP服务框架 langchain-mcp-adapters>=0.1.0 # 客户端适配器 aiohttp>=3.9.0 # 异步HTTP客户端 smartmontools==7.3 # SMART工具(通过系统包安装)提示:实际Python依赖只需前三项,smartmontools将在Dockerfile中通过apt安装
3.3 服务端核心实现
mcp_server.py关键功能解析:
磁盘列表查询功能
@mcp.tool def list_disks() -> List[Dict[str, Any]]: """ 查询磁盘列表的底层实现原理: 1. 使用lsblk命令获取磁盘信息(-J参数输出JSON格式) 2. 解析返回的JSON数据结构 3. 提取关键字段:名称、大小、类型、挂载点 4. 递归处理子设备(分区、逻辑卷等) """ result = subprocess.run( ["lsblk", "-J", "-o", "NAME,SIZE,TYPE,MOUNTPOINT"], capture_output=True, text=True, check=True ) data = json.loads(result.stdout) return data.get("blockdevices", [])SMART健康检查功能
@mcp.tool def check_disk_smart(device: str = "/dev/sda") -> str: """ SMART检查实现细节: 1. 调用smartctl命令(需root权限) 2. 解析输出中的"SMART overall-health"状态 3. 处理各种异常情况: - 命令不存在 - 设备不存在 - 权限不足 """ try: result = subprocess.run( ["sudo", "smartctl", "-H", device], capture_output=True, text=True, check=False ) output = result.stdout.lower() return "PASSED" if "passed" in output else "FAILED" except Exception as e: return f"ERROR: {str(e)}"3.4 客户端实现要点
mcp_client.py关键设计:
- 使用MultiServerMCPClient处理连接池
- 异步IO设计提高并发性能
- 结果处理支持多种格式:
- 原始文本
- JSON对象
- 错误信息
- 磁盘信息可视化展示:
def format_disk_info(disks): """使用树状结构美观展示磁盘层级关系""" # 实现细节省略...
4. Docker镜像构建
4.1 Dockerfile深度解析
FROM python:3.11-slim as builder # 阶段一:构建依赖 RUN apt-get update && apt-get install -y \ gcc \ python3-dev \ && pip install --user -r requirements.txt FROM python:3.11-slim # 安装运行时依赖 RUN apt-get update && apt-get install -y \ smartmontools \ util-linux \ sudo \ && rm -rf /var/lib/apt/lists/* # 复制已构建的Python环境 COPY --from=builder /root/.local /root/.local COPY . /app # 环境配置 ENV PATH=/root/.local/bin:$PATH WORKDIR /app # 权限配置 RUN echo "ALL ALL=(ALL) NOPASSWD: /usr/sbin/smartctl" >> /etc/sudoers && \ chmod +x /app/mcp_server.py EXPOSE 6666 CMD ["python", "mcp_server.py"]构建优化技巧:
- 使用多阶段构建减小镜像体积
- 分离构建时依赖和运行时依赖
- 最小化权限配置(仅允许smartctl的sudo权限)
- 使用slim基础镜像减少不必要的组件
4.2 镜像构建实操
执行构建命令:
docker build -t mcp-disk-monitor:1.0 .构建过程常见问题处理:
- 网络超时:更换pip源或使用代理
RUN pip install --trusted-host pypi.tuna.tsinghua.edu.cn \ -i https://pypi.tuna.tsinghua.edu.cn/simple \ -r requirements.txt - 权限不足:确保用户有docker组权限
- 存储空间不足:参考2.3节配置存储路径
- 架构不匹配:明确指定平台
docker build --platform linux/amd64 -t mcp-disk-monitor .
5. 运行与测试
5.1 容器化部署
启动容器的最佳实践:
docker run -d \ --name mcp-disk \ --restart unless-stopped \ -p 6666:6666 \ -v /dev:/dev:ro \ --cap-add=SYS_ADMIN \ mcp-disk-monitor:1.0参数说明:
-v /dev:/dev:ro:只读挂载设备目录--cap-add=SYS_ADMIN:授予必要的系统权限--restart:配置自动重启策略
5.2 服务验证
检查服务健康状态:
# 检查容器状态 docker ps -f name=mcp-disk # 查看实时日志 docker logs -f mcp-disk # 测试API接口 curl http://localhost:6666/sse客户端测试示例输出:
================================================== 测试 list_disks 工具... ================================================== ├─ sda (disk, 447.1G) ├─ sda1 (part, 512M) [挂载点: /boot/efi] ├─ sda2 (part, 1G) [挂载点: /boot] └─ sda3 (part, 445.6G) ├─ vg0-root (lvm, 50G) [挂载点: /] ├─ vg0-swap (lvm, 8G) └─ vg0-data (lvm, 387.6G) [挂载点: /data]5.3 生产环境建议
网络安全:
- 使用TLS加密通信
- 配置防火墙规则
- 启用API认证
资源限制:
docker run -d \ --memory 2g \ --cpus 1.5 \ --name mcp-prod \ ...日志管理:
docker run -d \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=3 \ ...
6. 高级配置与优化
6.1 安全加固方案
非root用户运行:
RUN useradd -r -u 1001 -g root appuser && \ chown -R appuser:root /app USER appuser只读文件系统:
docker run --read-only \ --tmpfs /tmp \ ...安全扫描:
docker scan mcp-disk-monitor:1.0
6.2 性能调优技巧
SSE连接优化:
mcp.run( transport="sse", host="0.0.0.0", port=6666, sse_ping_interval=30, # 保持连接活跃 timeout=300 )容器资源监控:
docker stats mcp-disk客户端连接池配置:
self.client = MultiServerMCPClient({ self.server_name: { "url": server_url, "transport": "sse", "pool_size": 5, # 连接池大小 "timeout": 30 } })
6.3 扩展性设计
添加新监控指标:
@mcp.tool def disk_usage(): """监控磁盘使用率""" return subprocess.check_output(["df", "-h"]).decode()集成告警功能:
def check_disk_smart(device): result = subprocess.run(...) if "FAILED" in result: send_alert(f"磁盘{device}故障") return result支持Prometheus监控:
from prometheus_client import start_http_server, Gauge smart_status = Gauge('disk_smart_status', 'SMART健康状态', ['device']) @mcp.tool def check_disk_smart(device): status = get_smart_status(device) smart_status.labels(device=device).set(1 if status=="PASSED" else 0) return status
在实际部署过程中,我发现以下几个经验点特别值得注意:
- 生产环境务必配置资源限制,避免单个容器耗尽系统资源
- SMART检查需要精确的权限控制,过度授权会带来安全隐患
- 客户端需要完善的错误处理和重试机制,特别是对网络波动的适应
- 磁盘信息查询的JSON处理要考虑各种边缘情况,如设备名称包含特殊字符等