MCP应用docker部署,docker-compose部署

一、概述

前面几篇文章,MCP应用直接用的python3 server.py运行的,如果服务器重启,进程就会关掉,很不方便。

所以需要使用docker部署,实现开机自启动。

二、docker部署

mysql_mcp_server_pro

准备文件

以mysql_mcp_server_pro为例:

server_docker.py

复制代码
from fastmcp import FastMCP
from mysql.connector import connect, Error
import os

mcp = FastMCP("operateMysql", host="0.0.0.0", port=9000)


def get_db_config():
    """从环境变量获取数据库配置信息

    返回:
        dict: 包含数据库连接所需的配置信息
        - host: 数据库主机地址
        - port: 数据库端口
        - user: 数据库用户名
        - password: 数据库密码
        - database: 数据库名称

    异常:
        ValueError: 当必需的配置信息缺失时抛出
    """

    config = {
        "host": os.getenv("MYSQL_HOST", "localhost"),
        "port": int(os.getenv("MYSQL_PORT", "3306")),
        "user": os.getenv("MYSQL_USER"),
        "password": os.getenv("MYSQL_PASSWORD"),
        "database": os.getenv("MYSQL_DATABASE"),
    }
    print(config)
    if not all(
        [
            config["host"],
            config["port"],
            config["user"],
            config["password"],
            config["database"],
        ]
    ):
        raise ValueError("缺少必需的数据库配置")

    return config


@mcp.tool()
def execute_sql(query: str) -> list:
    """执行SQL查询语句

    参数:
        query (str): 要执行的SQL语句,支持多条语句以分号分隔

    返回:
        list: 包含查询结果的TextContent列表
        - 对于SELECT查询:返回CSV格式的结果,包含列名和数据
        - 对于SHOW TABLES:返回数据库中的所有表名
        - 对于其他查询:返回执行状态和影响行数
        - 多条语句的结果以"---"分隔

    异常:
        Error: 当数据库连接或查询执行失败时抛出
    """
    config = get_db_config()
    try:
        with connect(**config) as conn:
            with conn.cursor() as cursor:
                statements = [stmt.strip() for stmt in query.split(";") if stmt.strip()]
                results = []

                for statement in statements:
                    try:
                        cursor.execute(statement)

                        # 检查语句是否返回了结果集 (SELECT, SHOW, EXPLAIN, etc.)
                        if cursor.description:
                            columns = [desc[0] for desc in cursor.description]
                            rows = cursor.fetchall()

                            # 将每一行的数据转换为字符串,特殊处理None值
                            formatted_rows = []
                            for row in rows:
                                formatted_row = [
                                    "NULL" if value is None else str(value)
                                    for value in row
                                ]
                                formatted_rows.append(",".join(formatted_row))

                            # 将列名和数据合并为CSV格式
                            results.append(
                                "\n".join([",".join(columns)] + formatted_rows)
                            )

                        # 如果语句没有返回结果集 (INSERT, UPDATE, DELETE, etc.)
                        else:
                            conn.commit()  # 只有在非查询语句时才提交
                            results.append(f"查询执行成功。影响行数: {cursor.rowcount}")

                    except Error as stmt_error:
                        # 单条语句执行出错时,记录错误并继续执行
                        results.append(
                            f"执行语句 '{statement}' 出错: {str(stmt_error)}"
                        )
                        # 可以在这里选择是否继续执行后续语句,目前是继续

                return ["\n---\n".join(results)]

    except Error as e:
        print(f"执行SQL '{query}' 时出错: {e}")
        return [f"执行查询时出错: {str(e)}"]


@mcp.tool()
def get_table_name(text: str) -> list:
    """根据表的中文注释搜索数据库中的表名

    参数:
        text (str): 要搜索的表中文注释关键词

    返回:
        list: 包含查询结果的TextContent列表
        - 返回匹配的表名、数据库名和表注释信息
        - 结果以CSV格式返回,包含列名和数据
    """
    config = get_db_config()
    sql = "SELECT TABLE_SCHEMA, TABLE_NAME, TABLE_COMMENT "
    sql += f"FROM information_schema.TABLES WHERE TABLE_SCHEMA = '{config['database']}' AND TABLE_COMMENT LIKE '%{text}%';"
    return execute_sql(sql)


@mcp.tool()
def get_table_desc(text: str) -> list:
    """获取指定表的字段结构信息

    参数:
        text (str): 要查询的表名,多个表名以逗号分隔

    返回:
        list: 包含查询结果的列表
        - 返回表的字段名、字段注释等信息
        - 结果按表名和字段顺序排序
        - 结果以CSV格式返回,包含列名和数据
    """
    config = get_db_config()
    # 将输入的表名按逗号分割成列表
    table_names = [name.strip() for name in text.split(",")]
    # 构建IN条件
    table_condition = "','".join(table_names)
    sql = "SELECT TABLE_NAME, COLUMN_NAME, COLUMN_COMMENT "
    sql += (
        f"FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '{config['database']}' "
    )
    sql += f"AND TABLE_NAME IN ('{table_condition}') ORDER BY TABLE_NAME, ORDINAL_POSITION;"
    return execute_sql(sql)


@mcp.tool()
def get_lock_tables() -> list:
    """
    获取当前mysql服务器InnoDB 的行级锁

    返回:
        list: 包含查询结果的TextContent列表
    """
    sql = """SELECT
    p2.`HOST` AS 被阻塞方host,
    p2.`USER` AS 被阻塞方用户,
    r.trx_id AS 被阻塞方事务id,
    r.trx_mysql_thread_id AS 被阻塞方线程号,
    TIMESTAMPDIFF(SECOND, r.trx_wait_started, CURRENT_TIMESTAMP) AS 等待时间,
    r.trx_query AS 被阻塞的查询,
    l.OBJECT_NAME AS 阻塞方锁住的表,
    m.LOCK_MODE AS 被阻塞方的锁模式,
    m.LOCK_TYPE AS '被阻塞方的锁类型(表锁还是行锁)',
    m.INDEX_NAME AS 被阻塞方锁住的索引,
    m.OBJECT_SCHEMA AS 被阻塞方锁对象的数据库名,
    m.OBJECT_NAME AS 被阻塞方锁对象的表名,
    m.LOCK_DATA AS 被阻塞方事务锁定记录的主键值,
    p.`HOST` AS 阻塞方主机,
    p.`USER` AS 阻塞方用户,
    b.trx_id AS 阻塞方事务id,
    b.trx_mysql_thread_id AS 阻塞方线程号,
    b.trx_query AS 阻塞方查询,
    l.LOCK_MODE AS 阻塞方的锁模式,
    l.LOCK_TYPE AS '阻塞方的锁类型(表锁还是行锁)',
    l.INDEX_NAME AS 阻塞方锁住的索引,
    l.OBJECT_SCHEMA AS 阻塞方锁对象的数据库名,
    l.OBJECT_NAME AS 阻塞方锁对象的表名,
    l.LOCK_DATA AS 阻塞方事务锁定记录的主键值,
    IF(p.COMMAND = 'Sleep', CONCAT(p.TIME, ' 秒'), 0) AS 阻塞方事务空闲的时间
    FROM performance_schema.data_lock_waits w
    INNER JOIN performance_schema.data_locks l ON w.BLOCKING_ENGINE_LOCK_ID = l.ENGINE_LOCK_ID
    INNER JOIN performance_schema.data_locks m ON w.REQUESTING_ENGINE_LOCK_ID = m.ENGINE_LOCK_ID
    INNER JOIN information_schema.INNODB_TRX b ON b.trx_id = w.BLOCKING_ENGINE_TRANSACTION_ID
    INNER JOIN information_schema.INNODB_TRX r ON r.trx_id = w.REQUESTING_ENGINE_TRANSACTION_ID
    INNER JOIN information_schema.PROCESSLIST p ON p.ID = b.trx_mysql_thread_id
    INNER JOIN information_schema.PROCESSLIST p2 ON p2.ID = r.trx_mysql_thread_id
    ORDER BY 等待时间 DESC;"""

    return execute_sql(sql)


if __name__ == "__main__":
    mcp.run(transport="sse")
复制代码

修改了之前文章的代码,去除了.env文件,直接引用系统环境变量。

注意:这里添加了host="0.0.0.0",否则k8s发布,会无法访问mcp server

 

Dockerfile

复制代码
FROM python:3.13.3-alpine3.21
ADD . /app
RUN pip3 install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple && \
    pip3 install mysql-connector-python fastmcp -i https://pypi.tuna.tsinghua.edu.cn/simple
WORKDIR /app

EXPOSE 9000

ENTRYPOINT ["python3","/app/server.py"]
复制代码

说明:

这里使用的python版本,是最新的3.13.3,镜像使用的是最小的,基于alpine

安装fastmcp模块,必须要升级pip才行,否则安装会失败。

 

编译并运行镜像

编译

docker build -t mysql_mcp_server_pro:v1 .

 

运行镜像,注意携带5个环境变量,一个个写变量太麻烦了,接下来使用docker-compose来运行

 

三、docker-compose部署

使用docker-compose方便管理docker,修改docker运行相关参数,也容易。

docker-compose.yaml

复制代码
services:
  mysql_mcp_server_pro:
    image: mysql_mcp_server_pro:v1
    container_name: mysql_mcp_server_pro
    ports:
      - "9090:9000"
    environment:
      MYSQL_HOST: "192.168.20.128"
      MYSQL_PORT: "3306"
      MYSQL_USER: "root"
      MYSQL_PASSWORD: "abcd@1234"
      MYSQL_DATABASE: "test"
      TZ: Asia/Shanghai
    restart: always
复制代码

注意修改mysql相关环境变量

 

运行

docker-compose up -d

 

四、dify测试

上一篇文章,已经介绍了dify调用MCP工具,链接:https://www.cnblogs.com/xiao987334176/p/18827261

还是一样的dify工作流,测试即可。

注意:如果MCP server服务中断,dify是不会自动重连的,需要重启dify的plugin_daemon组件,就会重新连接MCP server

 

测试工作流

 

原创作者: xiao987334176 转载于: https://www.cnblogs.com/xiao987334176/p/18827297
<think>好的,我现在需要帮助用户了解如何使用Docker部署MCP服务端。首先,我需要回忆一下用户提到的参考资料,特别是引用[2]中提到的mcp-server,它用于简化Qdrant的集群管理。用户可能希望部署这个mcp-server,以便更轻松地管理Qdrant或其他服务。 首先,我需要确定Docker部署MCP服务端的基本步骤。通常,使用Docker部署服务需要几个步骤:安装Docker,获取镜像,编写配置文件,运行容器,验证部署。但具体到MCP服务端,可能需要参考官方文档或用户提供的引用链接。不过用户提供的引用中并没有直接给出MCPDocker镜像地址,但引用[2]提到了mcp-server的功能,所以可能需要假设一些步骤,或者参考类似的项目,比如引用[4]中的Seata和Nacos的docker-compose部署方式。 接下来,用户可能需要一个具体的示例,比如Docker命令或者docker-compose文件。根据引用[1],docker run命令的使用可以参考菜鸟教程的示例,所以可能需要构造一个类似的命令。例如,假设MCP的镜像名为mcp-server:latest,那么运行命令可能是: docker run -d --name mcp-server -p 8080:8080 mcp-server:latest 但需要确认端口映射是否正确,是否需要其他参数,比如环境变量或者卷挂载。如果MCP需要连接其他服务,比如Qdrant或者Nacos,可能需要额外的配置,如环境变量或者配置文件。例如,引用[4]中Seata和Nacos的部署可能需要配置中心,所以MCP可能也需要类似的配置。 另外,用户可能希望使用docker-compose来管理多个服务,比如同时部署MCP和Qdrant。例如,引用[4]中的docker-compose部署方式,可以创建一个docker-compose.yml文件,定义mcp-server和其他相关服务。例如: version: '3' services: mcp-server: image: mcp-server:latest ports: - "8080:8080" environment: - NACOS_HOST=nacos-server depends_on: - nacos-server nacos-server: image: nacos/nacos-server:latest ports: - "8848:8848" 但需要确认MCP是否需要连接Nacos,或者是否有其他依赖服务。根据引用[3],Pilot作为服务注册中心,可能MCP需要与之集成,所以可能需要配置服务发现的参数。 另外,用户可能需要配置持久化存储,比如数据库或者配置文件,这时候需要使用Docker卷。例如: volumes: mcp-data:/data 然后在服务中挂载这个卷。此外,性能监控和证书配置可能需要额外的配置,如挂载SSL证书的目录或者配置监控工具的参数。 在验证部署时,可能需要检查容器日志,使用docker logs mcp-server,或者通过curl访问API端点。例如: curl http://localhost:8080/health 如果返回健康状态,则说明部署成功。 同时,需要提醒用户注意安全设置,比如暴露的端口是否需要防火墙规则,或者使用TLS加密通信。例如,引用[2]提到mcp-server处理证书配置,可能需要挂载证书文件: volumes: - ./certs:/etc/mcp/certs 然后在运行命令中添加环境变量指向这些证书。 最后,生成相关问题,比如如何配置集群,如何监控性能,或者如何处理依赖服务如Nacos的配置。这些问题可以帮助用户进一步了解部署后的管理步骤。</think>### 使用 Docker 部署 MCP 服务端的方法 #### 1. **环境准备** - 安装 DockerDocker Compose 确保系统已安装 DockerDocker Compose(建议使用最新稳定版本)。 ```bash # 安装 Docker(以 Ubuntu 为例) sudo apt-get update && sudo apt-get install docker.io # 安装 Docker Compose sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose ``` #### 2. **获取 MCP 服务端镜像** - 若官方提供镜像,可直接拉取: ```bash docker pull mcp-server:latest # 假设镜像名称为 mcp-server ``` - 若需自定义构建,需编写 Dockerfile: ```dockerfile FROM openjdk:17-jdk-slim # 假设 MCP 基于 Java COPY target/mcp-server.jar /app/ WORKDIR /app CMD ["java", "-jar", "mcp-server.jar"] ``` #### 3. **编写 Docker Compose 配置文件** - 创建 `docker-compose.yml`,定义 MCP 服务及其依赖(如 Nacos、数据库等)[^4]: ```yaml version: '3' services: mcp-server: image: mcp-server:latest ports: - "8080:8080" # 控制平面 API 端口 environment: - NACOS_HOST=nacos-server # 若需集成 Nacos 配置中心 volumes: - ./config:/app/config # 挂载配置文件 depends_on: - nacos-server nacos-server: # 示例依赖服务 image: nacos/nacos-server:latest ports: - "8848:8848" ``` #### 4. **启动服务** - 运行以下命令启动容器: ```bash docker-compose up -d ``` - 验证容器状态: ```bash docker ps | grep mcp-server ``` #### 5. **配置与验证** - 检查日志确认服务启动正常: ```bash docker logs mcp-server ``` - 访问 API 端点测试功能: ```bash curl http://localhost:8080/health # 假设健康检查路径为 /health ``` #### 6. **高级配置** - **集群管理**:通过环境变量指定节点角色(如 `ROLE=leader` 或 `ROLE=follower`)[^2]。 - **证书配置**:挂载 TLS 证书目录并设置环境变量路径: ```yaml volumes: - ./certs:/etc/mcp/certs environment: - SSL_CERT_PATH=/etc/mcp/certs/server.crt ``` - **性能监控**:集成 Prometheus 或 Grafana,暴露指标端口[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值