Развертывание приложения Django с помощью SQL Server для Служба приложений Azure

В этой статье объясняется, как развернуть приложение Django, использующее mssql-django в качестве серверной части, в Служба приложений Azure, включая настройку драйвера ODBC, секреты, заданные через переменные среды, и аутентификацию с использованием управляемого удостоверения.

Необходимые условия

  • подписка Azure
  • Экземпляр База данных SQL Azure или SQL Server, доступный из Azure
  • Проект Django, настроенный с помощью mssql-django
  • установлен Azure CLI

Драйвер ODBC на Служба приложений Azure

Экземпляры Linux Служба приложений Azure содержат Microsoft ODBC Driver for SQL Server. Чтобы проверить установленную версию драйвера, выполните следующую команду:

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

Note

Служба приложений Azure обычно включает драйвер ODBC 17 и/или 18, предварительно установленный в планах Linux. приложение для Windows планы обслуживания также включают драйвер ODBC.

Используйте переменные среды для хранения секретов

Не прописывайте учетные данные базы данных в settings.py жестко. Используйте переменные среды и настройте их в качестве параметров приложения службы приложений:

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

Для обязательных значений, таких как DB_NAME и DB_HOST, рекомендуется использовать os.environ["DB_NAME"] (без значения по умолчанию), чтобы приложение сразу завершалось с понятной KeyError, если переменная среды отсутствует.

Задайте переменные среды в Служба приложений Azure:

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>

Используйте аутентификацию с помощью управляемой идентичности

Для рабочих развертываний используйте управляемое удостоверение, чтобы избежать хранения учетных данных. Включите управляемое удостоверение, назначаемое системой, для вашей службы приложений:

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

Предоставьте управляемому удостоверению доступ к базе данных Azure SQL:

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

Предоставьте только роли, необходимые приложению. Предопределённая роль базы данных db_ddladmin требуется только в том случае, если приложение выполняет миграции. Для нагрузок, предназначенных только для чтения, достаточно db_datareader.

Если сервер настроен для аутентификации только через Microsoft Entra, FROM EXTERNAL PROVIDER завершается сбоем с Msg 33130, потому что сервер не может обратиться к Microsoft Graph, чтобы разрешить имя удостоверения. Создайте пользователя вручную с помощью CREATE USER [<your-app-name>] WITH SID = 0x<sid-hex>, TYPE = E, где <sid-hex> формируется на основе идентификатора приложения (клиента) управляемой идентичности, а не на основе её идентификатора объекта. Сведения о шагах преобразования см. в разделе Предоставление удостоверению доступа в Azure SQL.

Настройте settings.py для использования управляемого удостоверения:

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

Использование маркеров доступа с ManagedIdentityCredential

В качестве альтернативы используйте параметр TOKENвместе с azure.identity:

Caution

Значение TOKEN извлекается один раз при запуске процесса и истекает через 60–90 минут. Для длительно выполняемых развертываний App Service используйте этот подход только в том случае, если вы также реализуете логику обновления токенов или кратковременную перезагрузку рабочих процессов. Если в вашей среде шаблон ActiveDirectoryMsi напрямую работает, это позволяет избежать проблемы с токеном при запуске.

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удобно для разработки и общих баз кода, так как он пытается автоматически использовать несколько типов учетных данных, поэтому один и тот же код работает на ноутбуке, в CI и в Azure. Однако каждый тип учетных данных, который не применяется, добавляет несколько секунд времени ожидания, что замедляет запуск. Поскольку в App Service всегда доступно управляемое удостоверение, ManagedIdentityCredential проходит аутентификацию сразу, без цепочки проверок. Установите azure-identity в файле требований: pip install azure-identity

Выполнение миграций во время развертывания

Добавьте скрипт после развертывания или команду запуска для автоматического выполнения миграции:

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

Сбор статических файлов

Настройка обработки статических файлов для рабочей среды:

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

Запустите collectstatic в рамках развертывания:

python manage.py collectstatic --noinput

Развертывание в службе приложений Azure

Служба приложений может размещать приложение Django двумя способами:

  • Встроенный образ Linux Python: служба приложений создает код из источника и предоставляет среду выполнения Python.
  • Пользовательский образ Docker: вы создаете образ самостоятельно и ссылаетесь на него из реестра контейнеров.

Оба пути могут использовать управляемое удостоверение, назначаемое системой, для проверки подлинности в Azure SQL, но рецепт отличается. Выберите вкладку, соответствующую развертыванию.

Со встроенным образом Linux Python сборщик Oryx в App Service автоматически устанавливает requirements.txt и запускает приложение Django под gunicorn. Локальный HTTP-прокси управляемой идентификации позволяет Authentication=ActiveDirectoryMsi работать напрямую из строки подключения ODBC. Используйте settings.py, показанный в разделе Использование аутентификации с управляемым удостоверением.

Разверните код с помощью az webapp up, включите управляемую идентификацию, назначаемую системой, и задайте переменные среды базы данных:

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

Затем предоставьте доступ к управляемому удостоверению в SQL, как описано в разделе "Использование проверки подлинности управляемого удостоверения".

Локальная разработка с помощью Docker Compose

Для локальной разработки и тестирования используйте Docker Compose для запуска приложения Django вместе с контейнером SQL Server:

# 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

Контейнер SQL Server не создает базы данных приложений автоматически. После запуска контейнеров создайте базу данных и выполните миграцию:

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

Для образа контейнера SQL Server требуются ACCEPT_EULA=Y и сложный пароль SA. Для производственных сред используйте База данных SQL Azure с управляемым удостоверением вместо учетных данных SQL Server. См. Аутентификация с помощью управляемого удостоверения.