# 🎯 Esempi Pratici di Deployment Docker Questa guida fornisce esempi pratici e scenari reali di deployment del Data-Coupler usando Docker. ## 📚 Indice degli Scenari 1. [Development Locale](#scenario-1-development-locale) 2. [Production Single Server](#scenario-2-production-single-server) 3. [Staging Environment](#scenario-3-staging-environment) 4. [High Availability con Load Balancer](#scenario-4-high-availability) 5. [Docker Swarm Cluster](#scenario-5-docker-swarm) 6. [Kubernetes Deployment](#scenario-6-kubernetes) --- ## Scenario 1: Development Locale **Caso d'uso**: Sviluppatore vuole testare l'applicazione localmente ### Setup Rapido ```bash # 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 ```yaml # 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" ``` ```bash # 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 ```bash # /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 ```ini # /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 ```bash # 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 ```nginx # /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; } } ``` ```bash # 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 ```yaml # 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 ```bash # .env.staging DB_PASSWORD=YourStrongPassword123! ``` ### Deploy Script ```bash #!/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 ```yaml # 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 # 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 ```bash # 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 ```bash # Manager node docker swarm init --advertise-addr # Worker nodes (run on each worker) docker swarm join --token :2377 # Verify cluster docker node ls ``` ### Stack Deploy ```yaml # 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 ```bash # 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 ```yaml # 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 ```yaml # 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 ```yaml # 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 ```yaml # 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 ```yaml # 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 ```bash # 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 ```bash #!/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 ```bash #!/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+