Bereitstellen einer Django-App mit SQL Server zum Azure App Service

In diesem Artikel wird erläutert, wie Sie eine Django-Anwendung bereitstellen, die das mssql-django Back-End zum Azure App Service verwendet, einschließlich ODBC-Treiberkonfiguration, umgebungsbasierte Geheimschlüssel und verwalteter Identitätsauthentifizierung.

Voraussetzungen

  • Ein Azure-Abonnement
  • Eine Azure SQL-Datenbank- oder SQL Server Instanz, auf die über Azure zugegriffen werden kann
  • Ein mit mssql-django konfiguriertes Django-Projekt
  • Azure CLI installiert

ODBC-Treiber auf Azure App Service

Azure App Service Linux-Instanzen enthalten den Microsoft ODBC-Treiber für SQL Server. Sie können die installierte Treiberversion überprüfen, indem Sie Folgendes ausführen:

az webapp ssh --resource-group <your-rg> --name <your-app>
odbcinst -j

Note

Azure App Service enthält in der Regel ODBC-Treiber 17 und/oder 18, die auf Linux-Plänen vorinstalliert sind. Windows-App Servicepläne enthalten auch den ODBC-Treiber.

Verwenden von Umgebungsvariablen für geheime Schlüssel

Codieren Sie die Anmeldeinformationen der Datenbank nicht in settings.py. Verwenden Sie Umgebungsvariablen, und konfigurieren Sie sie als App Service-Anwendungseinstellungen:

import os

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": os.environ.get("DB_NAME", "<your-database>"),
        "USER": os.environ.get("DB_USER", ""),
        "PASSWORD": os.environ.get("DB_PASSWORD", ""),
        "HOST": os.environ.get("DB_HOST", "<your-server>.database.windows.net"),
        "PORT": os.environ.get("DB_PORT", "1433"),
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

Tip

Bei erforderlichen Werten wie DB_NAME und DB_HOST sollten Sie os.environ["DB_NAME"] (ohne Standardwert) verwenden, damit die Anwendung sofort mit einer eindeutigen KeyError fehlschlägt, wenn die Umgebungsvariable fehlt.

Legen Sie die Umgebungsvariablen in Azure App Service fest:

az webapp config appsettings set \
    --resource-group <your-rg> \
    --name <your-app> \
    --settings DB_NAME=<your-database> DB_HOST=<your-server>.database.windows.net DB_USER=<your-username> DB_PASSWORD=<your-password>

Verwenden von Authentifizierung der verwalteten Identität

Verwenden Sie für Produktionsbereitstellungen verwaltete Identitäten, um das Speichern von Anmeldeinformationen zu vermeiden. Aktivieren Sie die vom System zugewiesene verwaltete Identität in Ihrem App-Dienst:

az webapp identity assign --resource-group <your-rg> --name <your-app>

Gewähren Sie der verwalteten Identität Zugriff auf Ihre Azure SQL-Datenbank:

CREATE USER [<your-app-name>] FOR EXTERNAL PROVIDER;

ALTER ROLE db_datareader ADD MEMBER [<your-app-name>];
ALTER ROLE db_datawriter ADD MEMBER [<your-app-name>];
ALTER ROLE db_ddladmin ADD MEMBER [<your-app-name>];

Note

Weisen Sie Ihrer Anwendung nur die Rollen zu, die sie benötigt. Die db_ddladmin festen Datenbankrolle ist nur erforderlich, wenn die Anwendung Migrationen ausführt. Bei schreibgeschützten Workloads ist db_datareader ausreichend.

Wenn Ihr Server für Microsoft Entra-Only-Authentifizierung konfiguriert ist, schlägt FROM EXTERNAL PROVIDER mit Msg 33130 fehl, weil der Server Microsoft Graph nicht erreichen kann, um den Namen der Identität aufzulösen. Erstellen Sie den Benutzer manuell mit CREATE USER [<your-app-name>] WITH SID = 0x<sid-hex>, TYPE = E, wobei <sid-hex> aus der Anwendungs-ID (Client-ID) der verwalteten Identität abgeleitet wird, nicht aus der Objekt-ID. Die Konvertierungsschritte finden Sie unter Erteilen des Identitätszugriffs in Azure SQL.

Konfigurieren settings.py für die Verwendung von verwalteter Identität:

import os

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": os.environ.get("DB_NAME", "<your-database>"),
        "HOST": os.environ.get("DB_HOST", "<your-server>.database.windows.net"),
        "PORT": "1433",
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": "Authentication=ActiveDirectoryMsi",
        },
    },
}

Verwenden von Zugriffstoken mit ManagedIdentityCredential

Alternativ verwenden Sie die Einstellung TOKEN mit azure.identity:

Vorsicht

Der TOKEN Wert wird beim Starten des Prozesses einmal abgerufen und läuft nach 60-90 Minuten ab. Verwenden Sie diesen Ansatz bei lang andauernden App Service-Bereitstellungen nur, wenn Sie zusätzlich eine Logik zur Tokenaktualisierung oder ein kurzlebiges Worker-Recycling implementieren. Wenn das direkte ActiveDirectoryMsi Muster in Ihrer Umgebung funktioniert, wird das Problem mit dem Startzeittoken vermieden.

import os
from azure.identity import ManagedIdentityCredential

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

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": os.environ.get("DB_NAME", "<your-database>"),
        "HOST": os.environ.get("DB_HOST", "<your-server>.database.windows.net"),
        "PORT": "1433",
        "TOKEN": token,
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
        },
    },
}

Tip

DefaultAzureCredential ist praktisch für die Entwicklung und gemeinsam genutzte Codebasen, da mehrere Arten von Anmeldeinformationen automatisch ausprobiert werden, sodass derselbe Code auf einem Laptop, in CI und in Azure funktioniert. Jeder Anmeldedatentyp, der nicht zutrifft, verursacht jedoch zusätzlich mehrere Sekunden Wartezeit, was den Startvorgang verlangsamt. Da App Service immer eine verwaltete Identität verfügbar hat, wird ManagedIdentityCredential sofort ohne die Prüfkette authentifiziert. Installieren Sie azure-identity in Ihrer Anforderungsdatei: pip install azure-identity.

Ausführen von Migrationen während der Bereitstellung

Fügen Sie ein Skript nach der Bereitstellung oder einen Startbefehl hinzu, um Migrationen automatisch auszuführen:

az webapp config set \
    --resource-group <your-rg> \
    --name <your-app> \
    --startup-file "python manage.py migrate && gunicorn myproject.wsgi"

Sammeln statischer Dateien

Konfigurieren der statischen Dateibehandlung für die Produktion:

STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")

Führen Sie collectstatic als Teil Ihrer Bereitstellung aus:

python manage.py collectstatic --noinput

Bereitstellen in App Service

Der App-Dienst kann eine Django-App auf zwei Arten hosten:

  • Integriertes Linux-Python-Image: App Service erstellt Ihren Code aus der Quelle und stellt die Python Laufzeit bereit.
  • Benutzerdefiniertes Docker-Image: Sie erstellen das Image selbst und verweisen aus einer Containerregistrierung darauf.

Beide Pfade können eine vom System zugewiesene verwaltete Identität verwenden, um sich bei Azure SQL zu authentifizieren, aber das Rezept unterscheidet sich. Wählen Sie die Registerkarte aus, die Ihrer Bereitstellung entspricht.

Mit dem integrierten Linux-Python-Image installiert der Oryx-Builder von App Service automatisch requirements.txt und startet Ihre Django-App unter gunicorn. Der lokale HTTP-Proxy für verwaltete Identitäten ermöglicht, dass Authentication=ActiveDirectoryMsi direkt über die ODBC-Verbindungszeichenfolge funktioniert. Verwenden Sie die in Verwaltete Identitätsauthentifizierung verwenden gezeigte settings.py.

Stellen Sie Ihren Code mit az webapp up, aktivieren Sie die vom System zugewiesene verwaltete Identität, und legen Sie die Datenbankumgebungsvariablen fest:

az webapp up \
    --resource-group <your-rg> \
    --name <your-app> \
    --runtime "PYTHON:3.12" \
    --sku B1

az webapp identity assign --resource-group <your-rg> --name <your-app>

az webapp config appsettings set \
    --resource-group <your-rg> \
    --name <your-app> \
    --settings DB_NAME=<your-database> DB_HOST=<your-server>.database.windows.net

Gewähren Sie dann den verwalteten Identitätszugriff in SQL, wie unter "Verwaltete Identitätsauthentifizierung verwenden" beschrieben.

Lokale Entwicklung mit Docker Compose

Verwenden Sie Für lokale Entwicklung und Tests Docker Compose, um Ihre Django-App zusammen mit einem SQL Server-Container auszuführen:

# docker-compose.yml
services:
  db:
    image: mcr.microsoft.com/mssql/server:2022-latest
    environment:
      ACCEPT_EULA: "Y"
      MSSQL_SA_PASSWORD: "<password>"  # Must meet SQL Server complexity requirements
    ports:
      - "1433:1433"

  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      DB_HOST: db
      DB_NAME: mydb
      DB_USER: sa
      DB_PASSWORD: "<password>"
    depends_on:
      - db

Tip

Der container SQL Server erstellt keine Anwendungsdatenbanken automatisch. Erstellen Sie nach dem Starten der Container die Datenbank, und führen Sie Migrationen aus:

docker compose exec db /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "<password>" -No -Q "CREATE DATABASE mydb"
docker compose exec web python manage.py migrate

Das SQL Server Containerimage erfordert ACCEPT_EULA=Y und ein sicheres SA-Kennwort. Verwenden Sie für Produktionsumgebungen Azure SQL-Datenbank mit verwalteter Identität anstelle von SQL Server Anmeldeinformationen. Siehe Verwenden der verwalteten Identitätsauthentifizierung.