Compare commits

...

6 Commits

Author SHA1 Message Date
nemunaire da48300a6c Add some fresh links
continuous-integration/drone/push Build is passing Details
2024-04-15 09:59:17 +02:00
nemunaire c2fb8e9799 Bookify the subject
continuous-integration/drone/push Build is passing Details
2023-01-02 18:25:16 +01:00
nemunaire 394091338f Make OCI part an introduction to subsiduaries sections
continuous-integration/drone/push Build is passing Details
2022-12-17 23:12:17 +01:00
nemunaire 4e58219ba8 devops: Write renovate equivalent docker cmd
continuous-integration/drone/push Build is passing Details
2022-12-17 19:00:04 +01:00
nemunaire a4bf192c12 Remove no longer needed file
continuous-integration/drone/push Build is passing Details
2022-12-17 09:53:16 +01:00
nemunaire 01882ae09e Make link with demo from another repo
continuous-integration/drone/push Build is passing Details
2022-12-17 09:41:46 +01:00
12 changed files with 176 additions and 270 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "demo"]
path = demo
url = git@git.nemunai.re:teach/virli-demo.git

1
demo Submodule

@ -0,0 +1 @@
Subproject commit fff9e75e0a2cfdb5f1d6ad0b2c17110750bcc62b

View File

@ -1,23 +1,38 @@
Utiliser l'API de Docker
========================
Le Docker Engine expose une API REST sur le protocole HTTP. Comme première
tentative, vous pouvez essayer de récupérer des informations générales avec un
simple `curl` :
Le Docker Engine expose une API REST sur le protocole HTTP. Le client `docker`
utilise cette API pour communiquer avec le daemon. C'est aussi cette même API
que `docker-compose` emploie. En fait n'importe quel programme peut en faire
usage, c'est d'ailleurs très simple d'utilisation.
Si vous n'avez jamais communiqué avec une API REST, voici un premier exemple
pour récupérer des informations générales sur le daemon Docker avec un simple
`curl` :
<div lang="en-US">
```bash
curl -s --unix-socket /var/run/docker.sock http://localhost/v1.38/info | jq .
```
</div>
On retrouve un objet JSON contenant des informations similaires à ce que l'on
obtient avec un `docker info`.
On utilise l'option `--unix-socket` de `curl` car on ne se connecte pas
directement à un port, comme c'est le cas habituellement avec le protocole
HTTP. Bien évidemment lorsque le daemon Docker se trouve sur une machine
distante (dans le cas de Docker Desktop sur Windows et Mac), on utilise l'IP et
le port de la machine distance.
Le premier élément dans le chemin de l'URL (`/v1.38/`) correspond à la version
de l'API que l'on souhaite utiliser. Celle-ci change dès que des
fonctionnalités sont ajoutées, à l'occasion d'une nouvelle version. Il n'est
généralement pas nécessaire de mettre à jour cette version dans les programmes
que vous développez car l'API est rétro-compatible : les anciennes versions de
l'API restent accessibles.
La commande que l'on a lancé nous retourne un objet JSON contenant des
informations similaires à ce que l'on obtient avec un `docker info`. L'avantage
est ici de pouvoir effectuer un traitement programmatique de ces informations.
Le premier élément dans le chemin de l'URL correspond à la version de l'API que
l'on souhaite utiliser. Celle-ci change dès que des fonctionnalités sont
ajoutées, à l'occasion d'une nouvelle version. Il n'est généralement pas
nécessaire de mettre à jour cette version dans les programmes que vous
développez car l'API est rétro-compatible : les anciennes versions de l'API
restent accessibles.
Pour réaliser cet exercice, vous pouvez utiliser le langage de votre choix, en
utilisant des outils ou des bibliothèques cohérents avec l'objectif recherché :

View File

@ -5,8 +5,10 @@ Docker) qui pour un conteneur donné :
1. détecte si le conteneur exécute une image disposant d'une mise à jour ;
1. cherche à récupérer la dernière image disponible ;
1. mette à jour le contneur ;
1. dans un conteneur, automatiquement pour toutes les images.
1. met à jour le conteneur.
Enfin, pour simplifier son utilisation régulière, vous conceverez une image de
conteneur minimaliste.
## Étape 1 : Lister les conteneurs
@ -33,7 +35,7 @@ optimistic_meninsky
Écrivez un `Dockerfile` pour conteneuriser ce programme : gérer tant la
construction (s'il y a des étapes de construction) que l'exécution. En
utilisant les bonnes pratiques vues en cours.
utilisant les bonnes pratiques que nous avons pu voir.
### Exemple d'exécution {-}
@ -104,7 +106,7 @@ suivant si (0) aucune mise à jour de l'image n'est disponible, respectivement
</div>
N'hésitez pas à utiliser la sortie d'erreur et la sortie standard pour afficher
des informations pour vous. Celles-ci ne seront pas vérifiées.
des informations de débogage pour vous.
::::: {.warning}
@ -112,10 +114,11 @@ des informations pour vous. Celles-ci ne seront pas vérifiées.
Par *image à jour*, on entend : « aligné par rapport à l'image du
registre ». On ne s'intéresse pas à la date de construction ou de récupération
de l'image, mais uniquement à son identifiant. Si l'image sur laquelle se base
un conteneur en cours d'exécution n'a pas le même identifiant que l'image du
même tag dans le cache d'images, alors on considère que le conteneur doit être
redémarré (même si la construction ou la récupération est antérieure).\
de l'image, mais uniquement à son identifiant. En bref : si l'image sur
laquelle se base un conteneur en cours d'exécution n'a pas le même identifiant
que l'image du même tag dans le cache d'images, alors on considère que le
conteneur doit être redémarré (même si la construction ou la récupération est
antérieure).\
Attention, on souhaite rester sur **le même tag** que celui avec lequel on a
démarré le conteneur. Il ne s'agit pas de trouver un tag plus récent.
@ -135,7 +138,7 @@ plus souvent que les autres tags.
## Étape 3 : Chercher une mise à jour l'image
En ajoutant l'option `--pull`, votre programme va lancer un pull de l'image
En ajoutant l'option `--pull`, votre programme va lancer un *pull* de l'image
avant de faire la vérification.
<div lang="en-US">
@ -154,16 +157,24 @@ avant de faire la vérification.
```
</div>
::::: {.question}
L'image `youp0m` est mise à jour régulièrement. Il y a de forte chance pour
qu'elle ne soit plus à jour si celle dont vous disposez date de plus d'une
semaine. Si vous possédez déjà la dernière version de vos conteneurs,
recherchez une image sur le Docker Hub régulièrement mise à jour pour faire vos
tests.
Attention une fois l'image *pull* par `ctr-updater`, un appel à nouveau à
`ctr-updater` sans `--pull` retourne la mise à jour, car le `pull` précédent
:::::
::::: {.warning}
Une fois l'image *pull* par `ctr-updater`, un nouvel appel à `ctr-updater` sans
`--pull` indiquera qu'une mise à jour est disponible, car le `pull` précédent
aura téléchargé localement l'image.
:::::
::::: {.question}
#### Comment tester lorsqu'on a `pull` toutes ses images ? {-}

View File

@ -1,209 +0,0 @@
\documentclass[$if(fontsize)$$fontsize$,$endif$$if(lang)$$lang$,$endif$$if(papersize)$$papersize$,$endif$$for(classoption)$$classoption$$sep$,$endfor$]{$documentclass$}
\usepackage[T1]{fontenc} % font encoding
\usepackage{euler} % math font (must be loaded before fontspec)
\usepackage{tabularx} % arrays with paragraph-like cells
\usepackage[table]{xcolor} % colors
\usepackage{tikz} % graphics
\usepackage{float} % improve floating figures and tables
\usepackage{titlesec} % must be loaded BEFORE hyperref!
\usepackage{graphicx} % pictures inclusion
\usepackage{listings} % source code environments and inclusion
\usepackage{fancybox} % boxes
\usepackage{textcomp} % more symbols
\usepackage{pifont} % even more symbols (with \ding)
\usepackage{amsmath,amsfonts} % math symbols and environments
\usepackage{calc} % operations on lengths
\usepackage{booktabs} % better tables
\usepackage{multirow} % tabular cells spanning multiple rows
\usepackage{ifthen} % if-then-else construct
\usepackage{enumitem} % list customization
\usepackage{sectsty} % section-title customization
\usepackage{ifxetex,ifluatex}
\usepackage{setspace} % set space amount between lines
\usepackage[cm]{fullpage} % don't waste space around pages
\usepackage{longtable}
\usepackage{fixltx2e} % provides \textsubscript
% use upquote if available, for straight quotes in verbatim environments
\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
\usepackage[utf8]{inputenc}
$if(euro)$
\usepackage{eurosym}
$endif$
\else % if luatex or xelatex
\ifxetex
\usepackage{mathspec}
\usepackage{xltxtra,xunicode}
\else
\usepackage{fontspec}
\fi
\defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase}
\newcommand{\euro}{}
$if(mainfont)$
\setmainfont{$mainfont$}
$endif$
$if(sansfont)$
\setsansfont{$sansfont$}
$endif$
$if(monofont)$
\setmonofont[Mapping=tex-ansi]{$monofont$}
$endif$
$if(mathfont)$
\setmathfont(Digits,Latin,Greek){$mathfont$}
$endif$
\fi
\setmainfont[Ligatures={Common,Rare}]{LinLibertine}
\setsansfont[Ligatures=Common]{LinBiolinum}
\setmonofont{Inconsolata}
\linepenalty=100
\allsectionsfont{\color{black}}
\setlist{itemsep=1pt,topsep=2pt,partopsep=0pt,parsep=0pt,leftmargin=20pt}
\titlespacing{\section}{0pt}{2.5em}{0.66em}
\titlespacing{\subsection}{0pt}{1.5em}{0.5em}
\titlespacing{\subsubsection}{0pt}{1em}{0.4em}
\titlespacing{\paragraph}{0pt}{2ex}{1.2ex}
% use microtype if available
\IfFileExists{microtype.sty}{\usepackage{microtype}}{}
$if(geometry)$
\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry}
$endif$
$if(natbib)$
\usepackage{natbib}
\bibliographystyle{$if(biblio-style)$$biblio-style$$else$plainnat$endif$}
$endif$
$if(biblatex)$
\usepackage{biblatex}
$if(biblio-files)$
\bibliography{$biblio-files$}
$endif$
$endif$
$if(listings)$
\usepackage{listings}
$endif$
$if(lhs)$
\lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small\ttfamily}}{}
$endif$
$if(highlighting-macros)$
$highlighting-macros$
$endif$
$if(verbatim-in-note)$
\usepackage{fancyvrb}
$endif$
$if(tables)$
\usepackage{longtable}
$endif$
$if(graphics)$
\usepackage{graphicx}
% Redefine \includegraphics so that, unless explicit options are
% given, the image width will not exceed the width of the page.
% Images get their normal width if they fit onto the page, but
% are scaled down if they would overflow the margins.
\makeatletter
\def\ScaleIfNeeded{%
\ifdim\Gin@nat@width>\linewidth
\linewidth
\else
\Gin@nat@width
\fi
}
\makeatother
\let\Oldincludegraphics\includegraphics
{%
\catcode`\@=11\relax%
\gdef\includegraphics{\@ifnextchar[{\Oldincludegraphics}{\Oldincludegraphics[width=\ScaleIfNeeded]}}%
}%
$endif$
\ifxetex
\usepackage[setpagesize=false, % page size defined by xetex
unicode=false, % unicode breaks when used with xetex
xetex]{hyperref}
\else
\usepackage[unicode=true]{hyperref}
\fi
\hypersetup{breaklinks=true,
bookmarks=true,
pdfauthor={$author-meta$},
pdftitle={$title-meta$},
colorlinks=true,
citecolor=$if(citecolor)$$citecolor$$else$blue$endif$,
urlcolor=$if(urlcolor)$$urlcolor$$else$blue$endif$,
linkcolor=$if(linkcolor)$$linkcolor$$else$magenta$endif$,
pdfborder={0 0 0}}
\urlstyle{same} % don't use monospace font for urls
$if(links-as-notes)$
% Make links footnotes instead of hotlinks:
\renewcommand{\href}[2]{#2\footnote{\url{#1}}}
$endif$
$if(strikeout)$
\usepackage[normalem]{ulem}
% avoid problems with \sout in headers with hyperref:
\pdfstringdefDisableCommands{\renewcommand{\sout}{}}
$endif$
\setlength{\parskip}{6pt plus 2pt minus 1pt}
\setlength{\emergencystretch}{3em} % prevent overfull lines
$if(numbersections)$
\setcounter{secnumdepth}{5}
$else$
\setcounter{secnumdepth}{0}
$endif$
$if(verbatim-in-note)$
\VerbatimFootnotes % allows verbatim text in footnotes
$endif$
$if(lang)$
\usepackage[$lang$]{babel}
$endif$
$for(header-includes)$
$header-includes$
$endfor$
$if(title)$
\title{$title$}
$endif$
$if(subtitle)$
\subtitle{$subtitle$}
$endif$
\author{$for(author)$$author$$sep$ \and $endfor$}
\date{$date$}
\begin{document}
$if(title)$
\maketitle
$endif$
$for(include-before)$
$include-before$
$endfor$
$if(toc)$
{
\hypersetup{linkcolor=black}
\setcounter{tocdepth}{$toc-depth$}
\tableofcontents
}
$endif$
$body$
$if(natbib)$
$if(biblio-files)$
$if(biblio-title)$
$if(book-class)$
\renewcommand\bibname{$biblio-title$}
$else$
\renewcommand\refname{$biblio-title$}
$endif$
$endif$
\bibliography{$biblio-files$}
$endif$
$endif$
$if(biblatex)$
\printbibliography$if(biblio-title)$[title=$biblio-title$]$endif$
$endif$
$for(include-after)$
$include-after$
$endfor$
\end{document}

View File

@ -86,18 +86,18 @@ on lui attribue de nombreuses vulnérabilités. Vous devriez notamment consulter
* [Anatomy of a user namespaces vulnerability](https://lwn.net/Articles/543273/) :\
<https://lwn.net/Articles/543273/> ;
* <http://marc.info/?l=linux-kernel&m=135543612731939&w=2> ;
* <http://marc.info/?l=linux-kernel&m=135545831607095&w=2>.
* <http://marc.info/?l=linux-kernel&m=135545831607095&w=2> ;
* <https://www.openwall.com/lists/oss-security/2024/04/14/1>.
De nombreux projets ont choisi de ne pas autoriser l'utilisation de cet espace
de noms sans disposer de certaines *capabilities*[^userns-caps].
[^userns-caps]: Sont nécessaires, conjointement : `CAP_SYS_ADMIN`, `CAP_SETUID` et `CAP_SETGID`.
::::: {.question}
De nombreuses distributions ont choisi d'utiliser un paramètre du noyau pour
adapter le comportement.
::::: {.question}
##### Debian et ses dérivées {.unnumbered}
Si vous utilisez Debian ou l'un de ses dérivés, vous devrez autoriser

View File

@ -39,7 +39,7 @@ confiant sur le fait que ce sera toujours le cas (du moins tant que la
distribution assure le support de sa version).
\
Le but du DevOps est donc de retrouver une certaine fluidité entre le
Le but du DevOps[^ABOUTDEVOPS] est donc de retrouver une certaine fluidité entre le
développement et l'exploitation. Il s'agit d'un mouvement qui vise à ce que les
développeurs, sans avoir à gérer au quotidien la maintenance des serveurs de
production, soient davantage impliqués dans les opérations de déploiement. Cela
@ -48,6 +48,9 @@ phase de conception du projet, puis dès les premiers développements, des tests
automatisés sont réalisés directement dans un environnement proche de la
production.
[^ABOUTDEVOPS]: Pour une explication détaillée du mouvement DevOps, je vous recommande :
<https://blog.stephane-robert.info/post/introduction-devops/>
Il en résulte moins de friction entre les deux équipes. Les développeurs étant
par ailleurs amenés à écrire des recettes de déploiement, tels que des
playbooks Ansible ou bien encore des conteneurs Docker.

View File

@ -0,0 +1,20 @@
Exportez dans une variable d'environnement le token d'accès généré qui vous est affiché par Gitea :
<div lang="en-US">
```shell
export RENOVATE_TOKEN=a0b1c2d3e4f5A6B7C8D9
```
</div>
La commande que nous allons utiliser pour lancer Renovatebot est la suivante :
<div lang="en-US">
```shell
docker container run --name renovate --network my_ci_net \
-e RENOVATE_ENDPOINT="http://gitea:3000/api/v1/" RENOVATE_PLATFORM=gitea \
-e RENOVATE_TOKEN -e RENOVATE_GIT_AUTHOR="Renovatebot <renovate@sample>" \
-e RENOVATE_AUTODISCOVER=true -e RENOVATE_LOG_LEVEL=info -d \
renovate/renovate
```
</div>

View File

@ -24,7 +24,7 @@ Lançons enfin Drone avec les deux commandes suivantes :
```shell
docker volume create drone_data
docker container run --name droneci -v drone_data:/data --network my_ci_net
docker container run --name droneci -v drone_data:/data --network my_ci_net \
-p 80:80 -e DRONE_GITEA_CLIENT_ID -e DRONE_GITEA_CLIENT_SECRET \
-e DRONE_GITEA_SERVER=http://gitea:3000 -e DRONE_SERVER_PROTO=http \
-e DRONE_RPC_SECRET -e DRONE_SERVER_HOST=droneci -d \

View File

@ -33,16 +33,61 @@ 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, les dernières versions de `docker` utilisent `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`.
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 suite de couches de systèmes de
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
@ -52,14 +97,13 @@ 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.
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
contenant les modifications, suppressions, ... éventuelles de la couche
représentée.
représentant les modifications ou les suppressions éventuelles de la couche.
La
[configuration](https://github.com/opencontainers/image-spec/blob/master/config.md)
@ -72,14 +116,14 @@ des couches du système de fichiers, ainsi que l'historique de l'image.
### `distribution-spec`
Dernière née de l'organisme, cette spécification fédère la notion de
*registre* : une API REST sur HTTP où l'on peut récupérer des images, mais
aussi en envoyer.
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.
### Pour aller plus loin {-}
\
Si maintenant `docker` fait appel à un programme externe pour lancer
effectivement nos conteneurs, c'est que l'on peut changer cette
implémentation ? la réponse dans l'article :\
<https://ops.tips/blog/run-docker-with-forked-runc/>
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.

View File

@ -1,12 +1,17 @@
\newpage
Registres
=========
Registres d'images
==================
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).
Regardons d'un peu plus près les registres d'images OCI. Ce sont eux qui
distribuent les images OCI et permettent à Docker de récupérer très facilement
de nouveaux services.
Dans les sections à venir, nous allons essayer de récupérer la configuration et
les couches de quelques images courantes (Debian, Ubuntu, `hello-world`, ...) :
dans un premier temps en nous préoccupant simplement de la couche la plus basse
(le système de baase). Puis nous verrons dans le chapitre suivant comment gérer
les autres couches.
## Authentification
@ -29,7 +34,7 @@ lang="en-US">`repository:hello-world:pull`</span>). Ce qui nous donne :
dépôt (*repository*).
<div lang="en-US">
```bash
```
42sh$ curl "https://auth.docker.io/token?service=registry.docker.io&" \
"scope=repository:library/hello-world:pull" | jq .
```
@ -79,9 +84,10 @@ curl -s \
```
</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.
Parmi la liste des *manifests* retournés, nous devons récupérer le `digest`
correspondant au système qui correspond à votre architecture et notre
système. 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*
@ -100,17 +106,17 @@ curl -s \
</div>
Nous voici donc maintenant avec le *manifest* de notre image. Nous pouvons
constater qu'il n'a bien qu'une seule couche, ouf !
constater qu'il n'a bien qu'une seule couche. Ouf, ça va simplifier les
choses !
## 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.
Les deux éléments que l'on cherche maintenant à récupérer vont se trouver dans
le répertoire `blobs` de notre dépôt. Il ne s'agira plus de *manifest*, mais
bien des fichiers définitifs.
Pour récupérer la configuration de l'image :
Récupérons la configuration de l'image comme ceci :
<div lang="en-US">
```bash
@ -120,8 +126,16 @@ curl -s --location \
```
</div>
Remarquez l'usage de l'option `--location` de `curl` : 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. Sans
l'option `--location`, notre `curl` va retourner une redirection vers une autre
adresse, celle qui contient effectivement la configuration. Il en sera de même
pour les fichiers stockant les couches.\
Enfin, armé du `digest` de notre couche, il ne nous reste plus qu'à la demander gentiment :
Enfin d'autre part, armé du `digest` de notre couche, il ne nous reste plus
qu'à la demander gentiment :
<div lang="en-US">
```bash

View File

@ -0,0 +1,4 @@
\newpage
Programmes d'exécution de conteneurs
====================================