\newpage Registres ========= **Outils nécessaires :** `curl`, `gunzip`, `jq`, `tar`. * * * * * Dans cette partie, nous allons appréhender le fonctionnement d'un registre OCI, et préparer le *rootfs* d'une image de base (Debian, Ubuntu, hello, ...) : en nous préoccupant simplement de la couche la plus basse (qui ne contient pas de modification ou de suppression : chaque fichier est normal). ## 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 à leur 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 aujourd'hui ! Il n'en reste pas moins que le jeton est forgé pour un service donné (dans notre cas `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*).
```bash 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 à :
```bash | jq -r .token ```
**Attention :** 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 . ```
Dans la liste des manifests retournés, nous devons récupérer son `digest`. 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/${MANIFEST_DIGEST}" | jq . ```
Nous voici donc maintenant avec le manifest de notre image. Nous pouvons constater qu'il n'a bien qu'une seule couche, ouf ! ## Récupération de la configuration et de la première couche Les deux éléments que l'on cherche à récupérer vont se trouver dans le répertoire `blobs`, il ne s'agit en effet plus de manifest. 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. Pour récupérer la configuration de l'image :
```bash curl -s --location \ -H "Authorization: Bearer ${TOKEN}" \ "https://registry-1.docker.io/v2/library/hello-world/blobs/${CONFIG_DIGEST}" | jq . ```
Enfin, 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_DIGEST}" ```
## 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 :
```bash 42sh# chroot rootfs /hello Hello from Docker! [...] ```
## Exercice {-} Réalisez un script pour automatiser l'ensemble de ces étapes :
```bash 42sh$ cd $(mktemp) 42sh$ ~/workspace/registry_play.sh library/hello-world:latest 42sh$ find . ./rootfs ./rootfs/hello 42sh# chroot rootfs /hello Hello from Docker! [...] ```
Pensez également à tester avec d'autres images, comme par exemple `nemunaire/youp0m`. Il vous faudra alors extraire plusieurs couches.