Desarrollo de contenedores y local con mssql-python

Esta guía cubre la configuración del entorno para desarrolladores de Python que trabajan con el mssql-python controlador en Windows, Linux, macOS, contenedores Docker, devcontainers y pipelines CI.

Prerequisites

  • Python 3.10 o posterior.
  • Docker Desktop (para desarrollo basado en contenedores).
  • Un host compatible con x64 (máquina virtual Intel, AMD o x64) para contenedores Linux de SQL Server. Los contenedores de SQL Server Linux no soportan hosts ARM64.

La utilidad go-sqlcmd puede crear un contenedor SQL Server en un solo comando. Controla automáticamente la extracción de imágenes de Docker, la generación de contraseñas, la asignación de puertos y el contexto de conexión:

sqlcmd create mssql --accept-eula

Para crear un contenedor con una base de datos de ejemplo ya adjunta:

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

Después de la creación, sqlcmd almacena el contexto de conexión para que pueda consultar inmediatamente:

sqlcmd query "SELECT @@VERSION"

Crea un inicio de sesión de aplicación una vez y luego úsalo en tu 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>;"

Sustituye <database>, <app-login>, y <password> por valores de tu entorno.

Conéctese desde Python usando los datos de conexión que sqlcmd imprimió durante su creación. Use sqlcmd config view para recuperarlos más adelante:

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()

Cuando haya terminado, detenga o elimine el contenedor:

sqlcmd stop
sqlcmd delete

Tip

Ejecute sqlcmd create mssql --user-database <database> para crear un contenedor con una base de datos de usuario vacía lista para el desarrollo.

SQL Server local desde VS Code

La extensión SQL Server para VS Code (ms-mssql.mssql) puede crear contenedores locales de SQL Server directamente desde el editor:

  1. Abra la vista SQL Server en la barra de actividades.
  2. Seleccione Agregar conexión>Crear SQL Server local (o use la paleta de comandos: MS SQL: Crear SQL Server local).
  3. Elija la versión SQL Server y acepte el CLUF.
  4. La extensión extrae la imagen del contenedor, genera una contraseña y agrega automáticamente un perfil de conexión.

Una vez que el contenedor está en ejecución, puedes navegar por bases de datos, hacer consultas y gestionar objetos directamente en VS Code antes de cambiar a código Python.

SQL Server local con Docker

Si prefiere administrar contenedores directamente, la imagen de contenedor de SQL Server oficial funciona con dos variables de entorno:

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 unos segundos y luego conecta desde 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

Se usa MSSQL_SA_PASSWORD para contenedores de SQL Server. La variable anterior SA_PASSWORD está en desuso. La contraseña debe cumplir SQL Server requisitos de complejidad: al menos 8 caracteres, con mayúsculas, minúsculas, dígitos y caracteres especiales.

Para cargar la base de datos de ejemplo de AdventureWorks en el contenedor:

# 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'"

Tip

El sqlcmd create mssql --using enfoque de la sección anterior gestiona la descarga y restauración automáticamente.

Dockerfile para aplicaciones Python

Mantén la referencia de la imagen base de Python en un solo lugar para que las compilaciones locales, devcontainers y pipelines de CI no se desvíen. Para la experimentación local, una etiqueta amplia y soportada como python:3-slim funciona bien. Para devcontainers compartidos, CI y producción, sustituye esa etiqueta por una imagen aprobada y fijada en resumen de la lista de permisos de tu organización.

Crea un archivo Docker mínimo para una aplicación Python que se conecte a 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"]

Su requirements.txt:

mssql-python>=1.11.0

Compilación y ejecución:

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

En entornos compartidos, pasa una referencia a una imagen base inmutable aprobada con --build-arg PYTHON_BASE=python:3-slim@sha256:<approved-digest>.

Note

Usa host.docker.internal en Docker Desktop (Windows y macOS) para acceder a un SQL Server en el equipo host. En Linux, use --network host en su lugar.

Alpine Linux

Alpine usa musl en lugar de glibc. Instale los paquetes necesarios:

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

Configuración del devcontainer

Reutiliza el mismo archivo Dockerfile con el que compila tu aplicación. Este enfoque mantiene el devcontainer alineado con tu imagen de ejecución y evita dispersar los pines de la versión de Python entre varios archivos.

Crea un .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 SQL Server como servicio en el devcontainer, use 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 (Versión de 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 espacios de trabajo compartidos, fija la imagen del servicio de SQL Server a un resumen aprobado en lugar de depender de una etiqueta flotante. Carga MSSQL_SA_PASSWORD desde un archivo local .env o desde un almacén de secretos de la plataforma, en lugar de incorporarlo al control de código fuente.

Conéctate al servicio SQL Server por tu nombre:

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

Dependencias específicas de la plataforma

El mssql-python controlador agrupa sus componentes nativos. No necesitas instalar un gestor externo de drivers ODBC. Sin embargo, el controlador requiere un pequeño conjunto de librerías de sistema en Linux y macOS.

Plataforma Paquetes necesarios Comando Install
Windows None Incluido en el 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
Alpino libltdl, krb5-libs apk add libltdl krb5-libs
macOS OpenSSL (a través de Homebrew) brew install openssl

Para macOS, si encuentras errores SSL, configura las banderas del enlazador:

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

Para las instrucciones completas de instalación, consulta Instalar mssql-python.

Autenticación para el desarrollo

Desarrollo local con Azure SQL

Úsalo ActiveDirectoryDefault para autenticación sin contraseña. Esta opción se encadena automáticamente a través de CLI de Azure, Visual Studio, variables de entorno e identidad gestionada:

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

Asegúrate de iniciar sesión usando CLI de Azure:

az login

Desarrollo local frente a SQL Server

Usa autenticación SQL con una instancia local.

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

Desarrollo de contenedores con Azure SQL

Para contenedores que se ejecutan en Azure (App Service, Container Apps, AKS), usa la identidad gestionada.

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

Para contenedores que se ejecutan localmente y necesitan conectarse a Azure SQL, asegúrate de que el contenedor tenga un código fuente de credenciales que ActiveDirectoryDefault pueda usar. Las opciones más fiables son:

  • Instala CLI de Azure en el contenedor y inicia sesión allí. Monta ~/.azure desde el host solo si la imagen del contenedor ya incluye CLI de Azure y tienes intención de reutilizar esa caché de credenciales.
  • Proporcionar credenciales principales de servicio mediante variables de entorno como AZURE_CLIENT_ID, AZURE_TENANT_ID, y AZURE_CLIENT_SECRET.

Luego, utiliza ActiveDirectoryDefault en tu código de conexión.

Endpoints SQL de Microsoft compatibles

El mssql-python controlador se conecta a todos los endpoints de Microsoft SQL:

Endpoint Autenticación
SQL Server (local o en una máquina virtual) Autenticación SQL, autenticación de Windows
Azure SQL Database Microsoft Entra ID (recomendado), autenticación SQL
Instancia Gestionada de Azure SQL Microsoft Entra ID (recomendado), autenticación SQL
Azure Synapse Analytics (pools dedicados) Microsoft Entra ID, autenticación SQL
Base de datos SQL en Fabric Microsoft Entra ID
Almacenamiento de datos de tejido Microsoft Entra ID
Endpoint de analítica SQL (Lakehouse) Microsoft Entra ID
Endpoint de analítica SQL (base de datos espejada) Microsoft Entra ID

Consulte Autenticación Microsoft Entra para los siete modos de autenticación y Ciclo de vida de Soporte para la matriz completa de compatibilidad.

Configuración de canalización de CI

Acciones de GitHub

Mantén el runtime de Python en una sola variable para que puedas revisarlo y actualizarlo en un solo lugar. Úsalo 3.x para canalizaciones de validación rápidas, o retitúelo por una versión exacta aprobada por la organización para canalizaciones de lanzamiento.

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 canalizaciones compartidas, sustituye la contraseña provisional en línea por un secreto cifrado, fija la imagen del servicio SQL Server en un resumen y mantén la versión de Python en una variable gestionada por la organización o en una entrada de flujo de trabajo reutilizable.

Azure Pipelines

Utiliza un recurso contenedor para ejecutar SQL Server como servicio junto con tu trabajo de prueba:

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

Como con Acciones de GitHub, sustituye la contraseña provisional en línea por una variable secreta antes de usar este patrón fuera de una pipeline de demostración desechable.

Seguridad y secretos

No codifiques contraseñas de base de datos ni cadenas de conexión en código fuente ni en Dockerfiles. Utiliza en su lugar variables de entorno y gestión de secretos.

Variables ambientales para el desarrollo local

Almacena las credenciales en variables de entorno o en un archivo .env que esté excluido del control de versiones:

# .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 Docker Compose, consulta un archivo .env:

services:
  app:
    build: .
    env_file: .env

Caution

No suba nunca archivos .env al control de versiones. Agregue .env al archivo .gitignore.

Secretos CI/CD

En las canalizaciones de CI, utiliza el almacenamiento secreto de la plataforma en lugar de variables de entorno en texto plano:

Higiene de la cadena de suministro de contenedores

Utiliza estas prácticas para entornos de desarrollo compartidos y CI:

  • Mantén referencias de imagen en un solo lugar, como un Docker ARG, una compilación de devcontainer o una variable de pipeline.
  • Vincula las imágenes de contenedor compartidas a dígests inmutables en lugar de a etiquetas variables.
  • Revisa y actualiza los digestes fijados mediante un proceso de actualización aprobado como Dependabot, Renovate o un flujo de trabajo interno de promoción de imágenes.
  • Compromete un archivo de bloqueo de dependencia como uv.lock, o utiliza archivos de requisitos hashados para instalaciones reproducibles en Python.
  • Prefiere imágenes base aprobadas por la organización y réplicas internas del registro cuando la plataforma las ofrezca.

Producción: autenticación sin contraseña

Para cargas de trabajo de producción contra Azure SQL, utiliza autenticación Microsoft Entra con identidad gestionada. Este enfoque elimina por completo las contraseñas:

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

Para aplicaciones que necesitan almacenar secretos como contraseñas de autenticación SQL, usa Azure Key Vault y recupéralos en tiempo de ejecución.

Gestión de dependencias con uv

UV es un instalador rápido de paquetes Python que funciona bien en compilaciones de CI y contenedores:

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

En CI:

pip install uv
uv sync
uv run pytest

Solución de problemas comunes de contenedor

Síntoma Causa Corregir
ImportError: libltdl.so.7 Falta una biblioteca del sistema. Instala libltdl7 (Debian) o libltdl (Alpine).
ImportError: libkrb5.so.3 Biblioteca de Kerberos perdida. Instala libkrb5-3 (Debian) o krb5-libs (Alpine/RHEL).
SSL: CERTIFICATE_VERIFY_FAILED Certificado autofirmado en SQL Server local. Añade trust_server_certificate="yes" a la conexión. No uses esto en producción.
Conexión rechazada en el puerto 1433 SQL Server contenedor no está listo. Agregue una comprobación de estado o espere a que se inicie el servicio.
Login failed for user 'sa' La contraseña no cumple con los requisitos de complejidad. Usa una contraseña con mayúsculas, minúsculas, dígitos y caracteres especiales.
Cannot open database La base de datos aún no existe. Crea o restaura la base de datos antes de conectarte.
Primera conexión lenta en el contenedor Resolución de DNS o inicio de la cadena de credenciales. Para SQL Server local, usa localhost,1433 en lugar de nombre de host. Para Azure SQL, autentíquese previamente con az login.