611 lines
16 KiB
Markdown
611 lines
16 KiB
Markdown
# 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](#setup-registry-docker-privato)
|
|
2. [Protezione Codice Sorgente (Bytecode)](#protezione-codice-sorgente-bytecode)
|
|
3. [Build e Push dell'Immagine](#build-e-push-dellimmagine)
|
|
4. [Aggiornamento Docker Compose](#aggiornamento-docker-compose)
|
|
5. [Deploy sulle VM](#deploy-sulle-vm)
|
|
|
|
---
|
|
|
|
## Setup Registry Docker Privato
|
|
|
|
### Opzione 1: Registry Locale Semplice (HTTP - Solo per sviluppo)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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.
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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)
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
# 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__/`
|
|
|
|
```dockerfile
|
|
# 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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
./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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
./scripts/update-compose-image.sh <registry_url> <image_name> <tag>
|
|
```
|
|
|
|
#### Esempio
|
|
|
|
```bash
|
|
# 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:**
|
|
```yaml
|
|
orchestrator-1-load:
|
|
build: .
|
|
container_name: orchestrator-1-load
|
|
...
|
|
```
|
|
|
|
**Dopo:**
|
|
```yaml
|
|
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:
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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
|
|
|
|
```bash
|
|
# 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:**
|
|
```bash
|
|
# 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`:
|
|
```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:
|
|
```bash
|
|
docker login 192.168.1.203:5000
|
|
```
|
|
|
|
### Le immagini non si aggiornano sulle VM
|
|
|
|
**Soluzione:**
|
|
```bash
|
|
# 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`)
|