23c2788fcf
-Aggiunte github actions per la compilazione dei container e l'esposizione
16 KiB
16 KiB
🎯 Esempi Pratici di Deployment Docker
Questa guida fornisce esempi pratici e scenari reali di deployment del Data-Coupler usando Docker.
📚 Indice degli Scenari
- Development Locale
- Production Single Server
- Staging Environment
- High Availability con Load Balancer
- Docker Swarm Cluster
- Kubernetes Deployment
Scenario 1: Development Locale
Caso d'uso: Sviluppatore vuole testare l'applicazione localmente
Setup Rapido
# Pull ultima versione dev
docker pull ghcr.io/alessiodalsi/data-coupler:dev-latest
# Run con hot-reload friendly settings
docker run -d \
--name data-coupler-dev \
-p 7550:7550 \
-v $(pwd)/test-data:/var/lib/Data_Coupler \
-e ASPNETCORE_ENVIRONMENT=Development \
-e Logging__LogLevel__Default=Debug \
ghcr.io/alessiodalsi/data-coupler:dev-latest
# Verifica logs
docker logs -f data-coupler-dev
# Accedi all'app
# http://localhost:7550
Con Docker Compose
# docker-compose.dev.yml
version: '3.8'
services:
data-coupler:
image: ghcr.io/alessiodalsi/data-coupler:dev-latest
ports:
- "7550:7550"
volumes:
- ./dev-data:/var/lib/Data_Coupler
environment:
- ASPNETCORE_ENVIRONMENT=Development
- Logging__LogLevel__Default=Debug
restart: unless-stopped
# Database di test (opzionale)
test-db:
image: mcr.microsoft.com/mssql/server:2022-latest
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=YourStrong@Passw0rd
ports:
- "1433:1433"
# Start
docker-compose -f docker-compose.dev.yml up -d
# Stop
docker-compose -f docker-compose.dev.yml down
Scenario 2: Production Single Server
Caso d'uso: Deploy production su singolo server Linux
Setup con Systemd Integration
1. Crea lo script di deployment
# /opt/data-coupler/deploy.sh
#!/bin/bash
set -e
# Pull ultima versione
docker pull ghcr.io/alessiodalsi/data-coupler:latest
# Stop e rimuovi container esistente
docker stop data-coupler 2>/dev/null || true
docker rm data-coupler 2>/dev/null || true
# Avvia nuovo container
docker run -d \
--name data-coupler \
--restart unless-stopped \
-p 7550:7550 \
-v /var/lib/data-coupler:/var/lib/Data_Coupler \
-e ASPNETCORE_ENVIRONMENT=Production \
--memory="2g" \
--cpus="2" \
ghcr.io/alessiodalsi/data-coupler:latest
echo "Deployment completato!"
docker ps --filter name=data-coupler
2. Crea servizio systemd
# /etc/systemd/system/data-coupler.service
[Unit]
Description=Data Coupler Service
Requires=docker.service
After=docker.service
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/data-coupler
ExecStart=/opt/data-coupler/deploy.sh
ExecStop=/usr/bin/docker stop data-coupler
StandardOutput=journal
[Install]
WantedBy=multi-user.target
3. Abilita e avvia
# Permissions
chmod +x /opt/data-coupler/deploy.sh
# Enable service
sudo systemctl daemon-reload
sudo systemctl enable data-coupler.service
# Start
sudo systemctl start data-coupler.service
# Status
sudo systemctl status data-coupler.service
# Logs
journalctl -u data-coupler.service -f
Setup Nginx Reverse Proxy
# /etc/nginx/sites-available/data-coupler
server {
listen 80;
server_name datacoupler.example.com;
# Redirect to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name datacoupler.example.com;
ssl_certificate /etc/letsencrypt/live/datacoupler.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/datacoupler.example.com/privkey.pem;
location / {
proxy_pass http://localhost:7550;
proxy_http_version 1.1;
# WebSocket support for Blazor
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
}
# Health check endpoint
location /health {
proxy_pass http://localhost:7550/health;
access_log off;
}
}
# Abilita configurazione
sudo ln -s /etc/nginx/sites-available/data-coupler /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
Scenario 3: Staging Environment
Caso d'uso: Ambiente staging per test pre-production
Docker Compose Completo
# docker-compose.staging.yml
version: '3.8'
services:
data-coupler:
image: ghcr.io/alessiodalsi/data-coupler:staging-latest
container_name: data-coupler-staging
networks:
- staging-network
ports:
- "7550:7550"
volumes:
- staging-data:/var/lib/Data_Coupler
- ./logs:/var/log/data-coupler
environment:
- ASPNETCORE_ENVIRONMENT=Staging
- Logging__LogLevel__Default=Information
- ConnectionStrings__DefaultConnection=Server=staging-db;Database=DataCoupler;
depends_on:
- staging-db
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7550/health"]
interval: 30s
timeout: 10s
retries: 3
deploy:
resources:
limits:
cpus: '1'
memory: 1G
staging-db:
image: mcr.microsoft.com/mssql/server:2022-latest
container_name: staging-db
networks:
- staging-network
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=${DB_PASSWORD}
volumes:
- staging-db-data:/var/opt/mssql
ports:
- "1433:1433"
restart: unless-stopped
# Monitoring (opzionale)
portainer:
image: portainer/portainer-ce:latest
container_name: portainer-staging
networks:
- staging-network
ports:
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer-data:/data
restart: unless-stopped
networks:
staging-network:
driver: bridge
volumes:
staging-data:
staging-db-data:
portainer-data:
Environment File
# .env.staging
DB_PASSWORD=YourStrongPassword123!
Deploy Script
#!/bin/bash
# deploy-staging.sh
# Load environment
export $(cat .env.staging | xargs)
# Pull latest images
docker-compose -f docker-compose.staging.yml pull
# Deploy
docker-compose -f docker-compose.staging.yml up -d
# Check health
sleep 10
curl http://localhost:7550/health
# Show logs
docker-compose -f docker-compose.staging.yml logs -f --tail=50
Scenario 4: High Availability
Caso d'uso: Setup HA con load balancer e multiple instances
Docker Compose con Scale
# docker-compose.ha.yml
version: '3.8'
services:
nginx-lb:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- data-coupler
networks:
- ha-network
restart: unless-stopped
data-coupler:
image: ghcr.io/alessiodalsi/data-coupler:latest
networks:
- ha-network
volumes:
- shared-data:/var/lib/Data_Coupler
environment:
- ASPNETCORE_ENVIRONMENT=Production
deploy:
replicas: 3
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
resources:
limits:
cpus: '1'
memory: 1G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7550/health"]
interval: 10s
timeout: 5s
retries: 3
networks:
ha-network:
driver: bridge
volumes:
shared-data:
driver: local
driver_opts:
type: nfs
o: addr=nfs-server.example.com,rw
device: ":/exports/data-coupler"
Nginx Load Balancer Config
# nginx.conf
events {
worker_connections 1024;
}
http {
upstream data-coupler-backend {
least_conn;
server data-coupler:7550 max_fails=3 fail_timeout=30s;
# Docker Compose scale gestisce automaticamente multiple instances
# Se necessario, aggiungi manualmente:
# server data-coupler-2:7550;
# server data-coupler-3:7550;
}
server {
listen 80;
location / {
proxy_pass http://data-coupler-backend;
# Sticky sessions per Blazor SignalR
ip_hash;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 300s;
}
location /health {
proxy_pass http://data-coupler-backend/health;
access_log off;
}
}
}
Scale Up/Down
# Scale to 5 instances
docker-compose -f docker-compose.ha.yml up -d --scale data-coupler=5
# Scale down to 2 instances
docker-compose -f docker-compose.ha.yml up -d --scale data-coupler=2
# Check instances
docker-compose -f docker-compose.ha.yml ps
Scenario 5: Docker Swarm
Caso d'uso: Cluster multi-node con orchestrazione
Initialize Swarm
# Manager node
docker swarm init --advertise-addr <MANAGER-IP>
# Worker nodes (run on each worker)
docker swarm join --token <TOKEN> <MANAGER-IP>:2377
# Verify cluster
docker node ls
Stack Deploy
# stack-data-coupler.yml
version: '3.8'
services:
data-coupler:
image: ghcr.io/alessiodalsi/data-coupler:latest
ports:
- target: 7550
published: 7550
mode: host
volumes:
- data-coupler-data:/var/lib/Data_Coupler
environment:
- ASPNETCORE_ENVIRONMENT=Production
networks:
- data-coupler-network
deploy:
mode: replicated
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
placement:
constraints:
- node.role == worker
resources:
limits:
cpus: '1'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:7550/health"]
interval: 30s
timeout: 10s
retries: 3
networks:
data-coupler-network:
driver: overlay
attachable: true
volumes:
data-coupler-data:
driver: local
Deploy and Management
# Deploy stack
docker stack deploy -c stack-data-coupler.yml datacoupler
# Check services
docker stack services datacoupler
# Check tasks
docker service ps datacoupler_data-coupler
# Scale service
docker service scale datacoupler_data-coupler=5
# Update image
docker service update --image ghcr.io/alessiodalsi/data-coupler:latest \
datacoupler_data-coupler
# View logs
docker service logs -f datacoupler_data-coupler
# Remove stack
docker stack rm datacoupler
Scenario 6: Kubernetes
Caso d'uso: Deploy su cluster Kubernetes
Namespace e ConfigMap
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: data-coupler
---
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: data-coupler-config
namespace: data-coupler
data:
ASPNETCORE_ENVIRONMENT: "Production"
ASPNETCORE_URLS: "http://+:7550"
Logging__LogLevel__Default: "Information"
Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: data-coupler
namespace: data-coupler
spec:
replicas: 3
selector:
matchLabels:
app: data-coupler
template:
metadata:
labels:
app: data-coupler
spec:
containers:
- name: data-coupler
image: ghcr.io/alessiodalsi/data-coupler:latest
ports:
- containerPort: 7550
envFrom:
- configMapRef:
name: data-coupler-config
volumeMounts:
- name: data-volume
mountPath: /var/lib/Data_Coupler
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
livenessProbe:
httpGet:
path: /health
port: 7550
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 7550
initialDelaySeconds: 10
periodSeconds: 5
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: data-coupler-pvc
Service
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: data-coupler-service
namespace: data-coupler
spec:
selector:
app: data-coupler
ports:
- protocol: TCP
port: 80
targetPort: 7550
type: LoadBalancer
Ingress
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: data-coupler-ingress
namespace: data-coupler
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- datacoupler.example.com
secretName: datacoupler-tls
rules:
- host: datacoupler.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: data-coupler-service
port:
number: 80
Persistent Volume
# pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-coupler-pvc
namespace: data-coupler
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
storageClassName: standard
Deploy su Kubernetes
# Apply all manifests
kubectl apply -f namespace.yaml
kubectl apply -f configmap.yaml
kubectl apply -f pvc.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
# Check status
kubectl get all -n data-coupler
# Check pods
kubectl get pods -n data-coupler
# View logs
kubectl logs -f deployment/data-coupler -n data-coupler
# Scale
kubectl scale deployment data-coupler --replicas=5 -n data-coupler
# Rolling update
kubectl set image deployment/data-coupler \
data-coupler=ghcr.io/alessiodalsi/data-coupler:latest \
-n data-coupler
# Check health
kubectl exec -it deployment/data-coupler -n data-coupler -- \
curl http://localhost:7550/health
🔧 Utility Scripts
Auto-Update Script
#!/bin/bash
# auto-update.sh - Aggiorna automaticamente all'ultima versione
# Colori
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
# Config
IMAGE="ghcr.io/alessiodalsi/data-coupler:latest"
CONTAINER_NAME="data-coupler"
echo "Checking for updates..."
# Pull latest
docker pull $IMAGE
# Get current image ID
CURRENT_ID=$(docker inspect --format='{{.Image}}' $CONTAINER_NAME 2>/dev/null)
LATEST_ID=$(docker inspect --format='{{.Id}}' $IMAGE)
if [ "$CURRENT_ID" == "$LATEST_ID" ]; then
echo -e "${GREEN}Already up to date!${NC}"
exit 0
fi
echo -e "${GREEN}New version available! Updating...${NC}"
# Backup current database (opzionale)
echo "Creating backup..."
docker exec $CONTAINER_NAME tar czf /tmp/backup.tar.gz /var/lib/Data_Coupler
docker cp $CONTAINER_NAME:/tmp/backup.tar.gz ./backup-$(date +%Y%m%d-%H%M%S).tar.gz
# Stop and remove old container
docker stop $CONTAINER_NAME
docker rm $CONTAINER_NAME
# Start new container
docker run -d \
--name $CONTAINER_NAME \
--restart unless-stopped \
-p 7550:7550 \
-v data-coupler-data:/var/lib/Data_Coupler \
$IMAGE
# Wait for health
for i in {1..30}; do
if curl -sf http://localhost:7550/health > /dev/null; then
echo -e "${GREEN}Update completed successfully!${NC}"
exit 0
fi
sleep 2
done
echo -e "${RED}Update completed but health check failed${NC}"
exit 1
Backup Script
#!/bin/bash
# backup.sh - Backup database e configurazioni
BACKUP_DIR="/backups/data-coupler"
CONTAINER_NAME="data-coupler"
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
mkdir -p $BACKUP_DIR
# Backup database
docker exec $CONTAINER_NAME tar czf - /var/lib/Data_Coupler \
> $BACKUP_DIR/backup-$TIMESTAMP.tar.gz
# Keep only last 7 days
find $BACKUP_DIR -name "backup-*.tar.gz" -mtime +7 -delete
echo "Backup completed: $BACKUP_DIR/backup-$TIMESTAMP.tar.gz"
Data Creazione: 16 Gennaio 2026
Versione: 1.0
Testato su: Docker 24.x, Docker Compose 2.x, Kubernetes 1.28+