使用 mssql-python 进行容器和本地开发

本指南介绍了Python开发者在Windows、Linux、macOS、Docker容器、开发容器和CI流水线中使用该mssql-python驱动的环境设置。

先决条件

  • Python 3.10 或更高版本。
  • Docker Desktop(用于基于容器的开发)。
  • 一个兼容 x64 的主机(Intel、AMD 或 x64 虚拟机),用于 SQL Server Linux 容器。 SQL Server Linux 容器不支持 ARM64 主机。

go-sqlcmd 工具可以用一个命令创建 SQL Server 容器。 它会自动处理 Docker 映像拉取、密码生成、端口分配和连接上下文:

sqlcmd create mssql --accept-eula

若要创建已附加示例数据库的容器,

sqlcmd create mssql --accept-eula --using https://aka.ms/AdventureWorksLT.bak

创建后, sqlcmd 存储连接上下文,以便可以立即查询:

sqlcmd query "SELECT @@VERSION"

创建一个应用登录一次,然后在你的 Python 代码中使用:

sqlcmd query --database <database> "CREATE LOGIN <app-login> WITH PASSWORD = '<password>';"
sqlcmd query --database <database> "CREATE USER <app-login> FOR LOGIN <app-login>;"
sqlcmd query --database <database> "ALTER ROLE db_datareader ADD MEMBER <app-login>;"
sqlcmd query --database <database> "ALTER ROLE db_datawriter ADD MEMBER <app-login>;"

用你环境中的值替换 <database><app-login><password>

使用 sqlcmd 在创建时打印的连接详情通过 Python 进行连接。 使用 sqlcmd config view 以便稍后检索它们:

import mssql_python

conn = mssql_python.connect(
    server="localhost,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

cursor = conn.cursor()
cursor.execute("SELECT @@VERSION")
print(cursor.fetchval())
conn.close()

完成后,停止或删除容器:

sqlcmd stop
sqlcmd delete

Tip

运行 sqlcmd create mssql --user-database <database> 以创建一个容器,其中包含一个可供开发的空用户数据库。

VS Code 中的本地 SQL Server

VS Code 的 SQL Server 扩展(ms-mssql.mssql)可以直接从编辑器创建本地 SQL Server 容器:

  1. 在活动栏中打开SQL Server视图。
  2. 选择“添加连接>创建本地SQL Server”(或使用命令面板:MS SQL:创建本地SQL Server)。
  3. 选择SQL Server版本并接受 EULA。
  4. 该扩展会拉取容器映像,生成密码,并自动添加连接配置文件。

容器运行后,你可以直接在VS Code中浏览数据库、运行查询和管理对象,然后再切换到Python代码。

使用 Docker 的本地SQL Server

如果希望直接管理容器,官方SQL Server容器映像适用于两个环境变量:

docker run -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=YourStr0ngP@ssword" \
  -p 1433:1433 --name sql1 \
  -d mcr.microsoft.com/mssql/server:2022-latest

等几秒钟,然后用Python连接:

import mssql_python

conn = mssql_python.connect(
    server="localhost,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

cursor = conn.cursor()
cursor.execute("SELECT @@VERSION")
print(cursor.fetchval())
conn.close()

Important

对 SQL Server 容器使用 MSSQL_SA_PASSWORD。 旧 SA_PASSWORD 变量已弃用。 密码必须满足SQL Server复杂性要求:至少 8 个字符,包含大写、小写、数字和特殊字符。

要将 AdventureWorks 样本数据库加载到容器中:

# Download AdventureWorks backup
curl -L -o AdventureWorks2022.bak \
  "https://github.com/Microsoft/sql-server-samples/releases/download/adventureworks/AdventureWorks2022.bak"

# Copy into container
docker cp AdventureWorks2022.bak sql1:/var/opt/mssql/backup/

# Restore
docker exec sql1 /opt/mssql-tools18/bin/sqlcmd \
  -S localhost -U sa -P "YourStr0ngP@ssword" -C \
  -Q "RESTORE DATABASE AdventureWorks2022 FROM DISK='/var/opt/mssql/backup/AdventureWorks2022.bak' WITH MOVE 'AdventureWorks2022' TO '/var/opt/mssql/data/AdventureWorks2022.mdf', MOVE 'AdventureWorks2022_log' TO '/var/opt/mssql/data/AdventureWorks2022_log.ldf'"

Tip

sqlcmd create mssql --using前一节的方法会自动处理下载和恢复。

用于 Python 应用程序的 Dockerfile

Python基础镜像引用集中在一个地方,这样本地构建、开发容器和CI流水线就不会漂移。 对于本地实验,使用支持范围较广的标签(如 python:3-slim)效果很好。 对于共享开发容器、CI和生产环境,请用组织允许列表中经过批准的摘要置顶图片替换该标签。

为连接Microsoft SQL的Python应用创建一个最小的Docker文件:

ARG PYTHON_BASE=python:3-slim
FROM ${PYTHON_BASE}

# Install system libraries required by mssql-python on Linux
RUN apt-get update && \
    apt-get install -y --no-install-recommends libltdl7 libkrb5-3 libgssapi-krb5-2 && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
CMD ["python", "app.py"]

你的 requirements.txt

mssql-python>=1.11.0

生成并运行:

docker build -t myapp .
docker run -e SQL_SERVER=host.docker.internal,1433 myapp

在共享环境中,使用 --build-arg PYTHON_BASE=python:3-slim@sha256:<approved-digest> 传递经批准的不可变基础镜像引用。

注释

在 Docker Desktop(Windows 和 macOS)中使用 host.docker.internal 连接到主机上的 SQL Server。 在 Linux 上,请改用 --network host

Alpine Linux

Alpine用 musl 代替 glibc。 安装所需的包:

ARG PYTHON_BASE=python:3-alpine
FROM ${PYTHON_BASE}

RUN apk add --no-cache libltdl krb5-libs

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
CMD ["python", "app.py"]

Devcontainer 设置

复用用于构建应用程序的同一个 Dockerfile。 这种方法能让开发容器与你的运行时镜像保持一致,避免Python版本的引脚分散在多个文件中。

为 VS Code 创建一个 .devcontainer/devcontainer.json

{
    "name": "Python + SQL Server",
    "build": {
        "dockerfile": "../Dockerfile",
        "context": ".."
    },
    "features": {
        "ghcr.io/devcontainers/features/docker-in-docker:2": {}
    },
    "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
    "postCreateCommand": "pip install --no-cache-dir -r requirements.txt",
    "forwardPorts": [1433],
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-python.python",
                "ms-mssql.mssql"
            ]
        }
    }
}

若要将SQL Server作为服务包含在 devcontainer 中,请使用 Docker Compose:

.devcontainer/docker-compose.yml:

services:
  app:
    build:
      context: ..
      dockerfile: Dockerfile
    volumes:
      - ..:/workspace:cached
    command: sleep infinity
    depends_on:
      - db

  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      ACCEPT_EULA: "Y"
      MSSQL_SA_PASSWORD: "YourStr0ngP@ssword"
    ports:
      - "1433:1433"

.devcontainer/devcontainer.json (撰写版本):

{
    "name": "Python + SQL Server",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspace",
    "postCreateCommand": "pip install -r requirements.txt",
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-python.python",
                "ms-mssql.mssql"
            ]
        }
    }
}

对于共享工作空间,将 SQL Server 服务镜像钉在经过批准的摘要中,而不是依赖浮动标签。 从本地 .env 文件或平台机密存储中加载 MSSQL_SA_PASSWORD,而不是将其提交到源代码版本控制系统。

按名称连接 SQL Server 服务:

conn = mssql_python.connect(
    server="db,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

平台特定依赖

mssql-python驱动捆绑了其原生组件。 你不需要安装外部的ODBC驱动管理器。 然而,在 Linux 和 macOS 上,驱动需要少量系统库。

平台 所需包 安装命令
Windows操作系统 没有 包含在轮盘中。
Ubuntu/Debian libltdl7libkrb5-3libgssapi-krb5-2 sudo apt-get install libltdl7 libkrb5-3 libgssapi-krb5-2
红帽 / CentOS / Fedora libtool-ltdlkrb5-libs sudo dnf install libtool-ltdl krb5-libs
Alpine libltdlkrb5-libs apk add libltdl krb5-libs
macOS OpenSSL(通过 Homebrew) brew install openssl

对于macOS,如果遇到SSL错误,设置链接器标志:

export LDFLAGS="-L/opt/homebrew/opt/openssl/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl/include"

完整安装说明请参见 Install mssql-python

用于开发的身份验证

针对Azure SQL的本地开发

使用 ActiveDirectoryDefault 进行无密码身份验证。 该选项自动通过 Azure CLI、Visual Studio、环境变量和托管身份串联:

conn = mssql_python.connect(
    server="<server>.database.windows.net",
    database="<database>",
    authentication="ActiveDirectoryDefault",
    encrypt="yes"
)

确保你通过使用 Azure CLI 登录:

az login

针对 SQL Server 的本地开发

在本地实例中使用SQL认证。

conn = mssql_python.connect(
    server="localhost,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

针对Azure SQL的容器开发

对于在Azure中运行的容器(App Service、Container Apps、AKS),使用管理身份。

conn = mssql_python.connect(
    server="<server>.database.windows.net",
    database="<database>",
    authentication="ActiveDirectoryMSI",
    encrypt="yes"
)

对于本地运行且需要连接 Azure SQL 的容器,确保容器有一个可以使用的凭证来源ActiveDirectoryDefault。 最可靠的选项有:

  • 在容器中安装 Azure CLI 并登录。 只有当容器镜像已经包含 Azure CLI 并且你打算复用该凭证缓存时,才从主机挂载~/.azure
  • 通过环境变量 AZURE_CLIENT_ID如 、 AZURE_TENANT_IDAZURE_CLIENT_SECRET提供服务主体凭证。

然后在连接码里输入 ActiveDirectoryDefault

支持的 Microsoft SQL 端点

mssql-python驱动程序连接所有 Microsoft SQL 端点:

终结点 Authentication
SQL Server(本地或虚拟机中) SQL 认证,Windows 认证
Azure SQL 数据库 Microsoft Entra ID(推荐),SQL 身份验证
Azure SQL 托管实例 Microsoft Entra ID(推荐),SQL 身份验证
Azure Synapse Analytics(专用池) Microsoft Entra ID, SQL 身份验证
Fabric 中的 SQL 数据库 Microsoft Entra ID
Fabric Data Warehouse Microsoft Entra ID
SQL 分析端点(Lakehouse) Microsoft Entra ID
SQL 分析终结点(镜像数据库) Microsoft Entra ID

请参阅Microsoft Entra认证涵盖所有七种认证模式,以及支持生命周期以了解完整的兼容性矩阵。

CI 管道设置

GitHub Actions

把 Python 运行时放在一个变量里,这样你可以在一个地方查看和更新它。 将 3.x 用于快速迭代的验证管道,或者在发布管道中将其替换为组织批准的确切版本。

name: Test with SQL Server
on: [push, pull_request]

env:
  PYTHON_VERSION: "3.x"

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      sqlserver:
        image: mcr.microsoft.com/mssql/server:2022-latest
        env:
          ACCEPT_EULA: Y
          MSSQL_SA_PASSWORD: YourStr0ngP@ssword
        ports:
          - 1433:1433
        options: >-
          --health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P YourStr0ngP@ssword -C -Q 'SELECT 1'"
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-python@v5
        with:
          python-version: ${{ env.PYTHON_VERSION }}
          check-latest: true

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y libltdl7 libkrb5-3 libgssapi-krb5-2
          pip install -r requirements.txt

      - name: Run tests
        env:
          SQL_SERVER: localhost,1433
          SQL_UID: sa
          SQL_PWD: YourStr0ngP@ssword
        run: pytest

对于共享管道,将内联占位符替换为加密秘密密码,将 SQL Server 服务镜像钉在摘要中,并将 Python 版本保留在组织管理的变量或可重用的工作流输入中。

Azure Pipelines

使用容器资源将 SQL Server 作为服务与测试作业同时运行:

trigger:
  - main

variables:
  python.version: "3.x"

resources:
  containers:
    - container: sqlserver
      image: mcr.microsoft.com/mssql/server:2022-latest
      env:
        ACCEPT_EULA: Y
        MSSQL_SA_PASSWORD: YourStr0ngP@ssword
      ports:
        - 1433:1433

pool:
  vmImage: ubuntu-latest

services:
  sqlserver: sqlserver

steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: "$(python.version)"

  - script: |
      sudo apt-get update
      sudo apt-get install -y libltdl7 libkrb5-3 libgssapi-krb5-2
      pip install -r requirements.txt
    displayName: Install dependencies

  - script: pytest
    displayName: Run tests
    env:
      SQL_SERVER: localhost,1433
      SQL_UID: sa
      SQL_PWD: YourStr0ngP@ssword

与 GitHub Actions 一样,在将此模式用于一次性演示流水线之外的场景之前,请先用机密变量替换内联的占位符密码。

安全和机密

不要在源代码或Docker文件里硬编码数据库密码或连接字符串。 改用环境变量和秘密管理。

地方开发的环境变量

将凭据存储在环境变量中,或存储在排除在源代码管理之外的 .env 文件中:

# .env (add to .gitignore)
SQL_SERVER=localhost,1433
SQL_UID=sa
SQL_PWD=YourStr0ngP@ssword
import os
import mssql_python

conn = mssql_python.connect(
    server=os.environ["SQL_SERVER"],
    uid=os.environ["SQL_UID"],
    pwd=os.environ["SQL_PWD"],
    encrypt="yes",
    trust_server_certificate="yes"
)

对于 Docker Compose,引用一个 .env 文件:

services:
  app:
    build: .
    env_file: .env

注意

切勿将 .env 文件提交到源代码管理系统。 将 .env 添加到 .gitignore 文件。

CI/CD 密钥

在CI流水线中,使用平台的秘密存储而非明文环境变量:

  • GitHub Actions:使用加密的机密,并将其引用为 ${{ secrets.SQL_PWD }}
  • Azure Pipelines:使用秘密变量并引用为 $(SQL_PWD)

集装箱供应链卫生

在共享开发环境和持续集成中采用以下做法:

  • 将镜像引用集中在一个地方,比如 Docker ARG、开发容器构建或流水线变量。
  • 将共享容器镜像固定为不可变摘要,而不是使用浮动标签。
  • 通过批准的更新流程(如Dependabot、Renovate或内部图片推广流程)审查和刷新置顶摘要。
  • 提交依赖锁定文件(如 uv.lock),或使用带哈希值的 requirements 文件,以实现可复现的 Python 安装。
  • 当你的平台提供组织批准的基础镜像和内部注册镜像时,优先考虑这些。

生产:无密码认证

对于针对Azure SQL的生产工作负载,使用Microsoft Entra认证和管理身份。 这种方法完全消除了密码:

conn = mssql_python.connect(
    server="<server>.database.windows.net",
    database="<database>",
    authentication="ActiveDirectoryMSI",
    encrypt="yes"
)

对于需要存储秘密(如 SQL 认证密码)的应用程序,可以使用 Azure 密钥保管库,并在运行时检索它们。

用紫外线进行依赖管理

uv 是一个快速的 Python 包安装程序,非常适合 CI 和容器构建:

ARG PYTHON_BASE=python:3-slim
FROM ${PYTHON_BASE}

RUN apt-get update && \
    apt-get install -y --no-install-recommends libltdl7 libkrb5-3 libgssapi-krb5-2 && \
    rm -rf /var/lib/apt/lists/*

# Install uv. In shared builds, pin the source image to an approved digest.
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev

COPY . .
CMD ["uv", "run", "python", "app.py"]

在CI中:

pip install uv
uv sync
uv run pytest

排查常见容器问题

症状 原因 修复
ImportError: libltdl.so.7 缺少系统库。 安装 libltdl7 (Debian)或 libltdl (Alpine)。
ImportError: libkrb5.so.3 缺少 Kerberos 库。 安装 libkrb5-3 (Debian)或 krb5-libs (Alpine/RHEL)。
SSL: CERTIFICATE_VERIFY_FAILED 本地 SQL Server 上的自签名证书。 trust_server_certificate="yes" 添加到连接中。 不要在生产环境中使用这个。
端口 1433 上的连接被拒绝 SQL Server容器未就绪。 添加运行状况检查或等待服务启动。
Login failed for user 'sa' 密码不符合复杂度要求。 使用包含大写、小写、数字和特殊字符的密码。
Cannot open database 数据库尚不存在。 连接前先创建或恢复数据库。
容器内首次连接缓慢 DNS 解析或凭证链启动过程。 对于本地 SQL Server,请使用localhost,1433而不是主机名。 对于 Azure SQL,请先使用 az login 进行预身份验证。