Desenvolvimento em contentor e desenvolvimento local com mssql-python

Este guia aborda a configuração do ambiente para programadores Python que trabalham com o mssql-python driver em Windows, Linux, macOS, containers Docker, devcontainers e pipelines de CI.

Pré-requisitos

  • Python 3.10 ou posterior.
  • Docker Desktop (para desenvolvimento baseado em contentores).
  • Um host compatível com x64 (Intel, AMD ou VM x64) para contentores Linux do SQL Server. Os contentores Linux do SQL Server não suportam hosts ARM64.

A utilidade go-sqlcmd pode criar um contentor SQL Server num único comando. Trata automaticamente da consulta de imagens Docker, geração de palavra-passe, atribuição de portas e contexto de ligação:

sqlcmd create mssql --accept-eula

Para criar um contentor com uma base de dados de amostras já anexada:

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

Após a criação, sqlcmd armazena o contexto da ligação para que possas consultar imediatamente:

sqlcmd query "SELECT @@VERSION"

Cria um login de aplicação uma vez e depois usa-o no teu código Python:

sqlcmd query --database <database> "CREATE LOGIN <app-login> WITH PASSWORD = '<password>';"
sqlcmd query --database <database> "CREATE USER <app-login> FOR LOGIN <app-login>;"
sqlcmd query --database <database> "ALTER ROLE db_datareader ADD MEMBER <app-login>;"
sqlcmd query --database <database> "ALTER ROLE db_datawriter ADD MEMBER <app-login>;"

Substitua <database>, <app-login>, e <password> por valores do seu ambiente.

Estabelece a ligação a partir do Python usando os detalhes da ligação que sqlcmd imprimiu no momento da criação. Use sqlcmd config view para os recuperar mais tarde:

import mssql_python

conn = mssql_python.connect(
    server="localhost,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

cursor = conn.cursor()
cursor.execute("SELECT @@VERSION")
print(cursor.fetchval())
conn.close()

Quando terminar, pare ou apague o contentor:

sqlcmd stop
sqlcmd delete

Sugestão

Execute sqlcmd create mssql --user-database <database> para criar um contentor com uma base de dados de utilizadores vazia, pronta para desenvolvimento.

SQL Server Local a partir do VS Code

A extensão SQL Server para VS Code (ms-mssql.mssql) pode criar contentores SQL Server locais diretamente a partir do editor:

  1. Abra a vista SQL Server na Barra de Atividades.
  2. Selecione Adicionar Ligação>Criar SQL Server Local (ou use a Paleta de Comandos: MS SQL: Criar SQL Server Local).
  3. Escolha a versão do SQL Server e aceite o EULA.
  4. A extensão extrai a imagem do contentor, gera uma palavra-passe e adiciona automaticamente um perfil de ligação.

Depois de o contentor estar a correr, podes navegar por bases de dados, fazer consultas e gerir objetos diretamente no VS Code antes de mudares para código Python.

Servidor SQL local com Docker

Se preferir gerir contentores diretamente, a imagem oficial do contentor do SQL Server funciona com duas variáveis de ambiente:

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

Espera alguns segundos e depois liga-te a partir do Python:

import mssql_python

conn = mssql_python.connect(
    server="localhost,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

cursor = conn.cursor()
cursor.execute("SELECT @@VERSION")
print(cursor.fetchval())
conn.close()

Importante

Use MSSQL_SA_PASSWORD para contentores do SQL Server. A variável mais antiga SA_PASSWORD está obsoleta. A palavra-passe deve cumprir os requisitos de complexidade do SQL Server: pelo menos 8 caracteres, com maiúsculas, minúsculas, dígitos e caracteres especiais.

Para carregar a base de dados de exemplos do AdventureWorks no contentor:

# Download AdventureWorks backup
curl -L -o AdventureWorks2022.bak \
  "https://github.com/Microsoft/sql-server-samples/releases/download/adventureworks/AdventureWorks2022.bak"

# Copy into container
docker cp AdventureWorks2022.bak sql1:/var/opt/mssql/backup/

# Restore
docker exec sql1 /opt/mssql-tools18/bin/sqlcmd \
  -S localhost -U sa -P "YourStr0ngP@ssword" -C \
  -Q "RESTORE DATABASE AdventureWorks2022 FROM DISK='/var/opt/mssql/backup/AdventureWorks2022.bak' WITH MOVE 'AdventureWorks2022' TO '/var/opt/mssql/data/AdventureWorks2022.mdf', MOVE 'AdventureWorks2022_log' TO '/var/opt/mssql/data/AdventureWorks2022_log.ldf'"

Sugestão

A abordagem sqlcmd create mssql --using na secção anterior trata automaticamente da transferência e do restauro.

Dockerfile para aplicações Python

Mantenha a referência da imagem base em Python num só local para que builds locais, devcontainers e pipelines de CI não se desviem. Para experimentação local, uma etiqueta ampla e suportada como python:3-slim funciona bem. Para devcontainers partilhados, CI e produção, substitua essa etiqueta por uma imagem aprovada e fixada no digest da lista de permissões da sua organização.

Crie um Dockerfile mínimo para uma aplicação Python que se ligue ao Microsoft SQL:

ARG PYTHON_BASE=python:3-slim
FROM ${PYTHON_BASE}

# Install system libraries required by mssql-python on Linux
RUN apt-get update && \
    apt-get install -y --no-install-recommends libltdl7 libkrb5-3 libgssapi-krb5-2 && \
    rm -rf /var/lib/apt/lists/*

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

COPY . .
CMD ["python", "app.py"]

O seu requirements.txt:

mssql-python>=1.11.0

Construir e executar:

docker build -t myapp .
docker run -e SQL_SERVER=host.docker.internal,1433 myapp

Em ambientes partilhados, forneça uma referência aprovada de uma imagem de base imutável com --build-arg PYTHON_BASE=python:3-slim@sha256:<approved-digest>.

Note

Use host.docker.internal no Docker Desktop (Windows e macOS) para aceder a um SQL Server na máquina anfitriã. No Linux, usa --network host em vez disso.

Linux alpino

Alpine usa musl em vez de glibc. Instale os pacotes necessários:

ARG PYTHON_BASE=python:3-alpine
FROM ${PYTHON_BASE}

RUN apk add --no-cache libltdl krb5-libs

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

COPY . .
CMD ["python", "app.py"]

Configuração de devcontainer

Reutilize o mesmo Dockerfile com que a sua aplicação compila. Esta abordagem mantém o devcontainer alinhado com a imagem de runtime e evita a dispersão dos pins da versão Python por vários ficheiros.

Crie um .devcontainer/devcontainer.json para VS Code:

{
    "name": "Python + SQL Server",
    "build": {
        "dockerfile": "../Dockerfile",
        "context": ".."
    },
    "features": {
        "ghcr.io/devcontainers/features/docker-in-docker:2": {}
    },
    "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
    "postCreateCommand": "pip install --no-cache-dir -r requirements.txt",
    "forwardPorts": [1433],
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-python.python",
                "ms-mssql.mssql"
            ]
        }
    }
}

Para incluir o SQL Server como serviço no devcontainer, use o Docker Compose:

.devcontainer/docker-compose.yml:

services:
  app:
    build:
      context: ..
      dockerfile: Dockerfile
    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: "YourStr0ngP@ssword"
    ports:
      - "1433:1433"

.devcontainer/devcontainer.json (Versão Compose):

{
    "name": "Python + SQL Server",
    "dockerComposeFile": "docker-compose.yml",
    "service": "app",
    "workspaceFolder": "/workspace",
    "postCreateCommand": "pip install -r requirements.txt",
    "customizations": {
        "vscode": {
            "extensions": [
                "ms-python.python",
                "ms-mssql.mssql"
            ]
        }
    }
}

Para espaços de trabalho partilhados, fixe a imagem do serviço SQL Server num resumo aprovado em vez de depender de uma tag flutuante. Carrega MSSQL_SA_PASSWORD a partir de um ficheiro local .env ou de um armazenamento secreto da plataforma em vez de o registar no controlo de versão.

Ligue-se ao serviço SQL Server pelo nome:

conn = mssql_python.connect(
    server="db,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

Dependências específicas da plataforma

O controlador mssql-python inclui os seus componentes nativos. Não precisas de instalar um gestor externo de drivers ODBC. No entanto, o driver requer um pequeno conjunto de bibliotecas de sistema em Linux e macOS.

Platform Pacotes obrigatórios Comando de Instalação
Windows None Incluído no volante.
Ubuntu / Debian libltdl7, libkrb5-3, libgssapi-krb5-2 sudo apt-get install libltdl7 libkrb5-3 libgssapi-krb5-2
Red Hat / CentOS / Fedora libtool-ltdl, krb5-libs sudo dnf install libtool-ltdl krb5-libs
Alpine libltdl, krb5-libs apk add libltdl krb5-libs
macOS OpenSSL (via Homebrew) brew install openssl

No macOS, se encontrares erros de SSL, define as opções do linker:

export LDFLAGS="-L/opt/homebrew/opt/openssl/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openssl/include"

Para instruções completas de instalação, consulte Instalar mssql-python.

Autenticação para desenvolvimento

Desenvolvimento local contra SQL do Azure

Use ActiveDirectoryDefault para autenticação sem palavra-passe. Esta opção processa automaticamente, em cadeia, o CLI do Azure, o Visual Studio, as variáveis de ambiente e a identidade gerida:

conn = mssql_python.connect(
    server="<server>.database.windows.net",
    database="<database>",
    authentication="ActiveDirectoryDefault",
    encrypt="yes"
)

Certifique-se de que está iniciado sessão usando CLI do Azure:

az login

Desenvolvimento local contra SQL Server

Use autenticação SQL com uma instância local.

conn = mssql_python.connect(
    server="localhost,1433",
    uid="<app login>",
    pwd="<password>",
    encrypt="yes",
    trust_server_certificate="yes"
)

Desenvolvimento de containers contra SQL do Azure

Para contentores a correr no Azure (App Service, Container Apps, AKS), use identidade gerida.

conn = mssql_python.connect(
    server="<server>.database.windows.net",
    database="<database>",
    authentication="ActiveDirectoryMSI",
    encrypt="yes"
)

Para contentores a correr localmente e que precisam de se ligar ao SQL do Azure, certifique-se de que o contentor tem uma fonte de credenciais que ActiveDirectoryDefault possa usar. As opções mais fiáveis são:

  • Instala o CLI do Azure no container e faz login lá. Monte ~/.azure a partir do host apenas se a imagem do contentor já incluir o CLI do Azure e pretender reutilizar essa cache de credenciais.
  • Forneça credenciais de principal de serviço através de variáveis de ambiente como AZURE_CLIENT_ID, AZURE_TENANT_ID, e AZURE_CLIENT_SECRET.

Em seguida, usa ActiveDirectoryDefault no teu código de ligação.

Endpoints do Microsoft SQL suportados

O mssql-python controlador liga-se a todos os endpoints do Microsoft SQL:

Endpoint Authentication
SQL Server (on-premises ou numa VM) Autenticação SQL, autenticação do Windows
Base de Dados SQL do Azure Microsoft Entra ID (recomendado), autenticação SQL
Azure SQL Managed Instance Microsoft Entra ID (recomendado), autenticação SQL
Azure Synapse Analytics (pools dedicados) Microsoft Entra ID, autenticação SQL
Banco de dados SQL no Fabric Microsoft Entra ID
Armazém de Dados Fabric Microsoft Entra ID
Endpoint de análise SQL (Lakehouse) Microsoft Entra ID
Endpoint de análise SQL (base de dados espelhada) Microsoft Entra ID

Consulte a autenticação Microsoft Entra para conhecer os sete modos de autenticação e o ciclo de vida do suporte para a matriz de compatibilidade completa.

Configuração de pipeline CI

GitHub Actions

Mantém o tempo de execução em Python numa única variável para poderes rever e atualizar num só local. Use 3.x para pipelines de validação rápidos, ou substitua-o por uma versão exata aprovada pela organização para pipelines de release.

name: Test with SQL Server
on: [push, pull_request]

env:
  PYTHON_VERSION: "3.x"

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      sqlserver:
        image: mcr.microsoft.com/mssql/server:2022-latest
        env:
          ACCEPT_EULA: Y
          MSSQL_SA_PASSWORD: YourStr0ngP@ssword
        ports:
          - 1433:1433
        options: >-
          --health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P YourStr0ngP@ssword -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: ${{ env.PYTHON_VERSION }}
          check-latest: true

      - name: Install dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y libltdl7 libkrb5-3 libgssapi-krb5-2
          pip install -r requirements.txt

      - name: Run tests
        env:
          SQL_SERVER: localhost,1433
          SQL_UID: sa
          SQL_PWD: YourStr0ngP@ssword
        run: pytest

Para pipelines partilhados, substitua a palavra-passe marcante inline por um segredo encriptado, fixe a imagem do serviço SQL Server num resumo e mantenha a versão Python numa variável gerida pela organização ou num fluxo de trabalho reutilizável.

Azure Pipelines

Use um recurso de contentor para executar o SQL Server como serviço juntamente com o seu trabalho de teste:

trigger:
  - main

variables:
  python.version: "3.x"

resources:
  containers:
    - container: sqlserver
      image: mcr.microsoft.com/mssql/server:2022-latest
      env:
        ACCEPT_EULA: Y
        MSSQL_SA_PASSWORD: YourStr0ngP@ssword
      ports:
        - 1433:1433

pool:
  vmImage: ubuntu-latest

services:
  sqlserver: sqlserver

steps:
  - task: UsePythonVersion@0
    inputs:
      versionSpec: "$(python.version)"

  - script: |
      sudo apt-get update
      sudo apt-get install -y libltdl7 libkrb5-3 libgssapi-krb5-2
      pip install -r requirements.txt
    displayName: Install dependencies

  - script: pytest
    displayName: Run tests
    env:
      SQL_SERVER: localhost,1433
      SQL_UID: sa
      SQL_PWD: YourStr0ngP@ssword

Tal como com o GitHub Actions, substitua a palavra-passe de marcador de posição inline por uma variável secreta antes de utilizar este padrão fora de um pipeline de demonstração descartável.

Segurança e segredos

Não codifique palavras-passe de base de dados ou strings de ligação no código-fonte ou no Dockerfiles. Use variáveis de ambiente e gestão de segredos em vez disso.

Variáveis ambientais para o desenvolvimento local

Armazene credenciais em variáveis de ambiente ou num .env ficheiro excluído do controlo de versão:

# .env (add to .gitignore)
SQL_SERVER=localhost,1433
SQL_UID=sa
SQL_PWD=YourStr0ngP@ssword
import os
import mssql_python

conn = mssql_python.connect(
    server=os.environ["SQL_SERVER"],
    uid=os.environ["SQL_UID"],
    pwd=os.environ["SQL_PWD"],
    encrypt="yes",
    trust_server_certificate="yes"
)

Para o Docker Compose, consulte um .env ficheiro:

services:
  app:
    build: .
    env_file: .env

Atenção

Nunca submeta ficheiros .env ao controlo de código-fonte. Adiciona .env ao teu .gitignore ficheiro.

segredos do CI/CD

Nos pipelines de CI, utilize-se o armazenamento secreto da plataforma em vez de variáveis de ambiente em texto simples:

Higiene da cadeia de abastecimento de contentores

Use estas práticas para ambientes partilhados de programadores e CI:

  • Mantenha as referências de imagem num único local, como num Dockerfile ARG, na compilação de um devcontainer ou numa variável de pipeline.
  • Associe imagens de contentor partilhadas a identificadores imutáveis em vez de etiquetas variáveis.
  • Revise e atualize os resumos fixados através de um processo de atualização aprovado, como Dependabot, Renovate ou um fluxo de trabalho interno de promoção de imagens.
  • Adicione um ficheiro de bloqueio de dependências, como uv.lock, ou use ficheiros de requisitos com hashes para instalações Python reprodutíveis.
  • Prefira imagens de base aprovadas pela organização e espelhos internos do registo quando a sua plataforma os fornece.

Produção: autenticação sem palavra-passe

Para cargas de trabalho de produção para o SQL do Azure, use a autenticação Microsoft Entra com identidade gerida. Esta abordagem elimina completamente as palavras-passe:

conn = mssql_python.connect(
    server="<server>.database.windows.net",
    database="<database>",
    authentication="ActiveDirectoryMSI",
    encrypt="yes"
)

Para aplicações que precisam de armazenar segredos, como palavras-passe de autenticação SQL, use o Azure Key Vault e recupere-as em tempo de execução.

Gestão de dependências com uv

O UV é um instalador rápido de pacotes Python que funciona bem em compilações de CI e contentores:

ARG PYTHON_BASE=python:3-slim
FROM ${PYTHON_BASE}

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

# Install uv. In shared builds, pin the source image to an approved digest.
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv

WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN uv sync --frozen --no-dev

COPY . .
CMD ["uv", "run", "python", "app.py"]

Na Integração Contínua:

pip install uv
uv sync
uv run pytest

Resolução de problemas com os contentores comuns

Symptom Motivo Corrigir
ImportError: libltdl.so.7 Biblioteca de sistema em falta. Instalar libltdl7 (Debian) ou libltdl (Alpine).
ImportError: libkrb5.so.3 Biblioteca Kerberos em falta. Install libkrb5-3 (Debian) ou krb5-libs (Alpine/RHEL).
SSL: CERTIFICATE_VERIFY_FAILED Certificado auto-assinado no SQL Server local. Acrescenta trust_server_certificate="yes" à ligação. Não uses isto em produção.
Ligação recusada no porto 1433 Contentor do SQL Server não está pronto. Faça um exame de saúde ou espere que o serviço comece.
Login failed for user 'sa' A palavra-passe não cumpre os requisitos de complexidade. Use uma palavra-passe com maiúsculas, minúsculas, dígitos e caracteres especiais.
Cannot open database A base de dados ainda não existe. Crie ou restaure a base de dados antes de ligar.
Primeira ligação lenta no contentor Resolução DNS ou inicialização da cadeia de credenciais. Para SQL Server local, use localhost,1433 em vez de nome de host. Para SQL do Azure, pré-autenticar com az login.