Installer un registry Docker privé et multiarch
Un registry Docker privé, c’est pratique ! Mais s’il est en plus multiarch, c’est parfait ! Pourquoi faire ? Pour par exemple pouvoir installer avec le même docker pull
une image x86 ou une image arm.
Mais encore ? Si votre cluster Kubernetes est composé de noeuds x86 et de noeuds arm et que vous faites un daemonset, il est plutôt indispensable de pouvoir pointer sur une image unique ;-) (c’est aussi valable pour du Swarm, du déploiement via du compose…).
Let’s Encrypt
Pour générer un certificat Let’s Encrypt pour votre registry, vous aurez besoin du client certbot. Vérifiez s’il existe dans les paquets de votre distribution ou clonez le repository Github :
- Clonez le repository :
git clone https://github.com/certbot/certbot.git
Dans le répertoire certbot, utilisez certbot-auto pour générer un certificat :
./certbot-auto certonly --standalone --email admin@example.com -d mon-registry.com
Votre certificat sera stocké dans /etc/letsencrypt.
Installer le registry Docker v2
Pour persister les données du registry sur le disque et stocker sa configuration, je prépare son homedir :
mkdir -p /opt/registry/{auth,certs,data}
Dans le répertoire auth, je vais générer les couples user/pass, au format htpasswd, autorisés sur mon registry. Par exemple, si je reprends l’exemple de la doc docker :
docker run --entrypoint htpasswd registry:2 -Bbn testuser1 testpassword1 >> auth/htpasswd docker run --entrypoint htpasswd registry:2 -Bbn testuser2 testpassword2 >> auth/htpasswd
Dans le répertoire certs, on retrouve la chaine et la clé du certificat Let’s Encrypt :
cp /etc/letsencrypt/live/r3gistry.ddns.net/privkey.pem /opt/registry/certs/domain.key cp /etc/letsencrypt/live/r3gistry.ddns.net/fullchain.pem /opt/registry/certs/domain.crt
Le répertoire data contiendra les données de votre registry…
Je lance mon registry en ligne de commande avec :
docker run -d -p 5000:5000 --restart=always --name registry \\ -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 \\ -v /opt/registry/auth:/auth \\ -v /opt/registry/certs:/certs \\ -v /opt/registry/data:/data \\ registry:2
Une image multiarch
Mon salut est venu a la lecture de cette doc. Dans la version 2 / schéma 2 du manifeste des images Docker, il est possible de référencer derrière une image Docker une liste d’images Docker qui peuvent être spécifiques, par exemple, a une architecture. En clair, avec ce manifeste :
image: r3gistry:5000/common/prometheus:1.1.3
manifests:
-
image: r3gistry:5000/common/prometheus:1.1.3-arm
platform:
architecture: arm
os: linux
-
image: r3gistry:5000/common/prometheus:1.1.3-amd64
platform:
architecture: amd64
os: linux
… je vais pouvoir faire un docker pull r3gistry:5000/common/prometheus:1.1.3
.
Si je suis sur du intel, ca revient a faire un docker pull r3gistry:5000/common/prometheus:1.1.3-amd64
et mon raspberry fera lui un docker pull r3gistry:5000/common/prometheus:1.1.3-arm
!
Installation de manifest-tool
Reste a injecter ce manifeste dans le registry… Et il y a un outil pour ca. Il faudra vous construire le binaire. Pour ma part, j’ai fait comme ca :
Je clone le repo :
git clone https://github.com/estesp/manifest-tool /go/src/github.com/estesp/manifest-tool/
Il y a un Makefile et un Dockerfile mais j’ai fait simplement :
docker run -it -v /go:/go golang go build -o manifest github.com/estesp/manifest-tool
Et j’installe le binaire :
mv /go/manifest /usr/local/bin
Injection du manifeste
La suite est simple :
- Je pousse mon image amd64 :
docker push r3gistry:5000/common/prometheus:1.1.3-amd64
- Je pousse mon image arm :
docker push r3gistry:5000/common/prometheus:1.1.3-arm
- Je pousse mon manifest (celui vu plus haut) :
manifest pushml prometheus.yaml
. J’obtiens cette sortie :
$ /usr/local/bin/manifest pushml prometheus.yaml
INFO[0000] Retrieving digests of images...
INFO[0000] Image "r3gistry:5000/common/prometheus:1.1.3-arm" is digest sha256:d6; size: 2192
INFO[0001] Image "r3gistry:5000/common/prometheus:1.1.3-amd64" is digest sha256:63; size: 1986
Digest: sha256:5da2e32fd703d4743808e76e4
Si je veux consulter la liste des manifestes de cette image :
$ /usr/local/bin/manifest inspect r3gistry:5000/common/prometheus:1.1.3
r3gistry:5000/common/prometheus:1.1.3 is a manifest list containing the following 2 manifest references:
1 Mfst Type: application/vnd.docker.distribution.manifest.v2+json
1 Digest: sha256:d6
1 Mfst Length: 2192
1 Platform:
1 - OS: linux
1 - Arch: arm
1 - Variant:
1 - Feature:
1 # Layers: 10
layer 1: digest = sha256:38
layer 2: digest = sha256:a3
layer 3: digest = sha256:bc
layer 4: digest = sha256:0d
layer 5: digest = sha256:b7
layer 6: digest = sha256:49
layer 7: digest = sha256:3c
layer 8: digest = sha256:46
layer 9: digest = sha256:2c
layer 10: digest = sha256:5e
2 Mfst Type: application/vnd.docker.distribution.manifest.v2+json
2 Digest: sha256:63
2 Mfst Length: 1986
2 Platform:
2 - OS: linux
2 - Arch: amd64
2 - Variant:
2 - Feature:
2 # Layers: 9
layer 1: digest = sha256:9a
layer 2: digest = sha256:f3
layer 3: digest = sha256:a2
layer 4: digest = sha256:45
layer 5: digest = sha256:4b
layer 6: digest = sha256:7c
layer 7: digest = sha256:4c
layer 8: digest = sha256:80
layer 9: digest = sha256:35
Ce n’est pas encore parfait et il y a encore du boulot pour avoir un registry complètement compatible avec du multiarch mais cette solution m’a permis d’utiliser simplement les daemonsets Kubernetes sur mon cluster composé de noeuds arm et amd64 la ou avant, je devais jouer avec des règles iptables pour avoir le arm sur un registry et le amd64 sur un autre !