Développement conteneur et local avec mssql-django

Ce guide traite de la configuration de l’environnement pour les développeurs Django travaillant avec le mssql-django back-end sur Windows, Linux, macOS, conteneurs Docker, devcontainers et pipelines CI.

Prerequisites

  • Python 3.10 à 3.14. Django 6.0 et 6.1 nécessitent Python 3.12 et versions ultérieures.
  • Docker Desktop (pour le développement basé sur des conteneurs)
  • Microsoft ODBC Driver 17 ou 18 pour SQL Server lorsque vous utilisez le chemin pyodbc par défaut. Consultez Télécharger le pilote ODBC pour SQL Server.
  • Une image de base compatible avec le package requis mssql-python : Windows x64, Windows ARM64 avec Python 3.11 et versions ultérieures, macOS 15 et versions ultérieures, ou Linux x64/ARM64 avec glibc 2.28 et versions ultérieures ou musl 1.2 et versions ultérieures. SUSE Linux sur ARM64 n’est pas pris en charge.

Le chemin mssql-python ne nécessite pas un pilote Microsoft ODBC séparé pour l'installation de SQL Server. Il a toujours besoin du runtime unixODBC, car le backend importe pyodbc quand Django le charge. Pour plus d’informations, voir Sélectionner le pilote de base de données pour mssql-django.

L’utilitaire sqlcmd (Go) peut créer un conteneur SQL Server dans une seule commande. Il gère automatiquement le contexte d’extraction d’images Docker, de génération de mot de passe, d’affectation de port et de connexion :

sqlcmd create mssql --accept-eula

Pour créer un conteneur avec un exemple de base de données déjà attaché :

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

Après la création, sqlcmd stocke le contexte de connexion afin de pouvoir interroger immédiatement :

sqlcmd query "SELECT @@VERSION"

Configurez Django pour se connecter à l’aide des informations de connexion que sqlcmd a affichées au moment de la création. Utilisez sqlcmd config view pour les récupérer ultérieurement :

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",
        },
    },
}

Lorsque vous avez terminé, arrêtez ou supprimez le conteneur :

sqlcmd stop
sqlcmd delete

Tip

Exécutez sqlcmd create mssql --user-database mydb pour créer un conteneur avec une base de données utilisateur vide prête pour le développement.

SQL Server local dans Visual Studio Code

L’extension MSSQL pour Visual Studio Code peut créer des conteneurs SQL Server locaux directement à partir de l’éditeur :

  1. Ouvrez la vue SQL Server dans la barre d’activité.
  2. Sélectionnez Ajouter une connexion>créer un SQL Server local (ou utilisez la palette de commandes MS SQL : Créer un SQL Server local).
  3. Choisissez la version SQL Server et acceptez le CLUF.
  4. L’extension extrait l’image conteneur, génère un mot de passe et ajoute automatiquement un profil de connexion.

Une fois le conteneur en cours d’exécution, vous pouvez parcourir les bases de données, exécuter des requêtes et gérer des objets dans Visual Studio Code avant de passer à votre code Django.

SQL Server local avec Docker

Si vous préférez gérer directement des conteneurs, l’image de conteneur SQL Server officielle fonctionne avec deux variables d’environnement :

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

Utiliser MSSQL_SA_PASSWORD pour les conteneurs SQL Server. L’ancienne SA_PASSWORD variable est déconseillée. Le mot de passe doit respecter SQL Server exigences de complexité : au moins 8 caractères, avec des majuscules, des chiffres et des caractères spéciaux.

Attendez quelques secondes pour que le conteneur démarre, puis exécutez les migrations :

python manage.py migrate
python manage.py createsuperuser

Fichier Dockerfile pour les applications Django

Créez un fichier Docker minimal pour une application Django qui se connecte à SQL Server via le chemin pyodbc par défaut. Le pilote ODBC est la dépendance principale qui n'est pas fournie avec l'image de base 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

N’ajoutez apt-get autoremove -y pas après la purge. Il supprime libgssapi-krb5-2, que le pilote ODBC charge à l’exécution mais ne déclare pas comme une dépendance. La construction réussit toujours, et chaque connexion échoue ensuite. L’erreur pyodbc est trompeuse : la version 18 ne se charge pas, mssql-django revient à la version 17, et l’erreur nomme la version manquante 17 plutôt que la version 18 qui a échoué.

Votre requirements.txt:

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

Si votre alias de base de données utilise le chemin du pilote mssql-python avec "python_driver": "mssql_python", vous avez toujours besoin d’unixODBC, car le backend importe pyodbc lorsque Django le charge. Vous n'avez pas besoin du dépôt de paquets Microsoft ou msodbcsql18, donc le bloc d'installation ODBC se réduit à :

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

Générez et exécutez :

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

Utilisez host.docker.internal sur Docker Desktop (Windows et macOS) pour atteindre un SQL Server sur l’ordinateur hôte. Sur Linux, utilisez --network host plutôt.

Configuration de Devcontainer

Créez une .devcontainer/devcontainer.json pour Visual Studio Code qui inclut SQL Server en tant que service annexe :

{
    "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"
            ]
        }
    }
}

Ce devcontainer installe le pilote ODBC pour le chemin pyodbc par défaut et les dépendances Python mais n'inclut pas d'instance SQL Server. Démarrez-en un dans le devcontainer à l’aide sqlcmd create mssql --accept-eula (étant donné que Docker-in-Docker est disponible) ou utilisez l’approche Docker Compose pour un service de SQL Server intégré. Si vous utilisez le chemin mssql-python, remplacez l’installation msodbcsql18 dans le script post-création par sudo apt-get install -y unixodbc libkrb5-3 libgssapi-krb5-2.

Créez .devcontainer/post-create.sh pour installer le pilote ODBC pour pyodbc et les dépendances 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

Intégrer SQL Server avec Docker Compose

Pour inclure SQL Server en tant que service dans le devcontainer, utilisez 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 (Version 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"
            ]
        }
    }
}

Connectez Django au service SQL Server par nom :

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",
        },
    },
}

Authentification pour le développement

Choisissez une approche d’authentification basée sur l’emplacement d’exécution de votre application et l’emplacement où la base de données est hébergée.

Développement local contre Azure SQL

Pour le développement local avec Azure SQL, utilisez soit Authentication=ActiveDirectoryDefault dans OPTIONS["extra_params"] sur le chemin pyodbc, soit le TOKEN paramètre avec DefaultAzureCredential. DefaultAzureCredential récupère automatiquement votre az login session :

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",
        },
    },
}

Pour connaître la matrice d’authentification complète et les avertissements, consultez Microsoft Entra l’authentification avec mssql-django.

Développement de conteneurs sur Azure SQL

Pour les conteneurs s’exécutant dans Azure, utilisez le paramètre TOKEN avec ManagedIdentityCredential pour acquérir explicitement un jeton d’accès à 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",
    },
  },
}

Pour obtenir la liste complète des méthodes d’authentification, consultez Microsoft Entra authentification avec mssql-django.

Configuration du pipeline CI

Exécutez votre suite de test Django sur un conteneur de service SQL Server dans votre pipeline CI.

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

Pour les pipelines partagés, remplacez le mot de passe fictif en ligne par un secret chiffré (${{ secrets.SQL_PWD }}) et fixez l’image de service SQL Server à un condensé.

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 en fonction de l’environnement

Configurez settings.py pour lire les informations d’identification de base de données à partir de variables d’environnement. Cette configuration unique fonctionne dans le développement local, Docker et 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"),
        },
    },
}

Stocker les informations d’identification dans un .env fichier pour le développement local (ajouter .env à .gitignore) :

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

Charger des variables d’environnement avec django-environ ou 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"),
        },
    },
}

Caution

N’archivez jamais les fichiers .env dans la gestion de code source. Ajoutez .env à votre fichier .gitignore.

Résoudre les problèmes courants liés aux conteneurs

Symptôme Cause Réparer
Can't open lib 'ODBC Driver 18 for SQL Server' Le pilote ODBC n’est pas installé dans le conteneur dans le cas du chemin pyodbc, ou apt-get autoremove supprimé libgssapi-krb5-2 après l’installation. Installez msodbcsql18 dans votre fichier Docker ou un script post-création, et ne lancez apt-get autoremove pas après.
Can't open lib 'ODBC Driver 17 for SQL Server' Quand vous avez installé la version 18 La version 18 est enregistrée mais ne se charge pas, donc mssql-django revient à la version 17, qui n’est pas installée. La cause habituelle est l'absence de libgssapi-krb5-2. Installez libgssapi-krb5-2, et n’exécutez pas apt-get autoremove après avoir purgé curl.
Error loading pyodbc module: libodbc.so.2 Le conteneur ne dispose pas de l’environnement d’exécution unixODBC. Le backend importe pyodbc quand Django le charge, même sur le chemin mssql-python. Installer unixodbc (ou unixodbc-dev).
DDBC Error: Failed to load the driver Le pilote mssql-python ne peut pas charger ses propres dépendances. Installer libkrb5-3 et libgssapi-krb5-2.
Connexion refusée sur le port 1433 SQL Server conteneur non prêt. Ajoutez un contrôle d’intégrité ou attendez que le service démarre.
Login failed for user '<user_id>' Les informations d’identification sont incorrectes ou le mot de passe ne répond pas aux exigences de complexité. Sur le chemin mssql-python, une base de données qui n’existe pas affiche ce même message. Utilisez la connexion SQL correcte pour votre conteneur et vérifiez que le mot de passe répond aux exigences de complexité. Si les identifiants de connexion sont corrects, confirmez que la base de données dans NAME existe.
Cannot open database La base de données n’existe pas encore. Le chemin pyodbc rapporte ce cas ; le chemin mssql-python rapporte Login failed à la place. Créez la base de données avant d’exécuter migrateou utilisez-la master pour l’installation initiale.
Première connexion lente dans le conteneur Démarrage de la résolution DNS ou de la chaîne d’authentification. Pour les SQL Server locales, utilisez localhost plutôt qu’un nom d’hôte.
SSL Provider: [error:0A000086] Échec de validation de certificat TLS avec certificat auto-signé. Ajoutez TrustServerCertificate=yes à extra_params uniquement pour le développement.