160 lines
4.6 KiB
Markdown
160 lines
4.6 KiB
Markdown
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 doivent être effectuées 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*).
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
42sh$ curl "https://auth.docker.io/token"\
|
|
> "?service=registry.docker.io&scope=repository:library/hello-world:pull" | jq .
|
|
{
|
|
"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.
|
|
|
|
Avec `jq`, on peut l'extraire grâce à :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
| jq -r .token
|
|
```
|
|
</div>
|
|
|
|
|
|
## Lecture de l'index d'images
|
|
|
|
Une fois en possession de notre jeton, nous pouvons maintenant demander l'index
|
|
d'images à notre registre :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
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>
|
|
|
|
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 :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
curl -s \
|
|
-H "Authorization: Bearer ${TOKEN}" \
|
|
-H "Accept: ${MEDIATYPE}" \
|
|
"https://registry-1.docker.io/v2/library/hello-world/manifests/${MANIFEST_DIGEST}" | jq .
|
|
```
|
|
</div>
|
|
|
|
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 :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
curl -s --location \
|
|
-H "Authorization: Bearer ${TOKEN}" \
|
|
"https://registry-1.docker.io/v2/library/hello-world/blobs/${CONFIG_DIGEST}" | jq .
|
|
```
|
|
</div>
|
|
|
|
|
|
Enfin, armé du `digest` de notre couche, il ne nous reste plus qu'à la demander gentiment :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
wget --header "Authorization: Bearer ${TOKEN}" "https://registry-1.docker.io/v2/library/hello-world/blobs/${LAYER_DIGEST}"
|
|
```
|
|
</div>
|
|
|
|
|
|
## 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 :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
mkdir rootfs
|
|
tar xzf ${DL_LAYER} -C rootfs
|
|
```
|
|
</div>
|
|
|
|
Et voilà, nous avons extrait notre première image, nous devrions pouvoir :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
42sh# chroot rootfs /hello
|
|
Hello from Docker!
|
|
[...]
|
|
```
|
|
</div>
|
|
|
|
|
|
## Exercice {.unnumbered}
|
|
|
|
Réalisez un script pour automatiser l'ensemble de ces étapes :
|
|
|
|
<div lang="en-US">
|
|
```shell
|
|
42sh$ cd $(mktemp)
|
|
42sh$ ~/workspace/registry_play.sh library/hello
|
|
42sh$ find
|
|
.
|
|
./rootfs
|
|
./rootfs/hello
|
|
42sh# chroot rootfs /hello
|
|
Hello from Docker!
|
|
[...]
|
|
```
|
|
</div>
|