MariaDB in Docker: Deploy e Best Practices

MariaDB rappresenta una delle soluzioni database più affidabili e performanti nel panorama open source. Quando combinato con Docker, offre agli sviluppatori e ai team DevOps un ambiente di sviluppo e produzione estremamente flessibile e scalabile. In questa guida completa, esploreremo come deployare MariaDB utilizzando Docker, implementando le migliori pratiche per sicurezza, performance e gestione dei dati.

Introduzione a MariaDB e Docker

MariaDB è un fork di MySQL sviluppato dalla comunità open source, nato dalla necessità di mantenere un database management system completamente libero e compatibile con MySQL. Docker, d'altra parte, ha rivoluzionato il modo in cui deployamo e gestiamo le applicazioni, fornendo containerizzazione leggera e portabilità cross-platform.

L'utilizzo di MariaDB in container Docker offre numerosi vantaggi:

  • Isolamento: Ogni istanza MariaDB funziona in un ambiente isolato
  • Portabilità: Il database può essere spostato facilmente tra ambienti diversi
  • Scalabilità: Possibilità di creare rapidamente nuove istanze
  • Gestione delle versioni: Controllo preciso sulla versione di MariaDB utilizzata
  • Backup e restore semplificati: Gestione dei dati tramite volumi Docker

Prerequisiti e Setup Iniziale

Prima di iniziare con il deploy di MariaDB in Docker, assicuriamoci di avere tutti i prerequisiti necessari:

Requisiti di Sistema

  • Docker Engine 20.10+ installato e configurato
  • Docker Compose 2.0+ (opzionale ma raccomandato)
  • Almeno 2GB di RAM disponibili
  • Spazio disco sufficiente per i dati del database

Verifica dell'Installazione Docker

Verifichiamo che Docker sia correttamente installato e funzionante:

docker --version
docker run hello-world

Questi comandi dovrebbero restituire la versione di Docker installata e confermare che il sistema è operativo.

Deploy Base di MariaDB con Docker

Primo Container MariaDB

Iniziamo con un deploy base di MariaDB utilizzando il comando Docker run:

docker run --name mariadb-container \
  -e MYSQL_ROOT_PASSWORD=your_secure_password \
  -e MYSQL_DATABASE=myapp_db \
  -e MYSQL_USER=myapp_user \
  -e MYSQL_PASSWORD=user_password \
  -p 3306:3306 \
  -d mariadb:10.9

Analizziamo i parametri utilizzati:

  • --name mariadb-container: Assegna un nome specifico al container
  • -e MYSQL_ROOT_PASSWORD: Imposta la password per l'utente root
  • -e MYSQL_DATABASE: Crea automaticamente un database all'avvio
  • -e MYSQL_USER/MYSQL_PASSWORD: Crea un utente non-root con relativa password
  • -p 3306:3306: Mappa la porta del container sulla porta dell'host
  • -d: Esegue il container in background (detached mode)

Verifica del Container

Verifichiamo che il container sia attivo e funzionante:

docker ps
docker logs mariadb-container

Per connetterci al database dal container stesso:

docker exec -it mariadb-container mysql -u root -p

Gestione dei Dati con Volumi Docker

Persistenza dei Dati

Uno degli aspetti più critici quando si lavora con database in container è la persistenza dei dati. Per default, i dati di MariaDB vengono memorizzati all'interno del container e vengono persi quando il container viene rimosso. Per risolvere questo problema, utilizziamo i volumi Docker:

docker volume create mariadb_data

docker run --name mariadb-persistent \
  -e MYSQL_ROOT_PASSWORD=your_secure_password \
  -e MYSQL_DATABASE=myapp_db \
  -v mariadb_data:/var/lib/mysql \
  -p 3306:3306 \
  -d mariadb:10.9

Volumi Named vs Bind Mounts

Docker offre diverse opzioni per la gestione dei volumi:

Tipo Sintassi Pro Contro
Named Volume -v volume_name:/var/lib/mysql Gestito da Docker, backup semplificato Meno controllo sulla posizione
Bind Mount -v /host/path:/var/lib/mysql Controllo completo del percorso Dipendenza dal filesystem host

Utilizzo di Docker Compose per MariaDB

Docker Compose semplifica notevolmente la gestione di container complessi. Creiamo un file docker-compose.yml per il nostro setup MariaDB:

version: '3.8'

services:
  mariadb:
    image: mariadb:10.9
    container_name: mariadb-app
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    ports:
      - "3306:3306"
    volumes:
      - mariadb_data:/var/lib/mysql
      - ./config/mariadb.cnf:/etc/mysql/conf.d/custom.cnf:ro
      - ./init:/docker-entrypoint-initdb.d:ro
    networks:
      - app_network

volumes:
  mariadb_data:
    driver: local

networks:
  app_network:
    driver: bridge

File di Configurazione Ambiente

Creiamo un file .env per gestire le variabili di ambiente in modo sicuro:

MYSQL_ROOT_PASSWORD=your_very_secure_root_password
MYSQL_DATABASE=production_db
MYSQL_USER=app_user
MYSQL_PASSWORD=app_user_secure_password

Per avviare lo stack:

docker-compose up -d

Configurazione Avanzata di MariaDB

File di Configurazione Personalizzato

MariaDB può essere configurato tramite file di configurazione personalizzati. Creiamo un file config/mariadb.cnf:

[mysqld]
# Configurazioni di base
max_connections = 200
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2

# Ottimizzazioni per performance
query_cache_type = 1
query_cache_size = 128M
tmp_table_size = 64M
max_heap_table_size = 64M

# Configurazioni di sicurezza
bind-address = 0.0.0.0
skip-name-resolve

# Logging
log_error = /var/log/mysql/error.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

# Character set
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

Script di Inizializzazione

Possiamo automatizzare la creazione di tabelle e dati iniziali tramite script SQL nella directory init/:

-- init/01-schema.sql
CREATE TABLE IF NOT EXISTS users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_users_username ON users(username);
CREATE INDEX idx_users_email ON users(email);

Sicurezza e Best Practices

Gestione delle Password e Secrets

La sicurezza è fondamentale quando si gestiscono database in produzione. Ecco alcune best practices essenziali:

  • Mai hardcodare password: Utilizzare sempre variabili di ambiente o Docker secrets
  • Password complesse: Implementare policy di password robuste
  • Principio del least privilege: Creare utenti specifici con permessi minimi necessari
  • Network isolation: Utilizzare reti Docker personalizzate

Implementazione Docker Secrets

Per ambienti più sicuri, utilizziamo Docker Secrets con Docker Swarm:

version: '3.8'

services:
  mariadb:
    image: mariadb:10.9
    environment:
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
      MYSQL_DATABASE: production_db
    secrets:
      - mysql_root_password
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
    volumes:
      - mariadb_data:/var/lib/mysql
    networks:
      - backend

secrets:
  mysql_root_password:
    file: ./secrets/mysql_root_password.txt

volumes:
  mariadb_data:

networks:
  backend:
    driver: overlay

Configurazione Firewall e Networking

Limitiamo l'accesso al database attraverso configurazioni di rete appropriate:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # Rete interna non accessibile dall'esterno

Monitoraggio e Logging

Configurazione dei Log

Un sistema di logging efficace è cruciale per il debugging e il monitoraggio. Configuriamo Docker per gestire i log di MariaDB:

services:
  mariadb:
    image: mariadb:10.9
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    volumes:
      - ./logs:/var/log/mysql

Health Checks

Implementiamo health checks per monitorare lo stato del database:

services:
  mariadb:
    image: mariadb:10.9
    healthcheck:
      test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Backup e Restore Strategies

Backup Automatizzati

Implementiamo una strategia di backup utilizzando un container dedicato:

services:
  mariadb-backup:
    image: mariadb:10.9
    depends_on:
      - mariadb
    environment:
      MYSQL_HOST: mariadb
      MYSQL_USER: root
      MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD}
    volumes:
      - ./backups:/backups
      - ./scripts/backup.sh:/backup.sh:ro
    command: >
      sh -c "chmod +x /backup.sh && 
             echo '0 2 * * * /backup.sh' | crontab - && 
             crond -f"

Script di Backup

Creiamo uno script di backup completo:

#!/bin/bash
# scripts/backup.sh

BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
DATABASES=$(mysql -h${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_PASSWORD} -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)")

mkdir -p ${BACKUP_DIR}/${DATE}

for db in $DATABASES; do
    echo "Backing up database: $db"
    mysqldump -h${MYSQL_HOST} -u${MYSQL_USER} -p${MYSQL_PASSWORD} \
        --single-transaction \
        --routines \
        --triggers \
        --add-drop-database \
        --databases $db > ${BACKUP_DIR}/${DATE}/${db}.sql
done

# Compressione dei backup
cd ${BACKUP_DIR}
tar -czf ${DATE}.tar.gz ${DATE}/
rm -rf ${DATE}/

# Pulizia backup vecchi (mantieni ultimi 7 giorni)
find ${BACKUP_DIR} -name "*.tar.gz" -mtime +7 -delete

echo "Backup completed: ${DATE}.tar.gz"

Ottimizzazione delle Performance

Configurazione Memoria e CPU

Ottimizzi