Dev Container para montar tu entorno local de SQL Server y notebooks de Jupyter

Estos días, para una sesión que estuve preparando 📚, estoy viendo cómo juntar el mundo del Platform Engineering con el mundo de los datos, intentando hacer su vida un poquito más sencilla también ☺️
Si bien es cierto que mis conocimientos en este área son más bien básicos estoy intentando proporcionar un repositorio base donde tengan todo lo que necesitan para empezar a trabajar con el tipo de base de datos que les toque ese día/semana (cualquier feedback es siempre bienvenido 🤗).

Este repo consta de varias partes: por un lado una configuración de Dev Container, que me prepara el entorno con un servidor de base de datos en un contenedor para poder jugar y luego, por otro lado, un par de notebooks que permita interactuar con esa base de datos de forma sencilla y poder documentar las queries que necesitamos. Como esto último me ha costado un poco hacerlo funcionar, en este artículo te comparto los dos ejemplos que he preparado.

Configuración de Dev Container

Si tú también quieres probar estos notebooks, dentro del repositorio donde tengo los notebooks me he creado una configuración de Dev Container como la siguiente:

{
    "name": "SQL Server Dev Environment",
	"dockerComposeFile": "compose.yml",
	"service": "app",
	"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",    
    "forwardPorts": [
        1433,
        8888
    ],   
    "customizations": {
        "vscode": {
            "settings": {
                "mssql.connections": [
					{
						"server": "db,1433",
						"database": "",
						"authenticationType": "SqlLogin",
						"user": "sa",
						"password": "Yourpassword123",
						"savePassword": true,
						"profileName": "mssql-container",
						"trustServerCertificate": true
					}
				]
            },
            "extensions": [
                "ms-azuretools.vscode-docker",
                "ms-mssql.mssql",
                "ms-python.python",
                "ms-toolsai.jupyter",
                "HashiCorp.terraform",
                "ms-azuretools.vscode-azureterraform",
                "fnando.linter"
            ]
        }
    },
    "postCreateCommand": "pre-commit install",
    "remoteUser": "vscode",
    "features": {
        "ghcr.io/devcontainers-contrib/features/pre-commit:2": {},
        "ghcr.io/devcontainers/features/python:1": {
            "installTools": true,
            "installJupyterlab": true,
            "version": "latest"
        }
    }
}

Esta a su vez usa una configuración de Docker Compose para poder levantar no solo el workspace donde voy a tener mis notebooks y otras cosas, sino que también un servidor de base de datos SQL Server contenerizado:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ../..:/workspaces:cached
    command: sleep infinity
    ports:
      - 8888:8888
    depends_on:
      - db
  db:    
    image:  mcr.microsoft.com/azure-sql-edge
    restart: unless-stopped
    environment:
      SA_PASSWORD: Yourpassword123
      ACCEPT_EULA: Y

Para este workspace estoy usando un Dockerfile que además de tener .NET 9, también copia un archivo que me permitirá instalar diferentes herramientas para poder trabajar con esta base de datos:

FROM mcr.microsoft.com/devcontainers/dotnet:9.0
# Install SQL Tools: SQLPackage and sqlcmd
COPY installSQLtools.sh installSQLtools.sh
RUN bash ./installSQLtools.sh \
     && apt-get clean -y && rm -rf /var/lib/apt/lists/* /tmp/library-scripts

Y ya por último, el archivo installSQLtools.sh:

#!/bin/bash
echo "Installing mssql-tools"
curl -sSL https://packages.microsoft.com/keys/microsoft.asc | (OUT=$(apt-key add - 2>&1) || echo $OUT)
DISTRO=$(lsb_release -is | tr '[:upper:]' '[:lower:]')
CODENAME=$(lsb_release -cs)
echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-${DISTRO}-${CODENAME}-prod ${CODENAME} main" > /etc/apt/sources.list.d/microsoft.list
apt-get update
ACCEPT_EULA=Y apt-get -y install unixodbc-dev msodbcsql17 libunwind8 mssql-tools
echo "Installing sqlpackage"
curl -sSL -o sqlpackage.zip "https://aka.ms/sqlpackage-linux"
mkdir /opt/sqlpackage
unzip sqlpackage.zip -d /opt/sqlpackage 
rm sqlpackage.zip
chmod a+x /opt/sqlpackage/sqlpackage
# Install Microsoft ODBC Driver for SQL Server
if ! [[ "9 10 11 12" == *"$(grep VERSION_ID /etc/os-release | cut -d '"' -f 2 | cut -d '.' -f 1)"* ]];
then
    echo "Debian $(grep VERSION_ID /etc/os-release | cut -d '"' -f 2 | cut -d '.' -f 1) is not currently supported.";
    exit;
fi
# Download the package to configure the Microsoft repo
curl -sSL -O https://packages.microsoft.com/config/debian/$(grep VERSION_ID /etc/os-release | cut -d '"' -f 2 | cut -d '.' -f 1)/packages-microsoft-prod.deb
# Install the package
sudo dpkg -i packages-microsoft-prod.deb
# Delete the file
rm packages-microsoft-prod.deb
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18
# optional: for bcp and sqlcmd
sudo ACCEPT_EULA=Y apt-get install -y mssql-tools18
echo 'export PATH="$PATH:/opt/mssql-tools18/bin"' >> ~/.bashrc
source ~/.bashrc
# optional: for unixODBC development headers
sudo apt-get install -y unixodbc-dev
# optional: kerberos library for debian-slim distributions
sudo apt-get install -y libgssapi-krb5-2

Si no conoces Dev Containers puedes echarle un vistazo a este vídeo de mi canal:

y ahora centrémonos en esos notebooks 📓

Notebooks de Jupyter usando pyodbc y pandas

El notebook más sencillo, sobre todo vienes de este mundo, es usando directamente las librerías de Python. Como ya tengo instalado el driver de ODBC como parte de mi Dev Container todo es mucho más sencillo 😇 Solo tengo una primera celda donde instalo los módulos de Python que necesito para poder trabajar con este notebook (y así me garantizo saber qué es lo que me hace falta):

pip install pyodbc pandas

Y lo siguiente hago es crear una conexión con la base de datos:

import pyodbc
connectionString = f'DRIVER={{ODBC Driver 18 for SQL Server}};SERVER=db;DATABASE=direwolvesdb;UID=sa;PWD=Yourpassword123;Encrypt=yes;TrustServerCertificate=yes;'
connection = pyodbc.connect(connectionString)
cursor = connection.cursor()

Una vez que tengo esto ya puedo hacer las queries que quiera:

import pandas as pd
SQL_QUERY = '''
SELECT * FROM Direwolves;
'''
cursor.execute(SQL_QUERY)
rows = cursor.fetchall()

pandas_df = pd.DataFrame.from_records(rows, columns=[column[0] for column in cursor.description])
print(pandas_df)

El resultado sería algo como esto:

Este es el método más sencillo, pero quería encontrar otra forma para aquellos DBA que quizás no están acostumbrados a utilizar Python como parte de su día a día. Para ello tenemos los magic command.

Notebooks usando magic commands

Para el segundo caso lo que he hecho ha sido primeramente instalar estos dos módulos:

pip install --upgrade ipython-sql pyodbc

Una vez instalados, ya puedo cargar el comando mágico sql, configurarlo y crear la conexión con la base de datos:

%load_ext sql
%config SqlMagic.style = '_DEPRECATED_DEFAULT'
%sql mssql+pyodbc://sa:Yourpassword123@db/direwolvesdb?driver=ODBC+Driver+18+for+SQL+Server&TrustServerCertificate=yes

Y a partir de este momento ya puedo utilizar celdas como la siguiente para poder interactuar con mi base de datos SQL Server sin necesidad de saber Python 😃:

%sql SELECT * FROM Direwolves

En este caso el resultado sería algo como esto:

¡Saludos 👋🏻!

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.