Files
proxmox-ha-setup/scripts/DOCKER_REGISTRY_GUIDE.md
2025-11-29 19:51:15 +01:00

16 KiB

Guida Docker Registry Privato

Questa guida spiega come configurare un registry Docker privato e utilizzare gli script per buildare e distribuire le immagini degli orchestrator.

Indice

  1. Setup Registry Docker Privato
  2. Protezione Codice Sorgente (Bytecode)
  3. Build e Push dell'Immagine
  4. Aggiornamento Docker Compose
  5. Deploy sulle VM

Setup Registry Docker Privato

Opzione 1: Registry Locale Semplice (HTTP - Solo per sviluppo)

# Avvia un registry Docker locale sulla porta 5000
docker run -d -p 5000:5000 --name registry --restart=always registry:2

# Verifica che sia in esecuzione
curl http://localhost:5000/v2/_catalog

Opzione 2: Registry Locale con Persistenza

# Crea directory per i dati
mkdir -p /opt/docker-registry/data

# Avvia registry con volume persistente
docker run -d \
  -p 5000:5000 \
  --name registry \
  --restart=always \
  -v /opt/docker-registry/data:/var/lib/registry \
  registry:2

Opzione 3: Registry con HTTPS (Certificato Self-Signed con SANs)

⚠️ IMPORTANTE: I certificati moderni devono usare Subject Alternative Names (SANs) invece del campo Common Name.

# Usa lo script per generare certificati corretti
./scripts/generate-registry-cert.sh 192.168.1.204 registry.local

# Oppure manualmente:
mkdir -p /opt/docker-registry/{data,certs}

# Crea file di configurazione OpenSSL con SANs
cat > /opt/docker-registry/certs/openssl.cnf << 'EOF'
[req]
default_bits       = 4096
distinguished_name = req_distinguished_name
req_extensions     = req_ext
x509_extensions    = v3_ca
prompt             = no

[req_distinguished_name]
C  = IT
ST = Italy
L  = City
O  = Docker Registry
CN = registry.local

[req_ext]
subjectAltName = @alt_names

[v3_ca]
subjectAltName = @alt_names
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, keyEncipherment, keyCertSign
extendedKeyUsage = serverAuth

[alt_names]
DNS.1 = registry.local
DNS.2 = localhost
IP.1  = 192.168.1.204
IP.2  = 127.0.0.1
EOF

# Genera certificato con SANs
openssl req -newkey rsa:4096 \
  -nodes -sha256 \
  -keyout /opt/docker-registry/certs/domain.key \
  -x509 -days 365 \
  -config /opt/docker-registry/certs/openssl.cnf \
  -out /opt/docker-registry/certs/domain.crt

# Verifica SANs nel certificato
openssl x509 -in /opt/docker-registry/certs/domain.crt -text -noout | grep -A 3 "Subject Alternative Name"

# Avvia registry con HTTPS
docker run -d \
  -p 5000:5000 \
  --name registry \
  --restart=always \
  -v /opt/docker-registry/data:/var/lib/registry \
  -v /opt/docker-registry/certs:/certs \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2

Opzione 4: Registry con Autenticazione + HTTPS

# Genera certificati (vedi Opzione 3)
./scripts/generate-registry-cert.sh 192.168.1.204 registry.local

# Crea utente e password
mkdir -p /opt/docker-registry/auth
docker run --rm --entrypoint htpasswd httpd:2 \
  -Bbn myuser mypassword > /opt/docker-registry/auth/htpasswd

# Avvia registry con autenticazione e HTTPS
docker run -d \
  -p 5000:5000 \
  --name registry \
  --restart=always \
  -v /opt/docker-registry/data:/var/lib/registry \
  -v /opt/docker-registry/auth:/auth \
  -v /opt/docker-registry/certs:/certs \
  -e REGISTRY_AUTH=htpasswd \
  -e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
  -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  registry:2

# Login al registry
docker login 192.168.1.204:5000

Configurazione Client Docker per Registry HTTPS (Self-Signed)

Se usi certificati self-signed, devi installare il certificato sui client Docker:

Metodo Automatico (Raccomandato)

# Sul tuo computer di sviluppo o sulle VM client
./scripts/setup-registry-client.sh 192.168.1.204

# Lo script scaricherà e installerà automaticamente il certificato

Metodo Manuale

# 1. Crea directory per i certificati Docker
sudo mkdir -p /etc/docker/certs.d/192.168.1.204:5000

# 2. Copia il certificato dal registry
scp root@192.168.1.204:/opt/docker-registry/certs/domain.crt /tmp/registry.crt
sudo cp /tmp/registry.crt /etc/docker/certs.d/192.168.1.204:5000/ca.crt

# 3. Riavvia Docker
sudo systemctl restart docker

# 4. (Opzionale) Installa anche nel sistema per curl/wget
sudo cp /tmp/registry.crt /usr/local/share/ca-certificates/registry.crt
sudo update-ca-certificates

Test Connessione con Curl

# Test con certificato insecure (disabilita verifica)
curl -k https://192.168.1.204:5000/v2/

# Test con certificato installato nel sistema
curl https://192.168.1.204:5000/v2/_catalog

# Test con certificato specificato
curl --cacert /etc/docker/certs.d/192.168.1.204:5000/ca.crt https://192.168.1.204:5000/v2/_catalog

# Con autenticazione
curl -k -u myuser:mypassword https://192.168.1.204:5000/v2/_catalog

Configurazione Client Docker per Registry Insicuro (HTTP)

Se usi un registry HTTP locale, devi configurare Docker per accettare connessioni insicure:

# Edita /etc/docker/daemon.json
sudo nano /etc/docker/daemon.json

# Aggiungi:
{
  "insecure-registries": ["localhost:5000", "192.168.1.X:5000"]
}

# Riavvia Docker
sudo systemctl restart docker

Protezione Codice Sorgente (Bytecode)

Le immagini Docker vengono buildare con una configurazione speciale che protegge il codice sorgente Python.

Come Funziona

Il Dockerfile è configurato per:

  1. Compilare tutti i file Python in bytecode (.pyc) usando Python con ottimizzazione -OO
  2. Rimuovere tutti i file sorgente .py
  3. Mantenere solo i file bytecode compilati in __pycache__/
# Compila tutti i file Python in bytecode
# Usa -OO per rimuovere docstring e assert (ottimizzazione massima)
RUN python -OO -m compileall /app/src /app/env || true

# Rimuovi tutti i file sorgente .py, lasciando solo i .pyc compilati in __pycache__
RUN find /app/src -type f -name "*.py" -delete && \
    find /app/env -type f -name "*.py" -delete || true

Vantaggi

Protezione del Codice: I file sorgente non sono accessibili nell'immagine Dimensione Ridotta: I file .pyc sono più compatti dei .py Performance: Leggero miglioramento delle prestazioni (no compilazione a runtime) Rimozione Docstring: Con -OO vengono rimossi anche commenti e docstring

Limitazioni

⚠️ Debug Difficile: I traceback mostrano solo numeri di riga, non il codice sorgente ⚠️ No Reverse Engineering: Impossibile vedere la logica senza decompilare ⚠️ Serve Backup: Mantieni sempre i sorgenti in un repository git separato

Test dell'Immagine Bytecode

Usa lo script test-pyc-image.sh per verificare che l'immagine funzioni correttamente:

# Test immagine locale
./scripts/test-pyc-image.sh orchestrator-app:latest

# Test immagine dal registry
./scripts/test-pyc-image.sh 192.168.1.203:5000/orchestrator-app:v1.0.0

Il test verifica:

  • Assenza di file .py in /app/src
  • Presenza di file .pyc compilati
  • Importazione corretta dei moduli
  • Esecuzione dei moduli orchestrator
  • Configurazione ambiente Python

Struttura File nell'Immagine

Prima (con sorgenti):

/app/src/
├── load_orchestrator.py
├── elab_orchestrator.py
├── send_orchestrator.py
└── ftp_csv_receiver.py

Dopo (solo bytecode):

/app/src/
├── __pycache__/
│   ├── load_orchestrator.cpython-312.opt-2.pyc
│   ├── elab_orchestrator.cpython-312.opt-2.pyc
│   ├── send_orchestrator.cpython-312.opt-2.pyc
│   └── ftp_csv_receiver.cpython-312.opt-2.pyc

Build e Push dell'Immagine

Script: build-and-push-image.sh

Lo script automatizza il processo di build e push dell'immagine Docker.

Sintassi

./scripts/build-and-push-image.sh [registry_url] [image_name] [tag] [dockerfile_type]

Parametri

  • registry_url - URL del registry privato (default: 192.168.1.204:5000)
  • image_name - Nome dell'immagine (default: orchestrator-app)
  • tag - Tag dell'immagine (default: latest)
  • dockerfile_type - Tipo di Dockerfile: standard o distroless (default: standard)

Tipi di Dockerfile

standard - Usa Dockerfile (python:3.12-slim)

  • Dimensione: ~333MB
  • Include shell per debugging
  • Ideale per sviluppo e staging

distroless - Usa Dockerfile.distroless (gcr.io/distroless/python3)

  • Dimensione: ~180MB (50% più piccola!)
  • Nessuna shell (massima sicurezza)
  • Ideale per produzione

Esempi

# Build standard (default)
./scripts/build-and-push-image.sh

# Build distroless per produzione
./scripts/build-and-push-image.sh 192.168.1.204:5000 orchestrator-app latest distroless

# Build distroless con versione specifica
./scripts/build-and-push-image.sh 192.168.1.204:5000 orchestrator-app v1.2.3 distroless

# Build standard per staging
./scripts/build-and-push-image.sh 192.168.1.204:5000 orchestrator-app staging standard

Cosa fa lo script

  1. Verifica prerequisiti (Docker)
  2. Controlla che esistano Dockerfile e directory progetto
  3. Mostra configurazione e chiede conferma
  4. Builda l'immagine Docker
  5. Tagga l'immagine per il registry
  6. Mostra informazioni sull'immagine (dimensione, layer)
  7. Opzionalmente testa l'immagine localmente
  8. Pusha l'immagine al registry
  9. Opzionalmente rimuove l'immagine locale

Aggiornamento Docker Compose

Script: update-compose-image.sh

Questo script aggiorna i file docker-compose.yml in vm1/ e vm2/ per usare l'immagine dal registry invece di buildarla localmente.

Sintassi

./scripts/update-compose-image.sh <registry_url> <image_name> <tag>

Esempio

# Aggiorna docker-compose.yml per usare l'immagine dal registry
./scripts/update-compose-image.sh registry.example.com:5000 orchestrator-app latest

Cosa fa lo script

  1. Crea backup dei file docker-compose.yml (.backup)
  2. Sostituisce build: . con image: registry_url/image_name:tag
  3. Aggiorna entrambi i file vm1/ e vm2/

Prima e Dopo

Prima:

orchestrator-1-load:
  build: .
  container_name: orchestrator-1-load
  ...

Dopo:

orchestrator-1-load:
  image: registry.example.com:5000/orchestrator-app:latest
  container_name: orchestrator-1-load
  ...

Deploy sulle VM

1. Setup Registry su una VM Proxmox (Opzionale)

Se vuoi hostare il registry su una delle VM Proxmox:

# Crea una VM per il registry
./scripts/create-vm.sh 203 registry-server 2 4096 50G

# SSH nella VM
ssh root@192.168.1.203

# Avvia il registry
docker run -d \
  -p 5000:5000 \
  --name registry \
  --restart=always \
  -v /opt/registry-data:/var/lib/registry \
  registry:2

2. Build e Push dell'Immagine

# Sul tuo computer locale, dalla directory del progetto
cd /home/alex/devel/proxmox-ha-setup

# Build e push al registry
./scripts/build-and-push-image.sh 192.168.1.203:5000 orchestrator-app v1.0.0

3. Aggiorna Docker Compose Files

# Aggiorna i file docker-compose.yml
./scripts/update-compose-image.sh 192.168.1.203:5000 orchestrator-app v1.0.0

4. Deploy su VM1 e VM2

# Copia i file aggiornati sulle VM
scp -r vm1/* root@192.168.1.201:/opt/myapp/
scp -r vm2/* root@192.168.1.202:/opt/myapp/

# Su VM1
ssh root@192.168.1.201
cd /opt/myapp
docker pull 192.168.1.203:5000/orchestrator-app:v1.0.0
docker compose up -d

# Su VM2
ssh root@192.168.1.202
cd /opt/myapp
docker pull 192.168.1.203:5000/orchestrator-app:v1.0.0
docker compose up -d

5. Verifica Deploy

# Controlla i container in esecuzione
ssh root@192.168.1.201 'docker ps'
ssh root@192.168.1.202 'docker ps'

# Verifica i log
ssh root@192.168.1.201 'docker logs orchestrator-1-load'
ssh root@192.168.1.202 'docker logs orchestrator-1-load'

Workflow Completo di Esempio

Scenario: Deploy Iniziale

# 1. Setup registry su VM dedicata
./scripts/create-vm.sh 203 registry 2 4096 50G
ssh root@192.168.1.203 'docker run -d -p 5000:5000 --restart=always -v /opt/registry:/var/lib/registry --name registry registry:2'

# 2. Configura Docker per accettare il registry insicuro (su tutte le VM)
for vm in 201 202; do
  ssh root@192.168.1.$vm 'echo "{\"insecure-registries\": [\"192.168.1.203:5000\"]}" > /etc/docker/daemon.json && systemctl restart docker'
done

# 3. Build e push immagine
./scripts/build-and-push-image.sh 192.168.1.203:5000 orchestrator-app v1.0.0

# 4. Aggiorna docker-compose files
./scripts/update-compose-image.sh 192.168.1.203:5000 orchestrator-app v1.0.0

# 5. Deploy sulle VM
for vm in 201 202; do
  scp -r vm$((vm-200))/* root@192.168.1.$vm:/opt/myapp/
  ssh root@192.168.1.$vm 'cd /opt/myapp && docker compose pull && docker compose up -d'
done

Scenario: Aggiornamento dell'Applicazione

# 1. Build nuova versione
./scripts/build-and-push-image.sh 192.168.1.203:5000 orchestrator-app v1.1.0

# 2. Aggiorna docker-compose (se necessario)
./scripts/update-compose-image.sh 192.168.1.203:5000 orchestrator-app v1.1.0

# 3. Update sulle VM con zero downtime
# Prima aggiorna VM2 (backup)
ssh root@192.168.1.202 'cd /opt/myapp && docker compose pull && docker compose up -d'

# Attendi che sia stabile
sleep 30

# Poi aggiorna VM1 (master)
ssh root@192.168.1.201 'cd /opt/myapp && docker compose pull && docker compose up -d'

Comandi Utili

Gestione Registry

# Lista immagini nel registry
curl http://192.168.1.203:5000/v2/_catalog

# Lista tag di un'immagine
curl http://192.168.1.203:5000/v2/orchestrator-app/tags/list

# Verifica dimensione del registry
du -sh /opt/registry-data

Gestione Immagini

# Pull immagine dal registry
docker pull 192.168.1.203:5000/orchestrator-app:v1.0.0

# Lista immagini locali
docker images | grep orchestrator-app

# Rimuovi immagini vecchie
docker image prune -a

Debug

# Testa connessione al registry
telnet 192.168.1.203 5000

# Verifica log del registry
docker logs registry

# Test pull senza deploy
docker pull 192.168.1.203:5000/orchestrator-app:latest

Best Practices

  1. Versioning: Usa tag semantici (v1.0.0, v1.1.0) invece di latest per produzione
  2. Backup: Monta un volume per /var/lib/registry per persistenza
  3. Security: Usa HTTPS e autenticazione per registri in produzione
  4. Cleanup: Rimuovi regolarmente immagini vecchie dal registry
  5. Testing: Testa sempre l'immagine localmente prima del push
  6. Documentation: Documenta le modifiche in ogni versione

Troubleshooting

Errore: "connection refused" durante il push

Soluzione:

# Verifica che il registry sia in esecuzione
docker ps | grep registry

# Verifica connettività
curl http://192.168.1.203:5000/v2/

Errore: "http: server gave HTTP response to HTTPS client"

Soluzione: Aggiungi il registry come insicuro in /etc/docker/daemon.json:

{
  "insecure-registries": ["192.168.1.203:5000"]
}

Poi riavvia Docker: systemctl restart docker

Errore: "denied: requested access to the resource is denied"

Soluzione: Fai login al registry:

docker login 192.168.1.203:5000

Le immagini non si aggiornano sulle VM

Soluzione:

# Forza il pull della nuova immagine
docker compose pull
docker compose up -d --force-recreate

Note

  • Lo script build-and-push-image.sh builderà l'immagine dalla directory /home/alex/devel/proxmox-ha-setup/vm1
  • I file docker-compose.yml in vm1/ e vm2/ devono usare build: . per i servizi orchestrator
  • Puoi usare più tag per la stessa immagine (es: latest, v1.0.0, production)