quentin.dufour.io/_posts/2023-04-06-un-registre-statique-docker-avec-garage.md
Quentin 72ae0d59b6
All checks were successful
continuous-integration/drone/push Build is passing
Update Article “2023-04-06-un-registre-statique-docker-avec-garage”
2023-04-06 15:12:41 +00:00

243 lines
7.8 KiB
Markdown

---
layout: post
title: Un registre statique Docker avec Garage
date: 2023-04-06T16:13:14.025+02:00
status: draft
sitemap: true
category: developpement
description: Héberger vos conteneurs Docker directement depuis Garage
---
Dans ce petite article, je vais vous montrer rapidement comment monter votre registre Docker avec Garage seulement. En effet, un registre Docker n'est rien d'autre qu'une spécification par dessus HTTP, et il apparait que Garage supporte pile poil le bon sous ensemble pour la distribution (c'est à dire le téléchargement). Reste à réaliser l'envoi à la main, et c'est ce que nous allons détailler ici ! Et pour faire les choses bien, on va prendre l'exemple d'une image multi-arch, qui est un poil plus complexe.
L'idée, c'est qu'à la fin de ce tuto, vous puissiez faire quelque chose comme ça, mais avec votre propre domaine !
```bash
docker run --rm -it quentin.dufour.io/garage:v0.8.2 /garage help
```
## Inspecter un peu le registre Docker
Pour requêter le registre docker, on a besoin d'un token même en tant qu'utilisateur anonyme. Sinon on a une 401 :
```
$ curl -i 'https://registry.docker.com/v2/dxflrs/garage/manifests/v0.8.2'
HTTP/1.1 401 Unauthorized
content-type: application/json
docker-distribution-api-version: registry/2.0
www-authenticate: Bearer realm="https://auth.ipv6.docker.com/token",service="registry.docker.io",scope="repository:dxflrs/garage:pull"
date: Thu, 06 Apr 2023 14:55:10 GMT
content-length: 156
strict-transport-security: max-age=31536000
docker-ratelimit-source: 2a01:e0a:28f:5e60::
{"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":[{"Type":"repository","Class":"","Name":"dxflrs/garage","Action":"pull"}]}]}
```
La 401 nous donne toutes les informations pour récupérer notre token :
```bash
curl -vvv 'https://auth.ipv6.docker.com/token?service=registry.docker.io&scope=repository:dxflrs/garage:pull'|jq
```
On peut ensuite construire notre fichier d'en-tête `headers.txt` qui contiendra l'authorisation et l'information qu'on est un client Docker moderne :
```toml
Accept: application/vnd.docker.distribution.manifest.list.v2+json
Authorization: Bearer eyJh...
```
Et puis on peut l'utiliser avec curl pour récupérer le manifest multi arch :
```
curl -H @headers.txt 'https://registry.docker.com/v2/dxflrs/garage/manifests/v0.8.2'
```
On y retrouve alors la déclaration des 4 architectures supportées :
```json
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 428,
"digest": "sha256:236604ea7a441f907d52129d9490fe96b64ef2efd8d4b1c1c50ef8dbae361a8e",
"platform": {
"architecture": "arm64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 428,
"digest": "sha256:73a20980fd232dc7acd51d21df6c7c9964bc7c5fbcfdc098b95cfd221bf67bf6",
"platform": {
"architecture": "amd64",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 428,
"digest": "sha256:47df19e0c6333356e503258e6301c3a91848644667a0b7de4162e6841e89769a",
"platform": {
"architecture": "386",
"os": "linux"
}
},
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 428,
"digest": "sha256:12ec13fe92959249c52c46e97754333267ceeea22978434737978a135b7185ce",
"platform": {
"architecture": "arm",
"os": "linux"
}
}
]
}
```
Duquel ensuite on peut inspecter l'image d'une plateforme précise, ici `arm64` :
```bash
curl -H @headers.txt 'https://registry.docker.com/v2/dxflrs/garage/manifests/sha256:236604ea7a441f907d52129d9490fe96b64ef2efd8d4b1c1c50ef8dbae361a8e'|jq
```
Duquel enfin on récupère les informations de configuration et des différents _layers_ :
```json
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"config": {
"mediaType": "application/vnd.docker.container.image.v1+json",
"size": 459,
"digest": "sha256:258bd4fedb7a0bd5cffd4238777b293d6c5907e5eeaad0174bae3003041c309b"
},
"layers": [
{
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
"size": 19845930,
"digest": "sha256:d2d5e172a714fc48876a6657e7b4b0c3baa4c1ea42e92c687bdb9d86b8dd43c4"
}
]
}
```
En dernier lieu, on peut récupérer les différents blobs déclarés dans le manifest. Pour la configuration, on a
```bash
curl -L -H @/tmp/d.txt 'https://registry.docker.com/v2/dxflrs/garage/blobs/sha256:258bd4fedb7a0bd5cffd4238777b293d6c5907e5eeaad0174bae3003041c309b'|jq
```
Ce qui nous donne les informations sur l'image :
```json
{
"architecture": "arm64",
"created": "2023-03-13T20:27:37.477146404Z",
"history": [
{
"author": "kaniko",
"created": "0001-01-01T00:00:00Z",
"created_by": "COPY result-bin/bin/garage /"
}
],
"os": "linux",
"rootfs": {
"type": "layers",
"diff_ids": [
"sha256:01ff2f334b600faf0e0fc53e7fa19b4f44b1c340cd5f39ec49393b339f6e945f"
]
},
"config": {
"Cmd": [
"/garage",
"server"
],
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"RUST_BACKTRACE=1",
"RUST_LOG=garage=info"
]
}
}
```
Pour le layer, étant une archive tar.gzip, on passe la sortie de curl à tar :
```
$ curl -L -H @/tmp/d.txt 'https://registry.docker.com/v2/dxflrs/garage/blobs/sha256:d2d5e172a714fc48876a6657e7b4b0c3baa4c1ea42e92c687bdb9d86b8dd43c4'|tar -ztvf -
tar: Suppression de « / » au début des noms des membres
drwxr-xr-x 0/0 0 2023-03-13 21:27 /
-r-xr-xr-x 0/0 50846992 2023-03-13 21:27 garage
100 18.9M 100 18.9M 0 0 15.5M 0 0:00:01 0:00:01 --:--:-- 33.1M
```
Et nous voilà arriver au bout de notre exploration de l'API distribution de la Open Container Initiative définie par Docker à l'origine. Par la suite, on va pas s'amuser à récupérer tout ces fichiers à la main, mais demander à skopeo de le faire pour nous. Mais avant tout il faut…
## Déclarer un bucket comme registre
Rien de particulier ici, on va supposer que vous avez un bucket Garage déjà exposé comme site web. Dans ce billet, je vais utiliser directement le bucket de mon site web comme registre docker. Pour que ce dernier soit reconnu comme registre, il est de bon ton de renvoyer un petit OK sur le chemin `/v2/` :
```bash
echo ok > /tmp/v2
aws s3 cp /tmp/v2 s3://quentin.dufour.io/v2/index.html
```
## Récupérer une image depuis le Docker Hub
On va récupérer une image multi-arch de Garage depuis le Docker Hub pour se simplifier la vie dans un premier temps. Mais à la fin, on va build à la main notre image multi-arch depuis Nix, et sans jamais utiliser un daemon docker. Pratique !
Donc pour récupérer notre image multiarch, on va utiliser `skopeo` :
```bash
mkdir -p /tmp/garage-img-multi
skopeo --insecure-policy copy \
--all --format v2s2 --dest-compress \
docker://docker.io/dxflrs/garage:v0.8.2 \
dir:/tmp/garage-img-multi
```
Et voilà, vous avez votre image dans `/tmp/garage-img-multi`. Si vous avez bien suivi le tutoriel, ce sont les mêmes fichiers que vu lors de notre inspection du registre Docker avec curl.
## Copier l'image sur S3
Maintenant on va reconstituer cette image dans notre registre à la main. On copie d'abord le manifest multi-arch :
```bash
cd
```
Ensuite on copie les manifestes des images des différentes architectures (ici `linux/arm`, `linux/arm64`, `linux/amd64, et linux/386` :
```bash
undefined
```
Enfin, on copie les blobs, qui contiennent par exemple les layers de chaque images :
```bash
undefined
```
aa
## Tester notre registre
## Construire l'image nous-même avec Nix