Implantar um aplicativo Django com SQL Server para Serviço de Aplicativo do Azure

Este artigo explica como implantar um aplicativo Django que usa o back-end mssql-django no Serviço de Aplicativo do Azure, incluindo a configuração do driver ODBC, segredos baseados em variáveis de ambiente e autenticação com identidade gerenciada.

Pré-requisitos

  • Uma assinatura de Azure
  • Uma instância do Banco de Dados SQL do Azure ou do SQL Server acessível do Azure
  • Um projeto do Django configurado com mssql-django
  • CLI do Azure instalado

Driver ODBC no Serviço de Aplicativo do Azure

As instâncias do Serviço de Aplicativo do Azure no Linux incluem o Driver ODBC da Microsoft para SQL Server. Você pode verificar a versão do driver instalada executando:

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

Note

Serviço de Aplicativo do Azure normalmente inclui o Driver ODBC 17 e/ou 18 pré-instalado nos planos do Linux. Os planos do Serviço de Aplicativo do Windows também incluem o driver ODBC.

Usar variáveis de ambiente para segredos

Não codifique as credenciais do banco de dados em settings.py. Use variáveis de ambiente e defina-as como configurações de aplicativo do Serviço de Aplicativo:

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

Para valores necessários, como DB_NAME e DB_HOST, considere usar os.environ["DB_NAME"] (sem um padrão) para que o aplicativo falhe imediatamente com uma clara KeyError se a variável de ambiente estiver ausente.

Defina as variáveis de ambiente em Serviço de Aplicativo do 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>

Use a autenticação de identidade gerenciada

Para implantações de produção, use a identidade gerenciada para evitar o armazenamento de credenciais. Habilite a identidade gerenciada atribuída pelo sistema em seu Serviço de Aplicativo:

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

Conceda acesso à identidade gerenciada ao banco de dados SQL do Azure:

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

Conceda apenas as funções de que seu aplicativo precisa. A db_ddladmin função de banco de dados fixa será necessária somente se o aplicativo executar migrações. Para cargas de trabalho somente de leitura, db_datareader é suficiente.

Se o servidor estiver configurado para autenticação somente pelo Microsoft Entra, FROM EXTERNAL PROVIDER falhará com Msg 33130 porque o servidor não consegue acessar o Microsoft Graph para resolver o nome da identidade. Crie o usuário manualmente com CREATE USER [<your-app-name>] WITH SID = 0x<sid-hex>, TYPE = E, onde <sid-hex> é derivado da ID do aplicativo (cliente) da identidade gerenciada, não de sua ID de objeto. Para obter as etapas de conversão, consulte Conceder acesso à identidade em SQL do Azure.

Configurar settings.py para usar a identidade gerenciada:

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

Usar tokens de acesso com ManagedIdentityCredential

Como alternativa, use a configuração TOKEN com azure.identity:

Cuidado

O TOKEN valor é buscado uma vez na inicialização do processo e expira após 60 a 90 minutos. Para implantações de serviço de aplicativo de longa execução, use essa abordagem somente se você também implementar a lógica de atualização de token ou a reciclagem de trabalho de curta duração. Se o padrão direto ActiveDirectoryMsi funcionar no seu ambiente, isso evita o problema de token na inicialização.

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é conveniente para desenvolvimento e bases de código compartilhadas porque tenta vários tipos de credencial automaticamente, portanto, o mesmo código funciona em um laptop, em CI e em Azure. No entanto, cada tipo de credencial que não se aplica adiciona vários segundos de tempo limite, o que retarda a inicialização. Como o App Service sempre tem uma identidade gerenciada disponível, ManagedIdentityCredential autentica imediatamente sem a cadeia de sondagem. Instale azure-identity no arquivo de requisitos: pip install azure-identity.

Executar migrações durante a implantação

Adicione um script pós-implantação ou um comando de inicialização para executar migrações automaticamente:

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

Coletar arquivos estáticos

Configurar o tratamento de arquivos estáticos para produção:

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

Execute collectstatic como parte de sua implantação:

python manage.py collectstatic --noinput

Implantar no Serviço de Aplicativo

O Serviço de Aplicativo pode hospedar um aplicativo Django de duas maneiras:

  • Imagem interna do Python no Linux: o App Service compila seu código a partir do código-fonte e fornece o runtime do Python.
  • Imagem personalizada do Docker: você mesmo cria a imagem e faz referência a ela a partir de um registro de contêiner.

Ambos os caminhos podem usar uma identidade gerenciada atribuída pelo sistema para autenticar em SQL do Azure, mas a receita é diferente. Escolha a guia que corresponde ao seu tipo de implantação.

Com a imagem interna do Python no Linux, o builder Oryx do App Service instala requirements.txt e inicia automaticamente seu aplicativo Django com gunicorn. O proxy HTTP local de identidade gerenciada permite que Authentication=ActiveDirectoryMsi funcione diretamente a partir da cadeia de conexão ODBC. Use o settings.py conforme mostrado em Usar autenticação de identidade gerenciada.

Implante seu código com az webapp up, habilite a identidade gerenciada atribuída pelo sistema e defina as variáveis de ambiente de banco de dados:

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

Em seguida, conceda o acesso à identidade gerenciada no SQL, conforme descrito em Usar autenticação de identidade gerenciada.

Desenvolvimento local com o Docker Compose

Para desenvolvimento e teste locais, use o Docker Compose para executar seu aplicativo Django ao lado de um contêiner de 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

O contêiner SQL Server não cria bancos de dados de aplicativo automaticamente. Depois de iniciar os contêineres, crie o banco de dados e execute as migrações:

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

A imagem de contêiner SQL Server requer ACCEPT_EULA=Y e uma senha SA forte. Para ambientes de produção, use o Banco de Dados SQL do Azure com identidade gerenciada em vez de credenciais do SQL Server. Consulte Usar autenticação de identidade gerenciada.