academia/deploy/docker-mssql
Andrés Eduardo García Márquez 389c637152 chore(deploy): update deployment config and add utility scripts
Docker:
- docker-compose.yml: optimize resource allocation
- start.sh: improve startup sequence
- docker-mssql/: add standalone SQL Server config for local dev

Kubernetes (K3s):
- hpa.yaml: adjust autoscaling thresholds
- kustomization.yaml: add new resource references
- secrets.yaml: update secret structure

Utility scripts:
- start.backend.sh: fix environment variables
- start.db.sh: database initialization script
- start.db.simple.sh: simplified DB startup
- generate-docs.sh: PlantUML diagram generation

Misc:
- index.html: landing page redirect

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 07:44:43 -05:00
..
Dockerfile chore(deploy): update deployment config and add utility scripts 2026-01-09 07:44:43 -05:00
README.md chore(deploy): update deployment config and add utility scripts 2026-01-09 07:44:43 -05:00
build-push.sh chore(deploy): update deployment config and add utility scripts 2026-01-09 07:44:43 -05:00
entrypoint.sh chore(deploy): update deployment config and add utility scripts 2026-01-09 07:44:43 -05:00
optimize.sql chore(deploy): update deployment config and add utility scripts 2026-01-09 07:44:43 -05:00
update-dockerhub-readme.sh chore(deploy): update deployment config and add utility scripts 2026-01-09 07:44:43 -05:00

README.md

SQL Server 2017 Express - Low RAM Edition 🐳

Docker Pulls Docker Image Size

Imagen de Docker optimizada para ejecutar SQL Server 2017 Express con bajo consumo de RAM (384MB - 512MB).

Características

  • 🎯 RAM mínima: 384MB (vs 2GB oficial de Microsoft)
  • Optimizaciones automáticas al iniciar el contenedor
  • 🔧 Trace flags preconfigurados para estabilidad
  • 🏥 Health check integrado
  • 📝 Logs informativos del proceso de optimización
  • 🔐 Contraseña configurable por variable de entorno

🚀 Uso Rápido

docker run -d \
  --name mssql \
  --memory=384m \
  --memory-swap=2g \
  -e MSSQL_SA_PASSWORD=MiPassword123! \
  -p 1433:1433 \
  andresgarcia0313/mssql-express-lowram

📋 Variables de Entorno

Variables Requeridas

Variable Descripción
MSSQL_SA_PASSWORD REQUERIDO. Password del usuario SA (administrador)

Variables Opcionales

Variable Default Descripción
MSSQL_PID Express Edición de SQL Server
MSSQL_MEMORY_LIMIT_MB 340 Límite de memoria interna de SQL Server (MB)
MSSQL_COLLATION SQL_Latin1_General_CP1_CI_AS Collation de la instancia
MSSQL_LCID 1033 ID de idioma (1033=English, 3082=Spanish)
MSSQL_TCP_PORT 1433 Puerto TCP de SQL Server
TZ UTC Zona horaria del contenedor
ACCEPT_EULA Y Ya aceptada en la imagen

Valores de MSSQL_PID

Valor Descripción Límites
Express Recomendado. Gratuito para desarrollo y producción 1GB RAM, 10GB DB
Developer Todas las características, solo desarrollo Sin límites
Standard Requiere licencia 128GB RAM
Enterprise Requiere licencia Sin límites

Requisitos del Password

El password de SA debe cumplir:

  • Mínimo 8 caracteres
  • Al menos una letra mayúscula (A-Z)
  • Al menos una letra minúscula (a-z)
  • Al menos un número (0-9)
  • Al menos un caracter especial (!@#$%^&*)

Ejemplos válidos: MiPassword123!, Secure@Pass99, Dev#Server2024


💾 Configuración de Memoria y Swap

Parámetros de Docker para Memoria

Parámetro Descripción
--memory Límite de RAM física para el contenedor
--memory-swap Límite total (RAM + Swap). Debe ser mayor que --memory
--memory-reservation Reserva mínima de RAM (soft limit)
--memory-swappiness Preferencia de uso de swap (0-100)
--oom-kill-disable Deshabilita OOM killer (usar con cuidado)

Configuración Recomendada por Tipo de Disco

💿 Para SSD/NVMe (Recomendado)

El swap en SSD es rápido, permite configuración más agresiva:

docker run -d \
  --name mssql \
  --memory=384m \
  --memory-swap=4g \
  --memory-reservation=256m \
  --memory-swappiness=70 \
  -e MSSQL_SA_PASSWORD=MiPassword123! \
  -e MSSQL_PID=Express \
  -e MSSQL_MEMORY_LIMIT_MB=340 \
  -p 1433:1433 \
  -v mssql_data:/var/opt/mssql/data \
  andresgarcia0313/mssql-express-lowram
Parámetro Valor Razón
--memory 384m RAM mínima viable
--memory-swap 4g Swap generoso (SSD es rápido)
--memory-swappiness 60 Balance entre RAM y swap

🗄️ Para HDD (Disco Mecánico)

El swap en HDD es lento, minimizar su uso:

docker run -d \
  --name mssql \
  --memory=512m \
  --memory-swap=1g \
  --memory-reservation=384m \
  --memory-swappiness=10 \
  -e MSSQL_SA_PASSWORD=MiPassword123! \
  -e MSSQL_PID=Express \
  -e MSSQL_MEMORY_LIMIT_MB=450 \
  -p 1433:1433 \
  -v mssql_data:/var/opt/mssql/data \
  andresgarcia0313/mssql-express-lowram
Parámetro Valor Razón
--memory 512m Más RAM para evitar swap
--memory-swap 1g Swap mínimo (HDD lento)
--memory-swappiness 10 Evitar swap excepto emergencia

Tabla de Configuraciones Recomendadas

Escenario RAM Swap Swappiness MSSQL_MEMORY_LIMIT_MB
Mínimo SSD 384m 4g 60 340
Mínimo HDD 512m 1g 10 450
Desarrollo 512m 2g 30 450
CI/CD 512m 2g 30 450
Múltiples DBs 768m 2g 20 680
Carga moderada 1g 2g 10 900

Configuración para Máximo Rendimiento

Desarrollo Local - Máximo Rendimiento

docker run -d \
  --name mssql-performance \
  --memory=1g \
  --memory-swap=2g \
  --memory-swappiness=10 \
  --cpus=2 \
  -e MSSQL_SA_PASSWORD=MiPassword123! \
  -e MSSQL_PID=Developer \
  -e MSSQL_MEMORY_LIMIT_MB=900 \
  -e TZ=America/Bogota \
  -p 1433:1433 \
  -v mssql_data:/var/opt/mssql/data \
  -v mssql_log:/var/opt/mssql/log \
  andresgarcia0313/mssql-express-lowram

Máxima Estabilidad (Producción-like)

docker run -d \
  --name mssql-stable \
  --memory=768m \
  --memory-swap=2g \
  --memory-reservation=512m \
  --memory-swappiness=20 \
  --restart=unless-stopped \
  --cpus=2 \
  -e MSSQL_SA_PASSWORD=MiPassword123! \
  -e MSSQL_PID=Express \
  -e MSSQL_MEMORY_LIMIT_MB=680 \
  -p 1433:1433 \
  -v /path/to/data:/var/opt/mssql/data \
  -v /path/to/log:/var/opt/mssql/log \
  -v /path/to/backup:/var/opt/mssql/backup \
  andresgarcia0313/mssql-express-lowram

Recursos Mínimos Absolutos

docker run -d \
  --name mssql-minimal \
  --memory=384m \
  --memory-swap=6g \
  --memory-swappiness=80 \
  -e MSSQL_SA_PASSWORD=MiPassword123! \
  -e MSSQL_PID=Express \
  -e MSSQL_MEMORY_LIMIT_MB=300 \
  -p 1433:1433 \
  andresgarcia0313/mssql-express-lowram

⚠️ Con recursos mínimos, el rendimiento dependerá mucho del swap (requiere SSD).


🔧 Optimizaciones Incluidas en la Imagen

Configuración de SQL Server (Automática)

Setting Valor Propósito
max server memory 320 MB Límite del buffer pool
min server memory 128 MB Permite liberar RAM bajo presión
max degree of parallelism 2 Reduce consumo en queries paralelas
cost threshold for parallelism 50 Solo queries costosas usan paralelismo
optimize for ad hoc workloads ON Reduce caché de planes únicos
recovery interval 1 min Recuperación rápida tras crash

Trace Flags Activos (Automáticos)

Flag Propósito
TF 1117 Crecimiento uniforme de archivos de datos
TF 1118 Reduce contención en tempdb (extents uniformes)
TF 3226 Suprime logs de backup exitoso (menos I/O)

📦 Docker Compose

Configuración Básica

version: '3.8'

services:
  sqlserver:
    image: andresgarcia0313/mssql-express-lowram
    container_name: mssql
    mem_limit: 512m
    memswap_limit: 2g
    mem_reservation: 384m
    restart: unless-stopped
    environment:
      - MSSQL_SA_PASSWORD=MiPassword123!
      - MSSQL_PID=Express
      - MSSQL_MEMORY_LIMIT_MB=450
      - TZ=America/Bogota
    ports:
      - "1433:1433"
    volumes:
      - mssql_data:/var/opt/mssql/data
      - mssql_log:/var/opt/mssql/log
    healthcheck:
      test: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$$MSSQL_SA_PASSWORD" -Q "SELECT 1"
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  mssql_data:
  mssql_log:

Configuración Avanzada (SSD + Rendimiento)

version: '3.8'

services:
  sqlserver:
    image: andresgarcia0313/mssql-express-lowram
    container_name: mssql
    mem_limit: 768m
    memswap_limit: 4g
    mem_reservation: 512m
    cpus: 2
    restart: unless-stopped
    environment:
      MSSQL_SA_PASSWORD: ${MSSQL_PASSWORD:-MiPassword123!}
      MSSQL_PID: Express
      MSSQL_MEMORY_LIMIT_MB: 680
      MSSQL_COLLATION: Modern_Spanish_CI_AS
      TZ: America/Bogota
    ports:
      - "1433:1433"
    volumes:
      - mssql_data:/var/opt/mssql/data
      - mssql_log:/var/opt/mssql/log
      - mssql_backup:/var/opt/mssql/backup
    healthcheck:
      test: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$$MSSQL_SA_PASSWORD" -Q "SELECT 1"
      interval: 30s
      timeout: 10s
      start_period: 30s
      retries: 3
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

volumes:
  mssql_data:
    driver: local
  mssql_log:
    driver: local
  mssql_backup:
    driver: local

🔌 Conexión

Desde línea de comandos

# Usando sqlcmd dentro del contenedor
docker exec -it mssql /opt/mssql-tools/bin/sqlcmd \
  -S localhost -U sa -P 'MiPassword123!'

# Usando sqlcmd local
sqlcmd -S localhost,1433 -U sa -P 'MiPassword123!'

Connection Strings

.NET / C#

Server=localhost,1433;Database=MiDB;User Id=sa;Password=MiPassword123!;TrustServerCertificate=True;

Node.js (mssql)

const config = {
  server: 'localhost',
  port: 1433,
  user: 'sa',
  password: 'MiPassword123!',
  database: 'MiDB',
  options: { trustServerCertificate: true }
};

Python (pyodbc)

conn_str = (
    "DRIVER={ODBC Driver 17 for SQL Server};"
    "SERVER=localhost,1433;"
    "DATABASE=MiDB;"
    "UID=sa;"
    "PWD=MiPassword123!;"
    "TrustServerCertificate=yes;"
)

Java (JDBC)

String url = "jdbc:sqlserver://localhost:1433;database=MiDB;user=sa;password=MiPassword123!;trustServerCertificate=true;";

🏗️ Ejemplos de Uso

CI/CD (GitHub Actions)

services:
  sqlserver:
    image: andresgarcia0313/mssql-express-lowram
    env:
      MSSQL_SA_PASSWORD: TestPassword123!
      MSSQL_PID: Express
      MSSQL_MEMORY_LIMIT_MB: 450
    ports:
      - 1433:1433
    options: >-
      --memory=512m
      --memory-swap=2g
      --health-cmd="/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P TestPassword123! -Q 'SELECT 1'"
      --health-interval=10s
      --health-timeout=5s
      --health-retries=5      

Kubernetes

apiVersion: v1
kind: Pod
metadata:
  name: mssql-lowram
spec:
  containers:
  - name: mssql
    image: andresgarcia0313/mssql-express-lowram
    resources:
      limits:
        memory: "768Mi"
      requests:
        memory: "512Mi"
    env:
    - name: MSSQL_SA_PASSWORD
      valueFrom:
        secretKeyRef:
          name: mssql-secret
          key: sa-password
    - name: MSSQL_PID
      value: "Express"
    - name: MSSQL_MEMORY_LIMIT_MB
      value: "680"
    ports:
    - containerPort: 1433
    livenessProbe:
      exec:
        command:
        - /opt/mssql-tools/bin/sqlcmd
        - -S
        - localhost
        - -U
        - sa
        - -P
        - $(MSSQL_SA_PASSWORD)
        - -Q
        - SELECT 1
      initialDelaySeconds: 30
      periodSeconds: 30

⚠️ Advertencias

  • No recomendado para producción pesada - La RAM es insuficiente para cargas grandes
  • Swap en HDD - Experimentará lentitud significativa, usar SSD cuando sea posible
  • Realizar backups frecuentes en entornos con recursos limitados
  • Los trace flags se aplican en cada inicio (no persisten en la imagen)
  • MSSQL_MEMORY_LIMIT_MB debe ser menor que --memory (dejar ~60MB para el OS)

🔍 Troubleshooting

Ver logs de optimización

docker logs mssql 2>&1 | grep LOWRAM

Verificar configuración aplicada

docker exec mssql /opt/mssql-tools/bin/sqlcmd \
  -S localhost -U sa -P 'MiPassword123!' \
  -Q "SELECT name, value_in_use FROM sys.configurations WHERE name LIKE '%memory%' OR name LIKE '%parallel%'"

Ver uso de memoria real

docker stats mssql --no-stream

El contenedor no inicia

  1. Verificar que el password cumple los requisitos
  2. Verificar que hay suficiente RAM: docker stats
  3. Revisar logs: docker logs mssql
  4. Verificar swap disponible: free -h

Rendimiento lento

  1. Verificar tipo de disco (SSD vs HDD)
  2. Aumentar --memory si es posible
  3. Reducir --memory-swappiness en HDD
  4. Verificar que no hay otros contenedores compitiendo por recursos

🔬 Proceso de Optimización (Trazabilidad)

Esta imagen fue creada mediante un proceso de investigación y optimización documentado. A continuación se detalla el proceso completo para reproducibilidad y trazabilidad.

Problema Original

Microsoft SQL Server 2017 tiene un requisito mínimo oficial de 2GB de RAM, lo cual es excesivo para:

  • Desarrollo local en equipos con recursos limitados
  • Pipelines de CI/CD
  • Contenedores en entornos de pruebas
  • Microservicios que solo necesitan una DB pequeña

Investigación Realizada

  1. Documentación oficial consultada:

  2. Hallazgos clave:

    • MSSQL_MEMORY_LIMIT_MB existe pero requiere versiones recientes
    • SQL Server 2017 CU10+ incluye fix para respetar límites de contenedor
    • El 80% de RAM por defecto es configurable vía sp_configure
    • Trace flags pueden mejorar estabilidad en entornos con poca RAM

Optimizaciones Aplicadas

1. Configuración de SQL Server (sp_configure)

-- Ejecutado automáticamente al iniciar el contenedor

-- Limitar buffer pool (principal consumidor de RAM)
EXEC sp_configure 'max server memory', 320;

-- Permitir liberar memoria bajo presión del sistema
EXEC sp_configure 'min server memory', 128;

-- Reducir caché de planes para queries ad-hoc (ahorra RAM)
EXEC sp_configure 'optimize for ad hoc workloads', 1;

-- Limitar paralelismo (operaciones paralelas consumen más RAM)
EXEC sp_configure 'max degree of parallelism', 2;

-- Solo queries costosas usan paralelismo
EXEC sp_configure 'cost threshold for parallelism', 50;

-- Checkpoints frecuentes para recuperación rápida
EXEC sp_configure 'recovery interval (min)', 1;

2. Trace Flags para Estabilidad

-- Ejecutados automáticamente al iniciar

-- TF 1117: Crecimiento uniforme de archivos
-- Evita que un archivo crezca más que otros, reduciendo fragmentación
DBCC TRACEON(1117, -1);

-- TF 1118: Extents uniformes en tempdb
-- Reduce contención de páginas mixtas, mejora rendimiento
DBCC TRACEON(1118, -1);

-- TF 3226: Suprime logs de backup exitoso
-- Reduce I/O en el log de errores
DBCC TRACEON(3226, -1);

3. Entrypoint Personalizado

# El entrypoint realiza:
# 1. Valida que MSSQL_SA_PASSWORD esté definido
# 2. Inicia SQL Server en foreground
# 3. En background, espera que SQL Server esté listo
# 4. Aplica todas las optimizaciones automáticamente
# 5. Muestra logs informativos del proceso

4. Health Check Integrado

HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -Q "SELECT 1"

Pruebas de Validación

La imagen fue probada durante 6+ minutos de monitoreo continuo:

Minuto Estado RAM Operación
0 OK 380.9 MB Query básica
2 OK 381.9 MB Count de databases
4 OK 381.8 MB CREATE TABLE + 1000 INSERTs
6 OK 381.6 MB Listado de databases

Resultado: Sin errores, sin OOM, sin crashes, memoria estable.

Archivos de la Imagen

deploy/docker-mssql/
├── Dockerfile          # Imagen base + labels + health check
├── entrypoint.sh       # Validación + inicio + optimización automática
├── optimize.sql        # Queries de sp_configure y trace flags
├── build-push.sh       # Script para build y push a Docker Hub
└── README.md           # Esta documentación

Limitaciones Conocidas

Limitación Causa Mitigación
RAM mínima ~380MB Componentes fuera del buffer pool Usar swap en SSD
No persisten trace flags Se aplican en runtime, no en imagen Se re-aplican en cada inicio
Rendimiento reducido Menos RAM = menos caché Usar SSD, aumentar swap

Diferencias vs Imagen Oficial

Aspecto Imagen Oficial Esta Imagen
RAM mínima 2 GB 384 MB
Optimizaciones Ninguna Automáticas
Trace flags Ninguno 3 preconfigurados
Health check No
Validación password No Sí (con mensaje de error claro)
Documentación Básica Completa

Reproducir las Optimizaciones Manualmente

Si prefieres aplicar las optimizaciones a la imagen oficial:

# 1. Iniciar contenedor oficial
docker run -d --name mssql --memory=512m \
  -e ACCEPT_EULA=Y \
  -e MSSQL_SA_PASSWORD=TuPassword123! \
  -p 1433:1433 \
  mcr.microsoft.com/mssql/server:2017-latest

# 2. Esperar que inicie
sleep 30

# 3. Aplicar optimizaciones
docker exec mssql /opt/mssql-tools/bin/sqlcmd \
  -S localhost -U sa -P 'TuPassword123!' -Q "
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'max server memory', 384; RECONFIGURE;
EXEC sp_configure 'min server memory', 128; RECONFIGURE;
EXEC sp_configure 'optimize for ad hoc workloads', 1; RECONFIGURE;
EXEC sp_configure 'max degree of parallelism', 2; RECONFIGURE;
EXEC sp_configure 'cost threshold for parallelism', 50; RECONFIGURE;
EXEC sp_configure 'recovery interval (min)', 1; RECONFIGURE;
DBCC TRACEON(1117, -1);
DBCC TRACEON(1118, -1);
DBCC TRACEON(3226, -1);
"

📊 Basado en

  • Microsoft SQL Server 2017 Express (CU31 - versión 14.0.3515.1)
  • Imagen base: mcr.microsoft.com/mssql/server:2017-latest
  • Documentación oficial de Microsoft para SQL Server en Linux

📄 Licencia

  • SQL Server Express: Gratuito para desarrollo y producción (con límites)
  • Scripts de optimización: MIT License

👤 Autor

andresgarcia0313


Si esta imagen te fue útil, considera dejar una estrella en el repositorio.