Registry locale

E disponibile l'immagine registry:latest su Docker Hub. Installeremo su manager il servizio registry come servizio, con un contenitore da tale immagine.

Docker permette l'accesso a contenitori esterni col protocollo HTTP (non sicuro) solo da localhost. Ugni altra URL, non locale, deve usare il protocollo HTTPS (sicuro).

Ogni nostro nodo swarm deriva dall'immagine doker, che contiene un certificato per myregistry.com, che risolve al nodo manager.

sw-registry

Le immagini del servizio registry di swarm sono le stesse del registry dello host tramite una catena di host mapping (o bind mapping):

  • la directory /var/lib/registry del servizio è mappata alla directory /registry del nodo swarm che implementa il servixio - che deve essere manager.
  • su manager la directory /registry è mappata alla directory ~/registry dello host
  • il contenitore registry, che è fuori dallo swarm ma nell'ambiente docker dello host, mappa anch'esso la sua directory /var/lib/registry alla diretory ~/registry dello host

Così l'immagine che si chiama localhost:5000/immagine sullo host si chiama myregistry.com:5000/immagine per i nodi dello swarm. E' sufficiente caricare con push un'immagine sul registry dello host perchè sia visibile al servizio registry dello swarm.

Lancio del servizio registry

Col comando:

dk docker service create --name registry --publish=5000:5000 \
  --constraint=node.hostname==manager \
  --mount=type=bind,src=/root,dst=/certs \
  --mount=type=bind,src=/registry,dst=/var/lib/registry\
  -e REGISTRY_HTTP_ADDR=0.0.0.0:5000 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/registry.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/registry.key \
  registry:latest

Test

Compiere il pull di un'immagine su manager:

dk docker pull nginx

Aggiungere un tag che punta al registry:

dk docker tag nginx:latest myregistry.com:5000/nginx:latest

Compiere il push al registry locale:

dk docker push myregistry.com:5000/nginx:latest

Lanciare un servizio che carica l'immagine dal registry locale:

dk docker service create --name my-nginx \
  --replicas 1 -p 8000:80 \
  myregistry.com:5000/nginx

Scaliamo il servizio:

dk docker service scale my-nginx=5

La velocità è notevolmente aumentata. Inoltre abbiamo la possibilità di porre nel registry le nostre immagini private.

Esercizio: Sviluppo di un servizio

Preparare lo scaffolding:

mkdir -p ~/swarm/hello
cd ~/swarm/hello

Il nostro applicativo è scritto in Go, è un piccolo web server che stampa un messaggio e lo hostname del nodo su cui esegue.

vi main.go
package main

import (
  "fmt"
  "log"
  "net/http"
  "os"
)

func handler(w http.ResponseWriter, r *http.Request) {
  hostname, _ := os.Hostname()
  fmt.Fprintf(w, "Hello, 世界. My hostname is: %s\n", hostname)
}
func main() {
  http.HandleFunc("/", handler)
  fmt.Println("Running demo app. Press Ctrl+C to exit...")
  log.Fatal(http.ListenAndServe(":8888", nil))
}

Il Dockerfile di generazione dell'immagine è:

FROM golang:1.17-alpine AS build

WORKDIR /src/
COPY main.go go.* /src/
ENV GO111MODULE="off"
RUN CGO_ENABLED=0 go build -o /bin/demo

FROM scratch
COPY --from=build /bin/demo /bin/demo
EXPOSE 8888
CMD ["/bin/demo"]

Generiamo l'immagine myhello:

docker build -t myhello .

Aggiungiamo un tag all'immagine generata, che indichi il nostro repository locale sullo host:

docker tag myhello:latest localhost:5000/myhello:latest

Compiamo il push al repository locale sullo host. Grazie ai nostri host mapping, l'immagine diventa disponibile anche sul servizio registry dello swarm.

docker push localhost:5000/myhello:latest

Generiamo un servizio sullo swarm:

dk docker service create --name myhello \
  -p 8888:8888 \
  myregistry.com:5000/myhello

Listiamo i servizi dello swarm:

dk docker service ls

Testiamo il servizio dallo host:

curl manager:8888

Scaliamo il servizio sullo swarm:

dk docker service scale myhello=5

Proviamo più volte ad accedere al servizio dallo host:

curl manager:8888

Ogni volta il rapporto da uno hostname diverso.