virli/tutorial/docker-internals/oci.md
Pierre-Olivier Mercier 394091338f
All checks were successful
continuous-integration/drone/push Build is passing
Make OCI part an introduction to subsiduaries sections
2022-12-17 23:12:17 +01:00

129 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

\newpage
Open Container Initiative
=========================
Formée en juin 2015, l'Open Container Initiative (OCI) a pour but d'établir le
standard commun aux programmes de contenerisation, afin d'éviter une
fragmentation de l'écosystème.
## Spécifications
Trois spécifications ont été écrites :
- [`runtime-spec`](https://github.com/opencontainers/runtime-spec/blob/master/spec.md#platforms): définit les paramètres du démarrage d'un conteneur ;
- [`image-spec`](https://github.com/opencontainers/image-spec/blob/master/spec.md): définit la construction, le transport et la préparation des images ;
- [`distribution-spec`](https://github.com/opencontainers/distribution-spec/blob/master/spec.md): définit la manière dont sont partagées et récupérées les images.
### `runtime-spec`
`runc` est l'implémentation de cette spécification ; elle a été extraite de
`docker`, puis donnée par Docker Inc. à l'OCI.
Pour démarrer un conteneur, la spécification indique qu'il est nécessaire
d'avoir un fichier de configuration `config.json` ainsi qu'un dossier où l'on
peut trouver la racine de notre conteneur.
Le plus gros de la spécification concerne le format de ce fichier de
configuration : il contient en effet l'ensemble des paramètres avec lesquels il
faudra créer le conteneur : tant d'un point de vue isolement (on peut par
exemple choisir de quel *namespace* on souhaite se dissocier, ou le(s)quel(s)
rejoindre), quelles *capabilities* resteront disponibles, quels nouveaux points
de montages, ... Voir [la
suite](https://github.com/opencontainers/runtime-spec/blob/master/config.md).
Aujourd'hui, `docker` utilise `runc` pour l'étape de lancement du conteneur,
après avoir téléchargé l'image puis mis en place l'empilement de couches dans
un répertoire prédéterminé. `docker` ne lance donc plus de conteneur à
proprement parler, il fait seulement en sorte d'atteindre l'état voulu par
cette spécification, avant de passer la main à `runc`.
::::: {.question}
##### Si `docker` fait appel à un programme externe pour lancer effectivement nos conteneurs, c'est que l'on peut changer cette implémentation ? {-}
<!-- https://ops.tips/blog/run-docker-with-forked-runc/ -->
Oui ! Et il n'y a même pas besoin de faire beaucoup d'efforts, car c'est une
possibilité qui est offerte au travers d'une option du daemon Docker. Le
binaire doit simplement avoir la même interface de ligne de commande que `runc`
(les arguments `create` et `start`, nous les verrons plus tard).
Pour l'ajouter, il convient de passer l'option suivante au daemon Docker lors
de son lancement (dans le fichier de service `systemd`, ou d'`init`) :
<div lang="en-US">
```sh
/usr/bin/dockerd [...] --add-runtime=my-runtime=/usr/local/bin/my-runtime
```
</div>
Ou bien en passant par le fichier de configuration `/etc/docker/daemon.json` :
<div lang="en-US">
```json
{
"runtimes": {
"my-runtime": {
"path": "/usr/local/bin/my-runtime",
"runtimeArgs": []
}
}
}
```
</div>
Pour chaque nouveau conteneur lancé, il sera alors possible de préciser le *runtime* à utiliser grâce à l'option `--runtime` :
<div lang="en-US">
```sh
docker container run [...] --runtime=my-runtime nginx:alpine
```
</div>
:::::
### `image-spec`
Une image OCI est composée d'un manifest, d'une série de couches de systèmes de
fichiers, d'une configuration ainsi que d'un index d'image optionnel.
Le
[manifest](https://github.com/opencontainers/image-spec/blob/master/manifest.md)
est toujours le point d'entrée d'une image : il référence l'emplacement où
trouver les différents éléments : configuration et couches. Lorsqu'une même
image a des variations en fonction de l'architecture du processeur, du système
d'exploitation, ... dans ce cas [l'index
d'image](https://github.com/opencontainers/image-spec/blob/master/image-index.md)
est utilisé pour sélectionner le bon manifest correspondant au système.
Le format des [couches de système de
fichiers](https://github.com/opencontainers/image-spec/blob/master/layer.md)
sont spécifiées : il est nécessaire de passer par des formats standards (comme
les tarballs), contenant éventuellement des fichiers et dossiers spéciaux
représentant les modifications ou les suppressions éventuelles de la couche.
La
[configuration](https://github.com/opencontainers/image-spec/blob/master/config.md)
contient l'ensemble des métadonnées qui serviront par exemple à construire le
`config.json` attendu par `runc` lorsqu'il faudra lancer l'image (c'est
là-dedans que finissent toutes les métadonnées que l'on inscrit dans nos
`Dockerfile` : `CMD`, `VOLUME`, `PORT`, ...). On y retrouve également l'ordre
des couches du système de fichiers, ainsi que l'historique de l'image.
### `distribution-spec`
Enfin, cette spécification fédère la notion de *registre* et la manière dont
les clients vont interagir avec : il s'agit d'une API REST au dessus du
protocole HTTP.
Cela permet de récupérer des images, mais aussi d'en envoyer, en gérant
éventuellement la manière de s'authentifier.
\
Nous allons voir plus en détails, dans les chapitres suivantes, ce que l'on
peut tirer de ces spécifications, en décortiquant des usages précis.