virli/tutorial/docker-internals/registry.md

184 lines
4.8 KiB
Markdown
Raw Normal View History

2020-09-14 13:46:13 +00:00
\newpage
Registres
=========
2022-10-18 04:15:39 +00:00
Nous allons appréhender le fonctionnement d'un registre OCI, en essayant de
récupérer les couches de quelques images (Debian, Ubuntu, hello, ...) : dans un
premier temps 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
2022-10-18 14:40:31 +00:00
devoir nous plier à son mécanisme d'authentification : chaque requête au
2020-09-14 13:46:13 +00:00
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
2022-02-24 19:43:43 +00:00
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 !
2022-02-24 19:43:43 +00:00
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` : <span
lang="en-US">`repository:hello-world:pull`</span>). Ce qui nous donne :
[^quiddepot]: Dans un registre, les fichiers qui composent l'image forment un
dépôt (*repository*).
<div lang="en-US">
```bash
2022-05-04 09:18:16 +00:00
42sh$ curl "https://auth.docker.io/token?service=registry.docker.io&" \
2020-09-14 13:46:13 +00:00
"scope=repository:library/hello-world:pull" | jq .
2018-11-15 22:38:25 +00:00
```
```json
{
"token": "lUWXBCZzg2TGNUdmMy...daVZxGTj0eh",
"access_token": "eyJhbGciOiJSUzI1NiIsI...N5q469M3ZkL_HA",
"expires_in": 300,
"issued_at": "2012-12-12T12:12:12.123456789Z"
}
```
</div>
C'est le `token` qu'il faudra fournir lors de nos prochaines requêtes au
registre.
2021-09-23 00:55:18 +00:00
Avec `jq`, on peut l'extraire grâce à :
<div lang="en-US">
```bash
| jq -r .token
```
</div>
2022-02-24 19:43:43 +00:00
::::: {.warning}
Le token expire ! Pensez à le renouveler régulièrement.
:::::
2020-09-14 13:46:13 +00:00
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
2021-09-23 00:55:18 +00:00
d'images à notre registre :
<div lang="en-US">
```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 .
```
</div>
2022-10-18 14:40:31 +00:00
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.
2022-10-18 14:40:31 +00:00
## Lecture du *manifest*
2022-10-18 14:40:31 +00:00
Demandons maintenant le *manifest* correspondant à notre matériel et à notre
2021-09-23 00:55:18 +00:00
système d'exploitation :
<div lang="en-US">
```bash
curl -s \
-H "Authorization: Bearer ${TOKEN}" \
-H "Accept: ${MEDIATYPE}" \
2022-05-04 09:18:16 +00:00
"https://registry-1.docker.io/v2/library/hello-world/manifests/
${MNFST_DGST}"
```
</div>
2022-10-18 14:40:31 +00:00
Nous voici donc maintenant avec le *manifest* de notre image. Nous pouvons
2022-02-24 19:43:43 +00:00
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
2022-10-18 14:40:31 +00:00
répertoire `blobs`, il ne s'agit en effet plus de *manifest*. Si les *manifests*
2020-09-14 13:46:13 +00:00
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.
2021-09-23 00:55:18 +00:00
Pour récupérer la configuration de l'image :
<div lang="en-US">
```bash
curl -s --location \
-H "Authorization: Bearer ${TOKEN}" \
2022-05-04 09:18:16 +00:00
"https://registry-1.docker.io/v2/library/hello-world/blobs/${CNF_DIGEST}"
```
</div>
2021-09-23 00:55:18 +00:00
Enfin, armé du `digest` de notre couche, il ne nous reste plus qu'à la demander gentiment :
<div lang="en-US">
```bash
wget --header "Authorization: Bearer ${TOKEN}" \
2022-05-04 09:18:16 +00:00
"https://registry-1.docker.io/v2/library/hello-world/blobs/${LAYER_DGST}"
```
</div>
## Extraction
2022-10-18 14:40:31 +00:00
Le type indiqué par le *manifest* pour cette couche était :
2022-02-24 19:43:43 +00:00
application/vnd.docker.image.rootfs.diff.tar.gzip
Il s'agit donc d'une tarball compressée au format gzip :
<div lang="en-US">
```bash
mkdir rootfs
tar xzf ${DL_LAYER} -C rootfs
```
</div>
2021-09-23 00:55:18 +00:00
Et voilà, nous avons extrait notre première image, nous devrions pouvoir :
<div lang="en-US">
```bash
42sh# chroot rootfs /hello
Hello from Docker!
[...]
```
</div>
::::: {.exercice}
2022-10-18 14:40:31 +00:00
#### Assemblage {-}
2021-09-23 00:55:18 +00:00
Réalisez un script pour automatiser l'ensemble de ces étapes :
<div lang="en-US">
```bash
42sh$ cd $(mktemp -d)
2018-11-15 22:38:25 +00:00
2022-10-24 09:23:53 +00:00
42sh$ ./registry_play library/hello-world:latest
2018-11-15 22:38:25 +00:00
42sh$ find
.
./rootfs
./rootfs/hello
2018-11-15 22:38:25 +00:00
42sh# chroot rootfs /hello
Hello from Docker!
[...]
```
</div>
2020-09-14 13:46:13 +00:00
:::::