diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..82b14cd --- /dev/null +++ b/.dockerignore @@ -0,0 +1,26 @@ +.git/ +.gitignore +.venv/ +__pycache__/ +*.py[cod] +*.egg-info/ +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +.coverage +htmlcov/ +.worktrees/ +.DS_Store + +# Sensitive config - mount at runtime instead +config/connections.json +logs/ + +# Documentation not needed in image +docs/ +*.md +!README.md +AGENT.md + +# Tests not needed in image +tests/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d443196 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,75 @@ +# ============================================================== +# 第一阶段:构建阶段(编译安装依赖,产出安装好的 Python 包) +# 这个阶段的产物只有 /install 目录会被带到下一阶段, +# 其余所有内容(gcc 编译器、头文件等)都会被丢弃,不会出现在最终镜像中。 +# ============================================================== +FROM python:3.13-slim AS builder + +# 设置构建阶段的工作目录 +WORKDIR /build + +# 安装编译期依赖: +# gcc - C 编译器,psycopg 的 C 扩展需要用它来编译 +# libpq-dev - PostgreSQL 客户端开发库(头文件),编译 psycopg 时需要 +# 安装完成后清理 apt 缓存,减小这一层的体积 +RUN apt-get update && \ + apt-get install -y --no-install-recommends gcc libpq-dev && \ + rm -rf /var/lib/apt/lists/* + +# 拷贝项目定义文件和源码到构建目录 +COPY pyproject.toml ./ +COPY sql_query_mcp/ sql_query_mcp/ + +# 用 pip 安装项目及其所有依赖到 /install 目录 +# --no-cache-dir 不缓存下载的包,减小体积 +# --prefix=/install 安装到独立目录,方便后续只拷贝这个目录到运行阶段 +RUN pip install --no-cache-dir --prefix=/install . + + +# ============================================================== +# 第二阶段:运行阶段(最终镜像,只包含运行时必需的内容) +# 这里重新 FROM 一个干净的 python:3.13-slim, +# 第一阶段的 gcc、头文件等编译工具不会带进来,所以最终镜像很小。 +# ============================================================== +FROM python:3.13-slim + +# 镜像元数据标签 +LABEL maintainer="andyWang1688" +LABEL org.opencontainers.image.source="https://github.com/andyWang1688/sql-query-mcp" +LABEL org.opencontainers.image.description="A general-purpose MCP server that lets AI work with multiple databases within clear boundaries." + +# 安装运行时依赖: +# libpq5 - PostgreSQL 客户端运行时库,psycopg 连接数据库时需要 +# 注意:这里不需要 gcc 和 libpq-dev 了,因为编译已经在第一阶段完成 +RUN apt-get update && \ + apt-get install -y --no-install-recommends libpq5 && \ + rm -rf /var/lib/apt/lists/* + +# 从第一阶段(builder)拷贝已安装好的 Python 包到系统目录 +# 这一行就是多阶段构建的核心:只取编译产物,丢弃编译工具 +COPY --from=builder /install /usr/local + +# 设置运行阶段的工作目录 +WORKDIR /app + +# 拷贝应用源码和示例配置文件 +COPY sql_query_mcp/ sql_query_mcp/ +COPY config/connections.example.json config/connections.example.json + +# 创建非 root 用户 mcp(uid=1000),用该用户运行服务 +# 目的:即使容器被攻破,攻击者也不是 root,减少安全风险 +RUN groupadd --gid 1000 mcp && \ + useradd --uid 1000 --gid mcp --shell /bin/false mcp && \ + mkdir -p /app/logs && \ + chown -R mcp:mcp /app + +# 切换到非 root 用户 +USER mcp + +# 配置文件路径,可以通过以下两种方式覆盖: +# 1. 挂载卷:-v /your/connections.json:/app/config/connections.json:ro +# 2. 环境变量:-e SQL_QUERY_MCP_CONFIG=/custom/path.json +ENV SQL_QUERY_MCP_CONFIG=/app/config/connections.json + +# 容器启动时执行的命令(即 pyproject.toml 中定义的 console script) +ENTRYPOINT ["sql-query-mcp"] diff --git a/pyproject.toml b/pyproject.toml index 52d0da7..f11eb5e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "sql-query-mcp" -version = "0.1.2" +version = "0.1.3" description = "Read-only SQL MCP server for PostgreSQL and MySQL." readme = "README.md" requires-python = ">=3.10" diff --git a/sql_query_mcp/__init__.py b/sql_query_mcp/__init__.py index 1db183c..4c8cc68 100644 --- a/sql_query_mcp/__init__.py +++ b/sql_query_mcp/__init__.py @@ -2,4 +2,4 @@ __all__ = ["__version__"] -__version__ = "0.1.0" +__version__ = "0.1.3"