\newpage Registres d'images ================== Regardons d'un peu plus près les registres d'images OCI. Ce sont eux qui distribuent les images OCI et permettent à Docker de récupérer très facilement de nouveaux services. Dans les sections à venir, nous allons essayer de récupérer la configuration et les couches de quelques images courantes (Debian, Ubuntu, `hello-world`, ...) : dans un premier temps en nous préoccupant simplement de la couche la plus basse (le système de baase). Puis nous verrons dans le chapitre suivant comment gérer les autres couches. ## Authentification L'authentification est facultative et est laissée à l'appréciation du fournisseur de service. Étant donné que nous allons utiliser le [Docker Hub](https://hub.docker.com/), le registre par défaut de `docker`, nous allons devoir nous plier à son mécanisme d'authentification : chaque requête au registre doit être effectuée avec un jeton, que l'on obtient en s'authentifiant auprès d'un service dédié. Ce service peut délivrer un jeton sans authentifier l'interlocuteur, en restant anonyme ; dans ce cas, on ne pourra accéder qu'aux images publiques. Ça tombe bien, c'est ce qui nous intéresse ! Il n'en reste pas moins que le jeton est forgé pour un service donné (ici `registry.docker.io`) et avec un objectif bien cerné (pour nous, on souhaite récupérer le contenu du dépôt[^quiddepot] `hello-world` : `repository:hello-world:pull`). Ce qui nous donne : [^quiddepot]: Dans un registre, les fichiers qui composent l'image forment un dépôt (*repository*).
``` 42sh$ curl "https://auth.docker.io/token?service=registry.docker.io&" \ "scope=repository:library/hello-world:pull" | jq . ``` ```json { "token": "lUWXBCZzg2TGNUdmMy...daVZxGTj0eh", "access_token": "eyJhbGciOiJSUzI1NiIsI...N5q469M3ZkL_HA", "expires_in": 300, "issued_at": "2012-12-12T12:12:12.123456789Z" } ```
C'est le `token` qu'il faudra fournir lors de nos prochaines requêtes au registre. Avec `jq`, on peut l'extraire grâce à :
``` | jq -r .token ```
::::: {.warning} Le token expire ! Pensez à le renouveler régulièrement. ::::: En cas d'erreur inexplicable, vous pouvez ajouter un `-v` à la ligne de commande `curl`, afin d'afficher les en-têtes. Prêtez une attention toute particulière à `Www-Authenticate`. ## Lecture de l'index d'images Une fois en possession de notre jeton, nous pouvons maintenant demander l'index d'images à notre registre :
```bash curl -s \ -H "Authorization: Bearer ${TOKEN}" \ -H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \ "https://registry-1.docker.io/v2/library/hello-world/manifests/latest" | jq . ```
Parmi la liste des *manifests* retournés, nous devons récupérer le `digest` correspondant au système qui correspond à votre architecture et notre système. Dans tout l'écosystème OCI, les `digest` servent à la fois de chemin d'accès et de somme de contrôle. ## Lecture du *manifest* Demandons maintenant le *manifest* correspondant à notre matériel et à notre système d'exploitation :
```bash curl -s \ -H "Authorization: Bearer ${TOKEN}" \ -H "Accept: ${MEDIATYPE}" \ "https://registry-1.docker.io/v2/library/hello-world/manifests/ ${MNFST_DGST}" ```
Nous voici donc maintenant avec le *manifest* de notre image. Nous pouvons constater qu'il n'a bien qu'une seule couche. Ouf, ça va simplifier les choses ! ## Récupération de la configuration et de la première couche Les deux éléments que l'on cherche maintenant à récupérer vont se trouver dans le répertoire `blobs` de notre dépôt. Il ne s'agira plus de *manifest*, mais bien des fichiers définitifs. Récupérons la configuration de l'image comme ceci :
```bash curl -s --location \ -H "Authorization: Bearer ${TOKEN}" \ "https://registry-1.docker.io/v2/library/hello-world/blobs/${CNF_DIGEST}" ```
Remarquez l'usage de l'option `--location` de `curl` : si les *manifests* sont toujours stockés par le registre lui-même, les *blobs* peuvent être délégués à un autre service, par exemple dans le cloud, chez Amazon S3, un CDN, etc. Sans l'option `--location`, notre `curl` va retourner une redirection vers une autre adresse, celle qui contient effectivement la configuration. Il en sera de même pour les fichiers stockant les couches.\ Enfin d'autre part, armé du `digest` de notre couche, il ne nous reste plus qu'à la demander gentiment :
```bash wget --header "Authorization: Bearer ${TOKEN}" \ "https://registry-1.docker.io/v2/library/hello-world/blobs/${LAYER_DGST}" ```
## Extraction Le type indiqué par le *manifest* pour cette couche était : application/vnd.docker.image.rootfs.diff.tar.gzip Il s'agit donc d'une tarball compressée au format gzip :
```bash mkdir rootfs tar xzf ${DL_LAYER} -C rootfs ```
Et voilà, nous avons extrait notre première image, nous devrions pouvoir entrer dedans :
``` 42sh# chroot rootfs /hello Hello from Docker! [...] ```
::::: {.exercice} #### Assemblage {-} Réalisez un script pour automatiser l'ensemble de ces étapes :
``` 42sh$ cd $(mktemp -d) 42sh$ ./registry_play library/hello-world:latest 42sh$ find . ./rootfs ./rootfs/hello 42sh# chroot rootfs /hello Hello from Docker! [...] ```
:::::