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
This commit is contained in:
Andrés Eduardo García Márquez 2026-01-09 07:44:43 -05:00
parent df8a8e74f8
commit 22c6f37c4d
16 changed files with 4232 additions and 26 deletions

View File

@ -0,0 +1,50 @@
# =============================================================================
# SQL Server 2017 Express - Low RAM Edition
# =============================================================================
# Imagen optimizada para ejecutar SQL Server con bajo consumo de memoria
#
# Autor: andresgarcia0313
# Repositorio: https://hub.docker.com/r/andresgarcia0313/mssql-express-lowram
# GitHub: https://github.com/andresgarcia0313
#
# USO RAPIDO:
# docker run -d --name mssql --memory=384m \
# -e MSSQL_SA_PASSWORD=TuPassword123! \
# -p 1433:1433 andresgarcia0313/mssql-express-lowram
#
# VARIABLES DE ENTORNO:
# MSSQL_SA_PASSWORD (REQUERIDO) - Password del usuario SA
# MSSQL_PID (opcional) - Edición: Express, Developer, Standard
# MSSQL_MEMORY_LIMIT_MB (opcional) - Límite de memoria en MB (default: 340)
#
# RAM RECOMENDADA: 384MB - 512MB (mínimo viable para desarrollo)
# =============================================================================
FROM mcr.microsoft.com/mssql/server:2017-latest
LABEL maintainer="andresgarcia0313 <andresgarcia0313@gmail.com>"
LABEL org.opencontainers.image.title="SQL Server 2017 Express - Low RAM"
LABEL org.opencontainers.image.description="SQL Server 2017 Express optimizado para bajo consumo de RAM (384MB-512MB). Ideal para desarrollo local y CI/CD."
LABEL org.opencontainers.image.version="1.0"
LABEL org.opencontainers.image.vendor="andresgarcia0313"
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.source="https://github.com/andresgarcia0313"
# Variables de entorno por defecto (MSSQL_SA_PASSWORD debe ser proporcionada)
ENV ACCEPT_EULA=Y \
MSSQL_PID=Express \
MSSQL_MEMORY_LIMIT_MB=340
# Copiar scripts de optimización
COPY --chmod=755 entrypoint.sh /opt/mssql/bin/entrypoint.sh
COPY --chmod=644 optimize.sql /opt/mssql/bin/optimize.sql
# Puerto SQL Server
EXPOSE 1433
# Health check
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" || exit 1
# Entrypoint personalizado que aplica optimizaciones al iniciar
ENTRYPOINT ["/opt/mssql/bin/entrypoint.sh"]

View File

@ -0,0 +1,671 @@
# SQL Server 2017 Express - Low RAM Edition 🐳
[![Docker Pulls](https://img.shields.io/docker/pulls/andresgarcia0313/mssql-express-lowram)](https://hub.docker.com/r/andresgarcia0313/mssql-express-lowram)
[![Docker Image Size](https://img.shields.io/docker/image-size/andresgarcia0313/mssql-express-lowram/latest)](https://hub.docker.com/r/andresgarcia0313/mssql-express-lowram)
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
```bash
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:
```bash
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:
```bash
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
```bash
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)
```bash
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
```bash
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
```yaml
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)
```yaml
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
```bash
# 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#**
```csharp
Server=localhost,1433;Database=MiDB;User Id=sa;Password=MiPassword123!;TrustServerCertificate=True;
```
**Node.js (mssql)**
```javascript
const config = {
server: 'localhost',
port: 1433,
user: 'sa',
password: 'MiPassword123!',
database: 'MiDB',
options: { trustServerCertificate: true }
};
```
**Python (pyodbc)**
```python
conn_str = (
"DRIVER={ODBC Driver 17 for SQL Server};"
"SERVER=localhost,1433;"
"DATABASE=MiDB;"
"UID=sa;"
"PWD=MiPassword123!;"
"TrustServerCertificate=yes;"
)
```
**Java (JDBC)**
```java
String url = "jdbc:sqlserver://localhost:1433;database=MiDB;user=sa;password=MiPassword123!;trustServerCertificate=true;";
```
---
## 🏗️ Ejemplos de Uso
### CI/CD (GitHub Actions)
```yaml
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
```yaml
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
```bash
docker logs mssql 2>&1 | grep LOWRAM
```
### Verificar configuración aplicada
```bash
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
```bash
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:**
- [Configure SQL Server Docker Containers](https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-docker-container-configure)
- [SQL Server Linux Performance Best Practices](https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-performance-best-practices)
- [KB4347055 - Fix OOM in Docker containers](https://support.microsoft.com/en-us/topic/kb4347055)
- [mssql-conf Configuration Tool](https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-configure-mssql-conf)
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`)
```sql
-- 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
```sql
-- 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
```bash
# 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
```dockerfile
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 | Sí |
| 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:
```bash
# 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**
- GitHub: [@andresgarcia0313](https://github.com/andresgarcia0313)
- Docker Hub: [andresgarcia0313](https://hub.docker.com/u/andresgarcia0313)
---
⭐ Si esta imagen te fue útil, considera dejar una estrella en el repositorio.

View File

@ -0,0 +1,55 @@
#!/bin/bash
# =============================================================================
# Build y Push de imagen SQL Server Low RAM a Docker Hub
# =============================================================================
set -e
IMAGE_NAME="andresgarcia0313/mssql-express-lowram"
VERSION="1.0"
cd "$(dirname "$0")"
echo "=== Building image: $IMAGE_NAME:$VERSION ==="
docker build -t "$IMAGE_NAME:$VERSION" -t "$IMAGE_NAME:latest" .
echo ""
echo "=== Testing image locally ==="
docker rm -f mssql-test 2>/dev/null || true
docker run -d \
--name mssql-test \
--memory="384m" \
-e "MSSQL_SA_PASSWORD=TestPass123!" \
-p 1434:1433 \
"$IMAGE_NAME:latest"
echo "Esperando 30 segundos para que SQL Server inicie..."
sleep 30
if docker exec mssql-test /opt/mssql-tools/bin/sqlcmd \
-S localhost -U sa -P 'TestPass123!' \
-Q "SELECT 'TEST OK' AS Status" 2>/dev/null | grep -q "TEST OK"; then
echo "✓ Test passed!"
docker rm -f mssql-test
else
echo "✗ Test failed!"
docker logs mssql-test
docker rm -f mssql-test
exit 1
fi
echo ""
echo "=== Push to Docker Hub ==="
echo "Ejecuta: docker login"
echo "Luego: docker push $IMAGE_NAME:$VERSION"
echo " docker push $IMAGE_NAME:latest"
echo ""
echo "O ejecuta este script con 'push' como argumento:"
echo " $0 push"
if [ "$1" == "push" ]; then
docker push "$IMAGE_NAME:$VERSION"
docker push "$IMAGE_NAME:latest"
echo "✓ Push completado!"
fi

View File

@ -0,0 +1,77 @@
#!/bin/bash
# =============================================================================
# SQL Server 2017 Express - Low RAM Edition
# Entrypoint que inicia SQL Server y aplica optimizaciones automáticamente
# =============================================================================
set -e
# Colores para output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[LOWRAM]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[LOWRAM]${NC} $1"; }
log_error() { echo -e "${RED}[LOWRAM]${NC} $1"; }
# Validar que se proporcionó contraseña
if [ -z "$MSSQL_SA_PASSWORD" ]; then
log_error "ERROR: Variable MSSQL_SA_PASSWORD es requerida"
log_error ""
log_error "Uso correcto:"
log_error " docker run -e MSSQL_SA_PASSWORD=TuPassword123! ..."
log_error ""
log_error "Requisitos del password:"
log_error " - Mínimo 8 caracteres"
log_error " - Al menos una mayúscula"
log_error " - Al menos una minúscula"
log_error " - Al menos un número"
log_error " - Al menos un caracter especial (!@#\$%^&*)"
exit 1
fi
# Función para aplicar optimizaciones
apply_optimizations() {
log_info "Esperando que SQL Server esté listo..."
for i in {1..60}; do
if /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$MSSQL_SA_PASSWORD" \
-Q "SELECT 1" &>/dev/null; then
log_info "SQL Server listo - Aplicando optimizaciones..."
if /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$MSSQL_SA_PASSWORD" \
-i /opt/mssql/bin/optimize.sql 2>/dev/null; then
log_info "============================================="
log_info "SQL Server Low RAM Edition - LISTO"
log_info "============================================="
log_info "Conexión: localhost,1433"
log_info "Usuario: sa"
log_info "RAM: ~380MB (optimizado)"
log_info "============================================="
else
log_warn "Optimizaciones parcialmente aplicadas"
fi
return 0
fi
sleep 2
done
log_warn "Timeout esperando SQL Server - optimizaciones no aplicadas"
return 1
}
# Mostrar configuración
log_info "============================================="
log_info "SQL Server 2017 Express - Low RAM Edition"
log_info "============================================="
log_info "Edición: ${MSSQL_PID:-Express}"
log_info "Memoria límite: ${MSSQL_MEMORY_LIMIT_MB:-340} MB"
log_info "============================================="
# Aplicar optimizaciones en background después de que SQL Server inicie
apply_optimizations &
# Iniciar SQL Server (foreground)
exec /opt/mssql/bin/sqlservr

View File

@ -0,0 +1,57 @@
-- =============================================================================
-- SQL Server 2017 Express - Optimizaciones para Bajo Consumo de RAM
-- =============================================================================
-- Aplicar automáticamente al iniciar el contenedor
-- RAM objetivo: 384MB - 512MB
-- =============================================================================
-- Habilitar opciones avanzadas
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- MAX SERVER MEMORY: Limitar buffer pool (ajustar según contenedor)
-- Para 384MB container: usar 280-320MB
-- Para 512MB container: usar 380-420MB
EXEC sp_configure 'max server memory', 320;
RECONFIGURE;
-- MIN SERVER MEMORY: Permitir liberar memoria bajo presión
EXEC sp_configure 'min server memory', 128;
RECONFIGURE;
-- OPTIMIZE FOR AD HOC WORKLOADS
-- Reduce memoria del plan cache para queries únicos
-- Cachea stub pequeño en lugar de plan completo
EXEC sp_configure 'optimize for ad hoc workloads', 1;
RECONFIGURE;
-- MAX DEGREE OF PARALLELISM (MAXDOP)
-- Limitar a 2 para reducir consumo en operaciones paralelas
EXEC sp_configure 'max degree of parallelism', 2;
RECONFIGURE;
-- COST THRESHOLD FOR PARALLELISM
-- Subir umbral: solo queries costosas usan paralelismo
EXEC sp_configure 'cost threshold for parallelism', 50;
RECONFIGURE;
-- RECOVERY INTERVAL
-- Checkpoints más frecuentes = recuperación más rápida tras crash
EXEC sp_configure 'recovery interval (min)', 1;
RECONFIGURE;
-- =============================================================================
-- TRACE FLAGS PARA ESTABILIDAD
-- =============================================================================
-- TF 3226: Suprime mensajes de backup exitosos en el log (reduce I/O)
DBCC TRACEON(3226, -1);
-- TF 1118: Reduce contención en tempdb (extents uniformes)
DBCC TRACEON(1118, -1);
-- TF 1117: Crecimiento uniforme de archivos de datos
DBCC TRACEON(1117, -1);
PRINT '[LOWRAM] Todas las optimizaciones aplicadas correctamente';
GO

View File

@ -0,0 +1,49 @@
#!/bin/bash
# =============================================================================
# Actualizar README en Docker Hub Overview
# =============================================================================
# Uso: ./update-dockerhub-readme.sh <username> <password>
# =============================================================================
set -e
DOCKER_USER="${1:-andresgarcia0313}"
DOCKER_PASS="$2"
REPO_NAME="mssql-express-lowram"
README_FILE="$(dirname "$0")/README.md"
if [ -z "$DOCKER_PASS" ]; then
echo "Uso: $0 <username> <password>"
echo " o: $0 <username> (te pedirá el password)"
read -s -p "Docker Hub Password: " DOCKER_PASS
echo ""
fi
echo "=== Obteniendo token de Docker Hub ==="
TOKEN=$(curl -s -X POST "https://hub.docker.com/v2/users/login/" \
-H "Content-Type: application/json" \
-d "{\"username\":\"$DOCKER_USER\",\"password\":\"$DOCKER_PASS\"}" | jq -r '.token')
if [ -z "$TOKEN" ] || [ "$TOKEN" == "null" ]; then
echo "Error: No se pudo obtener token. Verifica credenciales."
exit 1
fi
echo "=== Token obtenido correctamente ==="
echo "=== Actualizando README en Docker Hub ==="
README_CONTENT=$(cat "$README_FILE" | jq -Rs .)
RESPONSE=$(curl -s -X PATCH "https://hub.docker.com/v2/repositories/$DOCKER_USER/$REPO_NAME/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"full_description\":$README_CONTENT}")
if echo "$RESPONSE" | jq -e '.full_description' > /dev/null 2>&1; then
echo "✅ README actualizado exitosamente en Docker Hub"
echo " https://hub.docker.com/r/$DOCKER_USER/$REPO_NAME"
else
echo "❌ Error al actualizar:"
echo "$RESPONSE" | jq .
exit 1
fi

View File

@ -4,33 +4,26 @@
services:
db:
image: mcr.microsoft.com/mssql/server:2022-latest
image: andresgarcia0313/mssql-express-lowram:latest
container_name: student-db
env_file:
- ../../.env
environment:
- ACCEPT_EULA=Y
- MSSQL_SA_PASSWORD=${DB_PASSWORD}
- MSSQL_MEMORY_LIMIT_MB=${DB_MEMORY_LIMIT_MB:-512}
- MSSQL_AGENT_ENABLED=false
- MSSQL_SA_PASSWORD=${DB_PASSWORD:-Asde71.4Asde71.4}
- MSSQL_PID=Express
- MSSQL_MEMORY_LIMIT_MB=340
ports:
- "${DB_PORT:-1433}:1433"
volumes:
- sqlserver-data:/var/opt/mssql:delegated
deploy:
resources:
limits:
cpus: "1"
memory: ${DB_MEMORY_LIMIT:-1280M}
reservations:
cpus: "0.5"
memory: 1024M
- sqlserver-data:/var/opt/mssql/data:delegated
mem_limit: 384m
memswap_limit: 4g
mem_reservation: 256m
healthcheck:
test: /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "$${MSSQL_SA_PASSWORD}" -Q "SELECT 1" -C || exit 1
interval: 15s
timeout: 5s
retries: 10
test: /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$${MSSQL_SA_PASSWORD}" -Q "SELECT 1" || exit 1
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
networks:
- student-network

View File

@ -39,7 +39,7 @@ docker compose up -d
echo -e "\n${YELLOW}► Esperando servicios...${NC}"
echo -n " SQL Server: "
timeout 60 bash -c 'until docker compose exec -T db /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "${DB_PASSWORD:-Your_Str0ng_P@ssword!}" -Q "SELECT 1" -C &>/dev/null; do sleep 2; done' && echo -e "${GREEN}${NC}" || echo -e "${RED}${NC}"
timeout 60 bash -c 'until docker compose exec -T db /opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P "${DB_PASSWORD:-Asde71.4Asde71.4}" -Q "SELECT 1" -C &>/dev/null; do sleep 2; done' && echo -e "${GREEN}${NC}" || echo -e "${RED}${NC}"
echo -n " API .NET: "
timeout 60 bash -c 'until curl -sf http://localhost:5000/health &>/dev/null; do sleep 2; done' && echo -e "${GREEN}${NC}" || echo -e "${RED}${NC}"

View File

@ -10,7 +10,7 @@ spec:
apiVersion: apps/v1
kind: Deployment
name: student-api
minReplicas: 2
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
@ -50,7 +50,7 @@ spec:
apiVersion: apps/v1
kind: Deployment
name: student-frontend
minReplicas: 2
minReplicas: 1
maxReplicas: 4
metrics:
- type: Resource

View File

@ -11,6 +11,7 @@ resources:
- api.yaml
- frontend.yaml
- ingress.yaml
- networkpolicy.yaml
labels:
- pairs:

View File

@ -5,7 +5,5 @@ metadata:
namespace: academia
type: Opaque
stringData:
# IMPORTANTE: Cambiar en producción
# Generar con: openssl rand -base64 32
db-password: "YourStr0ngP4ssword2026"
db-connection-string: "Server=sqlserver;Database=StudentEnrollment;User Id=sa;Password=YourStr0ngP4ssword2026;TrustServerCertificate=True"
db-password: "Asde71.4Asde71.4"
db-connection-string: "Server=sqlserver;Database=StudentEnrollment;User Id=sa;Password=Asde71.4Asde71.4;TrustServerCertificate=True"

1554
generate-docs.sh Executable file

File diff suppressed because it is too large Load Diff

1482
index.html Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
#!/bin/bash
cd src/backend && dotnet run --project Host
dotnet run --project src/backend/Host

195
start.db.sh Executable file
View File

@ -0,0 +1,195 @@
#!/bin/bash
# =============================================================================
# SQL Server 2017 Express - Configuración Optimizada para Bajo Consumo de RAM
# =============================================================================
# Uso: ./start.db.sh [start|stop|restart|status|optimize|logs]
# =============================================================================
set -e
CONTAINER_NAME="mssql2017"
SA_PASSWORD="Asde71.4Asde71.4"
DATA_DIR="/home/andres/mssql/data"
LOG_DIR="/home/andres/mssql/log"
# Colores
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
wait_for_sql() {
log_info "Esperando que SQL Server inicie..."
for i in {1..30}; do
if docker exec $CONTAINER_NAME /opt/mssql-tools/bin/sqlcmd \
-S localhost -U sa -P "$SA_PASSWORD" \
-Q "SELECT 1" &>/dev/null; then
log_info "SQL Server listo"
return 0
fi
sleep 2
done
log_error "SQL Server no respondió en 60 segundos"
return 1
}
apply_optimizations() {
log_info "Aplicando optimizaciones de rendimiento y estabilidad..."
docker exec $CONTAINER_NAME /opt/mssql-tools/bin/sqlcmd \
-S localhost -U sa -P "$SA_PASSWORD" -Q "
-- =============================================
-- OPTIMIZACIONES PARA BAJO CONSUMO + ESTABILIDAD
-- =============================================
-- Habilitar opciones avanzadas
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
-- MAX SERVER MEMORY: Limitar buffer pool
EXEC sp_configure 'max server memory', 384;
RECONFIGURE;
-- MIN SERVER MEMORY: Permitir liberar bajo presión
EXEC sp_configure 'min server memory', 128;
RECONFIGURE;
-- OPTIMIZE FOR AD HOC: Reduce cache de planes únicos
EXEC sp_configure 'optimize for ad hoc workloads', 1;
RECONFIGURE;
-- MAXDOP: Limitar paralelismo (reduce RAM en operaciones paralelas)
EXEC sp_configure 'max degree of parallelism', 2;
RECONFIGURE;
-- COST THRESHOLD: Solo queries costosas usan paralelismo
EXEC sp_configure 'cost threshold for parallelism', 50;
RECONFIGURE;
-- RECOVERY INTERVAL: Checkpoints frecuentes = recuperación rápida
EXEC sp_configure 'recovery interval (min)', 1;
RECONFIGURE;
-- TRACE FLAGS para estabilidad
DBCC TRACEON(3226, -1); -- Suprime logs de backup exitoso
DBCC TRACEON(1118, -1); -- Reduce contención tempdb
DBCC TRACEON(1117, -1); -- Crecimiento uniforme de archivos
PRINT 'Optimizaciones aplicadas correctamente';
" 2>/dev/null
log_info "Optimizaciones aplicadas"
}
start_container() {
if docker ps -q -f name=$CONTAINER_NAME | grep -q .; then
log_warn "El contenedor ya está corriendo"
return 0
fi
# Eliminar contenedor existente si está detenido
docker rm -f $CONTAINER_NAME 2>/dev/null || true
# Crear directorios si no existen
mkdir -p "$DATA_DIR" "$LOG_DIR"
log_info "Iniciando SQL Server 2017 Express (512MB RAM)..."
docker run -d \
--name $CONTAINER_NAME \
--memory="384m" \
--memory-swap="4g" \
--memory-reservation="384m" \
--restart=unless-stopped \
-e "ACCEPT_EULA=Y" \
-e "MSSQL_SA_PASSWORD=$SA_PASSWORD" \
-e "MSSQL_PID=Express" \
-e "MSSQL_MEMORY_LIMIT_MB=340" \
-v "$DATA_DIR:/var/opt/mssql/data" \
-v "$LOG_DIR:/var/opt/mssql/log" \
-p 1433:1433 \
mcr.microsoft.com/mssql/server:2017-latest
wait_for_sql
apply_optimizations
log_info "SQL Server iniciado y optimizado"
show_status
}
stop_container() {
log_info "Deteniendo SQL Server..."
docker stop $CONTAINER_NAME 2>/dev/null || true
log_info "SQL Server detenido"
}
show_status() {
echo ""
echo "=== Estado del Contenedor ==="
docker ps -a --filter "name=$CONTAINER_NAME" \
--format "table {{.Status}}\t{{.Ports}}"
if docker ps -q -f name=$CONTAINER_NAME | grep -q .; then
echo ""
echo "=== Consumo de Recursos ==="
docker stats $CONTAINER_NAME --no-stream \
--format "table {{.MemUsage}}\t{{.MemPerc}}\t{{.CPUPerc}}"
echo ""
echo "=== Configuración SQL Server ==="
docker exec $CONTAINER_NAME /opt/mssql-tools/bin/sqlcmd \
-S localhost -U sa -P "$SA_PASSWORD" -Q "
SET NOCOUNT ON;
SELECT
CAST(name AS VARCHAR(35)) AS Setting,
CAST(value_in_use AS VARCHAR(10)) AS Value
FROM sys.configurations
WHERE name IN (
'max server memory (MB)',
'min server memory (MB)',
'max degree of parallelism',
'optimize for ad hoc workloads'
)
ORDER BY name;
" 2>/dev/null
fi
}
show_logs() {
docker logs $CONTAINER_NAME --tail 50 -f
}
# =============================================================================
# MAIN
# =============================================================================
case "${1:-start}" in
start)
start_container
;;
stop)
stop_container
;;
restart)
stop_container
sleep 2
start_container
;;
status)
show_status
;;
optimize)
wait_for_sql && apply_optimizations
;;
logs)
show_logs
;;
*)
echo "Uso: $0 {start|stop|restart|status|optimize|logs}"
exit 1
;;
esac

24
start.db.simple.sh Normal file
View File

@ -0,0 +1,24 @@
docker rm -f mssql2017 2>/dev/null
docker run -d \
--name mssql2017 \
--memory="512m" \
--memory-swap="4g" \
--memory-reservation="384m" \
-e "ACCEPT_EULA=Y" \
-e "MSSQL_SA_PASSWORD=Asde71.4Asde71.4" \
-e "MSSQL_PID=Express" \
-e "MSSQL_MEMORY_LIMIT_MB=512" \
-v /home/andres/mssql/data:/var/opt/mssql/data \
-v /home/andres/mssql/log:/var/opt/mssql/log \
-p 1433:1433 \
mcr.microsoft.com/mssql/server:2017-latest
sleep 20
docker exec mssql2017 /opt/mssql-tools/bin/sqlcmd -S localhost -U sa \
-P 'Asde71.4Asde71.4' -Q "
EXEC sp_configure 'show advanced options', 1; RECONFIGURE;
EXEC sp_configure 'max server memory', 512; RECONFIGURE;
"