Un registro di container è un catalogo di storage da cui è possibile push e pull delle immagini di container.

Esistono molti registri pubblici e privati a disposizione dei sviluppatori come Docker Hub, Amazon ECR, e Google Cloud Artifact Registry. Ma a volte, invece di affidarsi a un fornitore esterno, potreste voler ospitare le vostre immagini da soli. Questo vi dà maggiore controllo sul come il registro è configurato e dove sono ospitate le immagini di container.

Questo articolo è un tutorial pratico che vi insegnerà come ospitare da soli un registro di container.

Indice

Riceverete il massimo beneficio da questo articolo se già conoscete gli strumenti come Docker e NGINX e avete una generale idea di cosa sia un container.

Cosa è un’immagine di container?

Prima di parlare dei registri di container, capiamo prima cosa sia un’immagine di container. In breve, un’immagine di container è un pacchetto che include tutti i file, le librerie e le configurazioni necessarie per eseguire un container. Sono composti da strati in cui ogni strato rappresenta un insieme di modifiche al file system che aggiungono, rimuovono o modificano file.

Il modo più comune per creare un’immagine di container è l’uso di un Dockerfile.

# costruisci un'immagine
docker build -t pliutau/hello-world:v0 .

# controlla le immagini locali
docker images
# REPOSITORY    TAG       IMAGE ID       CREATED          SIZE
# hello-world   latest    9facd12bbcdd   22 seconds ago   11MB

Questo crea un’immagine contenitore che viene memorizzata sulla macchina locale. Ma cosa succede se volete condividere questa immagine con altri o usarla su una macchina diversa? Ecco dove entra in gioco il registro dei contenitori.

Cos’è un Registro Contenitori?

Un registro contenitori è un catalogo di archiviazione in cui è possibile caricare e scaricare le immagini contenitore. Le immagini sono raggruppate in repository, che sono raccolte di immagini relative con lo stesso nome. Per esempio, sul registro Docker Hub, nginx è il nome del repository che contiene diverse versioni delle immagini NGINX.

Alcuni registri sono pubblici, il che significa che le immagini ospitate su di essi sono accessibili a chiunque sulla rete Internet. I registri pubblici come Docker Hub sono una buona scelta per ospitare progetti open-source.

Dall’altra parte, i registri privati forniscono un modo per includere sicurezza e privacy nell’archiviazione delle immagini contenitore aziendali, sia ospitate in cloud o sul posto. questi registri privati spesso includono funzionalità di sicurezza avanzate e supporto tecnico.

Ci sono una lista in crescita di registri privati disponibili come Amazon ECR, GCP Artifact Registry, GitHub Container Registry, e Docker Hub offre anche una funzione di repository privato.

Come sviluppatore, si interagisce con il registro dei container quando si usano i comandi docker push e docker pull.

docker push docker.io/pliutau/hello-world:v0

# Nel caso di Docker Hub si potrebbe anche saltare la parte del registro
docker push pliutau/hello-world:v0

Ecco l’anatomia dell’URL di un’immagine di container:

docker pull docker.io/pliutau/hello-world:v0@sha256:dc11b2...
                |            |            |          |
                ↓            ↓            ↓          ↓
             registry    repository      tag       digest

Perché si potrebbe voler ospitare autonomamente un registro di container

A volte, invece di affidarsi a un provider come AWS o GCP, si potrebbe voler ospitare autonomamente le immagini. In questo modo si mantiene l’infrastruttura interna e si fa meno affidamento su fornitori esterni. In alcuni settori fortemente regolamentati, questo è addirittura un requisito.

Un registro self-hosted viene eseguito sui vostri server, dandovi un maggiore controllo su come il registro è configurato e dove sono ospitate le immagini dei container. Allo stesso tempo, però, comporta un costo per la manutenzione e la protezione del registro.

Come auto-ospitare un registro di container

Sono disponibili diverse soluzioni open-source per il registro dei container. La più popolare è quella ufficialmente supportata da Docker, chiamata registry, con la sua implementazione per la memorizzazione e la distribuzione delle immagini e degli artefatti dei container. Questo significa che è possibile eseguire il proprio registro all’interno di un container.

Ecco i passi principali per eseguire un registro su un server:

  • Installare Docker e Docker Compose sul server.

  • Configurare ed eseguire il contenitore registry.

  • Esegui NGINX per la gestione del TLS e il reindirizzamento delle richieste al contenitore registry.

  • Imposta i certificati SSL e configura un dominio.

Step 1: Installare Docker e Docker Compose sul server

Puoi utilizzare qualsiasi server che supporti Docker. Per esempio, puoi usare un Droplet di DigitalOcean con Ubuntu. Per questo demo, ho creato una VM con Ubuntu su Google Cloud Compute.

neofetch

# SO: Ubuntu 20.04.6 LTS x86_64
# CPU: Intel Xeon (2) @ 2.200GHz
# Memoria: 3908MiB

Una volta dentro la nostra VM, dovremmo installare Docker e Docker Compose. Docker Compose è facoltativo, ma rende più semplice la gestione di applicazioni multi-contenitore.

# install docker engine and docker-compose
sudo snap install docker

# verifica dell'installazione
docker --version
docker-compose --version

Step 2: Configurare e eseguire il contenitore registry

Prossimo, dobbiamo configurare il nostro contenitore registry. Il seguente file compose.yaml creerà un contenitore registry con un volume per la memorizzazione delle immagini e un volume per la memorizzazione del file password.

services:
  registry:
    image: registry:latest
    environment:
      REGISTRY_AUTH: htpasswd
      REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
      REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
      REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
    volumes:
      # Monta il file delle password
      - ./registry/registry.password:/auth/registry.password
      # Monta la directory dei dati
      - ./registry/data:/data
    ports:
      - 5000

Il file delle password definito in REGISTRY_AUTH_HTPASSWD_PATH viene utilizzato per autenticare gli utenti quando push o pull le immagini dal registro. Dovremmo creare un file delle password utilizzando il comando htpasswd. Dovremmo anche creare una cartella per l’archiviazione delle immagini.

mkdir -p ./registry/data

# installa htpasswd
sudo apt install apache2-utils

# crea un file password. nome utente: busy, password: bee
htpasswd -Bbn busy bee > ./registry/registry.password

Ora possiamo avviare il contenitore del registro. Se vedete questo messaggio, allora tutto sta funzionando come dovrebbe:

docker-compose up

# l'esecuzione riuscita dovrebbe visualizzare qualcosa del genere:
# registry | level=info msg="listening on [::]:5000"

Step 3: Avviare NGINX per la gestione di TLS

Come menzionato prima, possiamo utilizzare NGINX per la gestione di TLS e inoltrare richieste al contenitore del registro.

Il Registro Docker richiede un certificato SSL valido e fidato per funzionare. Puoi usare qualcosa come Let’s Encrypt o ottenerlo manualmente. Assicurati di avere un nome di dominio che punta al tuo server (registry.pliutau.com nel mio caso). Per questa dimostrazione ho già ottenuto i certificati utilizzando certbot e li ho messi nella directory ./nginx/certs.

Riprendendo il nostro Docker Registry in un contenitore, possiamo anche eseguire NGINX in un contenitore aggiungendo il seguente servizio al file compose.yaml:

services:
  registry:
    # ...
  nginx:
    image: nginx:latest
    depends_on:
      - registry
    volumes:
      # mount the nginx configuration
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      # mount the certificates obtained from Let's Encrypt
      - ./nginx/certs:/etc/nginx/certs
    ports:
      - "443:443"

Il nostro file nginx.conf potrebbe avere questo aspetto:

worker_processes auto;

events {
    worker_connections 1024;
}

http {
    upstream registry {
        server registry:5000;
    }

    server {
        server_name registry.pliutau.com;
        listen 443 ssl;

        ssl_certificate /etc/nginx/certs/fullchain.pem;
        ssl_certificate_key /etc/nginx/certs/privkey.pem;

        location / {
            # important setting for large images
            client_max_body_size                1000m;

            proxy_pass                          http://registry;
            proxy_set_header  Host              $http_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;
            proxy_read_timeout                  900;
        }
    }
}

Pronto per andare!

Dopo questi passaggi, possiamo eseguire i contenitori del nostro registry e di Nginx.

docker-compose up

Ora, dal lato del client, puoi push e pull le immagini dal tuo registry. Ma prima dobbiamo effettuare l’accesso al registry.

docker login registry.pliutau.com

# Username: busy
# Password: bee
# Login Succeeded

Ora è il momento di costruire e push l’immagine nel nostro registry auto-hosted:

docker build -t registry.pliutau.com/pliutau/hello-world:v0 .

docker push registry.pliutau.com/pliutau/hello-world:v0
# v0: digest: sha256:a56ea4... size: 738

Sul tuo server puoi controllare le immagini caricate nella cartella data:

ls -la ./registry/data/docker/registry/v2/repositories/

Altre opzioni

Seguendo l’esempio sopra, puoi anche eseguire il registry su Kubernetes. O puoi usare un servizio di registry gestito come Harbor, che è un registro open-source che offre funzionalità di sicurezza avanzate e è compatibile con Docker e Kubernetes.

Anche se vuoi avere una UI per il tuo registro auto-gestito, potresti utilizzare un progetto come joxit/docker-registry-ui e eseguirlo in un container separato.

Conclusione

I registri container auto-gestiti ti consentono di avere il controllo completo sul tuo registro e sul modo in cui è distribuito. Allo stesso tempo, questo comporta il costo della manutenzione e della sicurezza del registro.

Qualunque sia il motivo per cui stai utilizzando un registro auto-gestito, ora sai come lo fare. Da qui puoi confrontare le diverse opzioni e scegliere quella che meglio si adatta alle tue necessità.

Puoi trovare il codice sorgente completo di questa demo su GitHub. Inoltre, puoi guardarlo come video sul nostro canale YouTube.