使用 mssql-django 進行容器與本地開發

本指南說明 Django 開發者在 Windows、Linux、macOS、Docker 容器、開發容器及 CI 管線中使用 mssql-django 後端作業時的環境設定。

先決條件

  • Python 3.10 到 3.14。 Django 6.0 和 6.1 需要 Python 3.12 及更新版本。
  • Docker 桌面(用於容器式開發)
  • 當你使用預設的 pyodbc 路徑時,Microsoft ODBC 驅動程式 17 或 18 適用於 SQL Server。 請參閱下載 SQL Server 的 ODBC 驅動程式。
  • 與所需mssql-python套件相容的基礎映像檔:Windows x64、Windows ARM64(含 Python 3.11 及更新版本)、macOS 15 及以後版本,或 Linux x64/ARM64(含 glibc 2.28 及以上版本)或 musl 1.2 及以後版本。 SUSE Linux 在 ARM64 上不被支援。

mssql-python 路徑不需要另外安裝 Microsoft ODBC 驅動程式 for SQL Server。 它仍然需要 unixODBC 執行階段,因為 Django 載入後端時會匯入 pyodbc。 欲了解更多資訊,請參閱 MSSQL-django 的選擇資料庫驅動程式。

sqlcmd (Go) 工具可透過單一指令建立 SQL Server 容器。 它能自動處理 Docker 映像拉取、密碼產生、埠口指派及連線上下文:

sqlcmd create mssql --accept-eula

要建立一個已經附有範例資料庫的容器:

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

建立後, sqlcmd 會儲存連線上下文,讓你能立即查詢:

sqlcmd query "SELECT @@VERSION"

設定 Django 使用建立時列印的 sqlcmd 連線細節來連接。 使用 sqlcmd config view 稍後再取回它們:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "master",
        "USER": "sa",
        "PASSWORD": "<password from sqlcmd output>",
        "HOST": "localhost",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "TrustServerCertificate=yes",
        },
    },
}

完成後,停止或刪除該容器:

sqlcmd stop
sqlcmd delete

Tip

執行 sqlcmd create mssql --user-database mydb 以建立一個容器,裡面有一個空的使用者資料庫,準備開發。

Visual Studio Code 中的本地 SQL Server

Visual Studio Code 的 MSSQL 擴充功能可直接從編輯器建立本地 SQL Server 容器:

  1. 在活動欄開啟 SQL Server 檢視。
  2. 選擇新增連線>建立本地 SQL Server(或使用指令面板:MS SQL: Create Local SQL Server)。
  3. 選擇 SQL Server 版本並接受 EULA。
  4. 擴充功能會自動拉取容器映像檔,產生密碼並新增連線設定檔。

容器開始執行後,你可以先在 Visual Studio Code 中瀏覽資料庫、執行查詢及管理物件,再切換回 Django 程式碼。

本地 SQL Server 與 Docker

如果你偏好直接管理容器,官方 SQL Server 容器映像支援兩個環境變數:

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

Important

將 MSSQL_SA_PASSWORD 用於 SQL Server 容器。 舊 SA_PASSWORD 變數已被棄用。 密碼必須符合 SQL Server 的複雜度要求:至少 8 個字元,包含大寫、小寫、數字及特殊字元。

等幾秒鐘容器啟動,然後執行遷移:

python manage.py migrate
python manage.py createsuperuser

Django 應用程式的 Dockerfile

為一個 Django 應用程式建立一個最小的 Dockerfile,該應用程式透過預設的 pyodbc 路徑連接到 SQL Server。 ODBC 驅動程式是 Python 基底映像未隨附的關鍵相依性:

FROM python:3.12-slim

# Install ODBC Driver 18 for SQL Server
RUN apt-get update && \
    apt-get install -y --no-install-recommends curl gnupg2 && \
    curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | \
        gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg && \
    echo "deb [signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > \
        /etc/apt/sources.list.d/mssql-release.list && \
    apt-get update && \
    ACCEPT_EULA=Y apt-get install -y --no-install-recommends msodbcsql18 unixodbc-dev && \
    apt-get purge -y curl gnupg2 && \
    rm -rf /var/lib/apt/lists/*

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

COPY . .

# Collect static files
RUN python manage.py collectstatic --noinput

EXPOSE 8000
CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]

Important

清除後不要再加。apt-get autoremove -y 它會移除 ODBC 驅動程式在執行階段載入、但未將其宣告為相依性的 libgssapi-krb5-2。 建置仍然成功,但所有連線接著都失敗了。 pyodbc 錯誤具有誤導性:版本 18 無法載入,mssql-django 會退回到版本 17,且錯誤點名的是缺少的版本 17,而非失敗的版本。

您的 requirements.txt:

django>=5.2,<6.2
mssql-django>=2.0
gunicorn>=22.0

如果你的資料庫別名使用含有 "python_driver": "mssql_python" 的 mssql-python 驅動程式路徑,你仍然需要 unixODBC,因為 Django 載入該後端時會匯入 pyodbc。 你不需要 Microsoft 套件倉庫或 msodbcsql18,因此 ODBC 安裝區塊會縮小為:

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

建造與執行:

docker build -t mydjango .
docker run -e "DB_HOST=host.docker.internal" -e "DB_NAME=<database>" \
  -e "DB_USER=<user_id>" -e "DB_PASSWORD=<password>" \
  -p 8000:8000 mydjango

Note

在 Docker 桌面(Windows 和 macOS)上使用host.docker.internal,以存取主機上的 SQL Server。 在 Linux 上,請改用--network host

開發容器設定

為 Visual Studio Code 建立一個.devcontainer/devcontainer.json包含 SQL Server 作為側車服務的系統:

{
    "name": "Django + SQL Server",
    "image": "mcr.microsoft.com/devcontainers/python:3",
    "features": {
        "ghcr.io/devcontainers/features/docker-in-docker:2": {}
    },
    "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
    "postCreateCommand": "bash .devcontainer/post-create.sh",
    "forwardPorts": [1433, 8000],
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-python.python",
                "ms-mssql.mssql"
            ]
        }
    }
}

這個開發容器會安裝預設 pyodbc 路徑和 Python 相依的 ODBC 驅動程式,但不包含 SQL Server 實例。 在開發容器內使用 sqlcmd create mssql --accept-eula 啟動一個 SQL Server 執行個體(因為支援 Docker-in-Docker),或使用 Docker Compose 方式來建立內建的 SQL Server 服務。 如果你採用 mssql-python 路徑,請將 post-create 指令碼中的 msodbcsql18 install 替換為 sudo apt-get install -y unixodbc libkrb5-3 libgssapi-krb5-2。

建立.devcontainer/post-create.sh,以安裝供 pyodbc 使用的 ODBC 驅動程式和 Python 相依性:

#!/bin/bash
set -e

# Install ODBC Driver 18
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | \
    sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
echo "deb [signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" | \
    sudo tee /etc/apt/sources.list.d/mssql-release.list
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev

pip install -r requirements.txt

在 Docker Compose 中加入 SQL Server

若要將 SQL Server 作為服務納入開發容器,請使用 Docker Compose:

.devcontainer/docker-compose.yml:

services:
  app:
    image: mcr.microsoft.com/devcontainers/python:3
    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: "<strong_password>"
    ports:
      - "1433:1433"

.devcontainer/devcontainer.json(Compose 版本):

{
    "name": "Django + SQL Server",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspace",
    "postCreateCommand": "bash .devcontainer/post-create.sh",
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-python.python",
                "ms-mssql.mssql"
            ]
        }
    }
}

依名稱連接 Django 至 SQL Server 服務:

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "mydb",
        "USER": "sa",
        "PASSWORD": "<password>",
        "HOST": "db",
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "TrustServerCertificate=yes",
        },
    },
}

開發認證

根據應用程式執行地點及資料庫託管地點,選擇認證方式。

針對 Azure SQL 的本機開發

若要針對 Azure SQL 進行本機開發,請在 pyodbc 路徑中使用 Authentication=ActiveDirectoryDefault 內的 OPTIONS["extra_params"],或搭配 DefaultAzureCredential 使用 TOKEN 設定。 DefaultAzureCredential 自動接續你的 az login 工作階段:

from azure.identity import DefaultAzureCredential

credential = DefaultAzureCredential()
token = credential.get_token("https://database.windows.net/.default").token

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": "mydb",
        "HOST": "<server>.database.windows.net",
        "PORT": "1433",
        "TOKEN": token,
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

完整認證矩陣與注意事項,請參閱 Microsoft Entra 與 mssql-django 的認證。

針對 Azure SQL 的容器開發

對於在 Azure 中執行的容器,請搭配 TOKEN 使用 ManagedIdentityCredential 設定,以明確取得 Microsoft Entra 存取權杖:

from azure.identity import ManagedIdentityCredential

credential = ManagedIdentityCredential()
token = credential.get_token("https://database.windows.net/.default").token

DATABASES = {
  "default": {
    "ENGINE": "mssql",
    "NAME": "mydb",
    "HOST": "<server>.database.windows.net",
    "PORT": "1433",
    "TOKEN": token,
    "OPTIONS": {
      "driver": "ODBC Driver 18 for SQL Server",
    },
  },
}

完整認證方法清單,請參見 Microsoft Entra 與 mssql-django 的認證。

CI 管線設定

在你的 CI 管線中,將你的 Django 測試套件與 SQL Server 服務容器對比。

GitHub Actions

name: Django Tests
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      sqlserver:
        image: mcr.microsoft.com/mssql/server:2022-latest
        env:
          ACCEPT_EULA: Y
          MSSQL_SA_PASSWORD: "<strong_password>"
        ports:
          - 1433:1433
        options: >-
          --health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P \"$$MSSQL_SA_PASSWORD\" -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: "3.12"

      - name: Install ODBC Driver for pyodbc
        run: |
          curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | \
              sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
          echo "deb [signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/ubuntu/$(lsb_release -rs)/prod $(lsb_release -cs) main" | \
              sudo tee /etc/apt/sources.list.d/mssql-release.list
          sudo apt-get update
          sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run tests
        env:
          DB_HOST: localhost
          DB_NAME: "master"
          DB_USER: "<user_id>"
          DB_PASSWORD: "<password>"
        run: python manage.py test

Tip

對於共用管線,請將內嵌的預留位置密碼替換為加密密鑰(${{ secrets.SQL_PWD }}),並將 SQL Server 服務映像固定為特定摘要。

Azure Pipelines

trigger:
  - main

resources:
  containers:
    - container: sqlserver
      image: mcr.microsoft.com/mssql/server:2022-latest
      env:
        ACCEPT_EULA: Y
        MSSQL_SA_PASSWORD: "<strong_password>"
      ports:
        - 1433:1433

pool:
  vmImage: ubuntu-latest

services:
  sqlserver: sqlserver

steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: "3.12"

  - script: |
      curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | \
          sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg
      echo "deb [signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/ubuntu/$(lsb_release -rs)/prod $(lsb_release -cs) main" | \
          sudo tee /etc/apt/sources.list.d/mssql-release.list
      sudo apt-get update
      sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 unixodbc-dev
      pip install -r requirements.txt
    displayName: Install dependencies

  - script: python manage.py test
    displayName: Run tests
    env:
      DB_HOST: "localhost"
      DB_NAME: "master"
      DB_USER: "<user_id>"
      DB_PASSWORD: "<password>"

以環境為基礎的 settings.py

設定 settings.py 從環境變數讀取資料庫憑證。 這個單一配置可跨越本地開發、Docker 與 CI:

import os

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": os.environ.get("DB_NAME", "mydb"),
        "USER": os.environ.get("DB_USER", ""),
        "PASSWORD": os.environ.get("DB_PASSWORD", ""),
        "HOST": os.environ.get("DB_HOST", "localhost"),
        "PORT": os.environ.get("DB_PORT", "1433"),
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": os.environ.get("DB_EXTRA_PARAMS", "TrustServerCertificate=yes"),
        },
    },
}

將憑證儲存在 .env 檔案中以供本地開發(新增 .env 到 .gitignore):

DB_HOST=localhost
DB_NAME=mydb
DB_USER=<user_id>
DB_PASSWORD=<password>

使用 django-environ 或 python-dotenv 載入環境變數:

pip install django-environ
import environ

env = environ.Env()
environ.Env.read_env()  # Reads .env from the directory holding this settings file

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": env("DB_NAME"),
        "USER": env("DB_USER", default=""),
        "PASSWORD": env("DB_PASSWORD", default=""),
        "HOST": env("DB_HOST", default="localhost"),
        "PORT": env("DB_PORT", default="1433"),
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": env("DB_EXTRA_PARAMS", default="TrustServerCertificate=yes"),
        },
    },
}

謹慎

切勿將 .env 檔案提交到原始碼控制。 把它加 .env 到你的 .gitignore 檔案裡。

排除常見容器問題

癥狀 原因 修復
Can't open lib 'ODBC Driver 18 for SQL Server' ODBC 驅動程式未安裝在 pyodbc 路徑的容器中,或 apt-get autoremove 是在安裝後被 libgssapi-krb5-2 剝離。 安裝 msodbcsql18 在你的 Dockerfile 或後製腳本裡,之後不要執行 apt-get autoremove 。
Can't open lib 'ODBC Driver 17 for SQL Server' 當你安裝版本 18 時 第 18 版已註冊但無法載入,因此 mssql-django 會退回到未安裝的第 17 版。 通常是因為遺漏了 libgssapi-krb5-2。 安裝 libgssapi-krb5-2,並且在清除 apt-get autoremove 後不要執行 curl。
Error loading pyodbc module: libodbc.so.2 容器沒有 unixODBC 執行階段環境。 即使是在 mssql-python 路徑中,當 Django 載入後端時,後端仍會匯入 pyodbc。 安裝 unixodbc (或 unixodbc-dev)。
DDBC Error: Failed to load the driver mssql-python 驅動程式無法載入自己的相依性。 安裝 libkrb5-3 和 libgssapi-krb5-2。
1433埠拒絕連線 SQL Server 容器尚未準備好。 加做健康檢查或等待服務開始。
Login failed for user '<user_id>' 憑證錯誤或密碼不符合複雜度要求。 在 mssql-python 路徑上,一個不存在的資料庫也會發出同樣的訊息。 使用正確的容器 SQL 登入,並確保密碼符合複雜度要求。 如果登入正確,請確認該 NAME 資料庫是否存在。
Cannot open database 資料庫還不存在。 pyodbc 路徑會回報此情況;而 mssql-python 路徑則會改為回報 Login failed。 在執行 migrate 前建立資料庫,或使用 master 進行初始設定。
容器中首次連線緩慢 DNS 解析或認證鏈啟動。 對於本機 SQL Server,請使用 localhost,不要使用主機名稱。
SSL Provider: [error:0A000086] 使用自簽憑證時,TLS 憑證驗證失敗。 僅供開發時,將 TrustServerCertificate=yes 新增至 extra_params。