Work on tuto 2
This commit is contained in:
parent
1ca35a1d57
commit
bc179806db
19 changed files with 545 additions and 145 deletions
|
|
@ -8,7 +8,7 @@ que l'on a réussi à faire précédemment en utilisant le `Dockerfile` suivant
|
|||
|
||||
<div lang="en-US">
|
||||
```dockerfile
|
||||
FROM ubuntu:latest
|
||||
FROM ubuntu:jammy
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get install -y nano
|
||||
|
|
@ -21,7 +21,16 @@ est suivie de ses arguments.
|
|||
|
||||
Dans notre exemple, nous utilisons `FROM`{.dockerfile} qui indique une image de
|
||||
départ à utiliser ; `RUN`{.dockerfile} est une commande qui sera exécutée dans
|
||||
le conteneur, dans le but de le construire.
|
||||
le conteneur intermédiaire, dans le but de construire l'image. De la même
|
||||
manière que les `docker container run` de la partie précédente.
|
||||
|
||||
::::: {.warning}
|
||||
|
||||
Vous avez remarqué que la première instruction que l'on utilise est
|
||||
`FROM`. Chaque image construite par un `Dockerfile` doit dépendre d'une autre
|
||||
image. Ici nous avons choisi de partir de l'image `ubuntu`.
|
||||
|
||||
:::::
|
||||
|
||||
Pour lancer la construction de la nouvelle image, créons un nouveau dossier ne
|
||||
contenant que notre fichier `Dockerfile`, plaçons-nous ensuite dedans, puis
|
||||
|
|
@ -33,6 +42,23 @@ docker image build --tag=my_editor .
|
|||
```
|
||||
</div>
|
||||
|
||||
On utilise l'option `--tag` pour donner un nom et un tag à l'image qui
|
||||
résultera de l'exécution de cette construction.
|
||||
|
||||
::::: {.warning}
|
||||
|
||||
#### Attention de ne pas oublier le point à la fin de la commande ! {-}
|
||||
|
||||
Vous n'êtes plus sans savoir que Docker se compose d'un client et d'un
|
||||
serveur. Et c'est la partie serveur qui va s'occuper de construire l'image.
|
||||
|
||||
Le client transmet donc tout le contexte autour du Dockerfile (les fichiers,
|
||||
dossiers, sons-dossiers) à partir du chemin qu'on lui indique en dernier
|
||||
argument. Le point représente donc ici simplement le dossier courant. Tous les
|
||||
fichiers et dossiers présents ici seront transmis au daemon.
|
||||
|
||||
:::::
|
||||
|
||||
Une fois la construction de l'image terminée, nous pouvons la lancer et
|
||||
constater l'existence de notre éditeur favori :
|
||||
|
||||
|
|
@ -85,13 +111,17 @@ RUN service mysqld start && mysql -u root -p toor virli < /db.sql
|
|||
```
|
||||
</div>
|
||||
|
||||
Après le `RUN`{.dockerfile}, MySQL sera de nouveau tué.\
|
||||
Après le `RUN`{.dockerfile}, MySQL sera de nouveau tué, mais la seconde
|
||||
commande aura entre-temps pu ajouter des données.\
|
||||
|
||||
En aucun cas, une commande exécutée par un `RUN`{.dockerfile} se retrouvera en
|
||||
::::: {.warning}
|
||||
|
||||
**En aucun cas, une commande exécutée par un `RUN`{.dockerfile} se retrouvera en
|
||||
cours d'exécution lorsque l'on invoquera un conteneur par `docker container
|
||||
run`. Seul la commande fournie par l'utilisateur ou la commande par défaut de
|
||||
l'image sera exécutée au lancement d'un conteneur.
|
||||
l'image sera exécutée au lancement d'un conteneur.**
|
||||
|
||||
:::::
|
||||
|
||||
### Exposer des ports
|
||||
|
||||
|
|
@ -131,6 +161,51 @@ Dans un autre terminal, lançons un `docker container ls`, pour consulter la col
|
|||
|
||||
Rendez-vous ensuite dans votre navigateur sur <http://localhost:49153/>.
|
||||
|
||||
|
||||
### Copier des fichiers dans l'image
|
||||
|
||||
Une autre action très courante est de vouloir recopier un fichier ou un binaire
|
||||
dans notre image : un fichier de configuration, un produit de compilation, des
|
||||
scripts pour contrôler l'exécution, ...
|
||||
|
||||
On va utiliser pour cela l'instruction `COPY` :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
COPY myconfig.conf /etc/nginx/conf.d/my.conf
|
||||
```
|
||||
</div>
|
||||
|
||||
Cette instruction permet également de copier l'arborescence d'un dossier :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
COPY myconfs/ etc/nginx/conf.d/
|
||||
COPY mywebsite /usr/share/nginx/html/
|
||||
```
|
||||
</div>
|
||||
|
||||
::::: {.warning}
|
||||
|
||||
Le comportement de la copie de dossier est différente du comportement que l'on
|
||||
a l'habitude d'avoir avec `cp -r`. Si la source du `COPY` est un dossier, c'est
|
||||
son contenu qui sera recopié récursivement, habituellement avec `cp` le dossier
|
||||
recopié puis son contenu.
|
||||
|
||||
Pour obtenir le même comportement, il faut bien indiquer une cible
|
||||
incluant le nom du dossier :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
COPY docker-entrypoint.d /docker-entrypoint.d
|
||||
```
|
||||
</div>
|
||||
|
||||
Le dossier sera créé s'il n'existe pas, et le contenu du dossier source ser
|
||||
recopié.
|
||||
|
||||
:::::
|
||||
|
||||
:::::: {.exercice}
|
||||
|
||||
#### À vous de jouer {-}
|
||||
|
|
@ -166,11 +241,76 @@ build`.
|
|||
|
||||
Les couches du cache peuvent être partagées entre plusieurs conteneurs, c'est
|
||||
ainsi que vous pouvez partager facilement une plus grosse partie du système de
|
||||
fichiers (rappelez-vous le principe d'union FS).
|
||||
fichiers.\
|
||||
|
||||
Pour profiter du cache, on va placer de préférence les étapes les plus
|
||||
génériques (qui seraient les plus susceptibles d'apparaître dans d'autres
|
||||
images), en haut du `Dockerfile`.
|
||||
Pour profiter au mieux du cache, on place les instructions qui sont le moins
|
||||
susceptibles de changer en haut du `Dockerfile`, celles qui changent le plus
|
||||
régulièrement à la fin. Ainsi, lorsqu'une reconstruction de l'image sera
|
||||
nécessaire, on gagnera du temps puisque le cache sera utilisé jusqu'à la
|
||||
première instruction changeante. Un `Dockerfile` bien ordonné peu facilement
|
||||
faire gagner de nombreuses minutes à ses utilisateurs.
|
||||
|
||||
::::: {.question}
|
||||
|
||||
#### Quelle place cela prend-t-il sur mon disque ? {-}
|
||||
|
||||
Nous pouvons afficher la taille de chaque image via la commande `docker image
|
||||
ls` :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh$ docker image ls
|
||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
nginx latest 2d389e545974 6 days ago 142MB
|
||||
debian stable 9b4953ae981c 7 days ago 124MB
|
||||
nemunaire/youp0m latest 2c06880e48aa 12 days ago 25MB
|
||||
```
|
||||
</div>
|
||||
|
||||
Si vous avez beaucoup d'images, cela peut paraître beaucoup, mais rappelez-vous
|
||||
que les images sont composées de couches qui sont souvent partagées entre
|
||||
plusieurs conteneurs.
|
||||
|
||||
Si on regarde l'espace vraiment utilisé, il est moindre :
|
||||
|
||||
<div lang="en-US">
|
||||
```
|
||||
42sh$ docker system df
|
||||
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
|
||||
Images 3 3 167MB 0B
|
||||
Containers 0 0 0B 0B
|
||||
Local Volumes 0 0 0B 0B
|
||||
Build Cache 0 0 0B 0B
|
||||
```
|
||||
</div>
|
||||
|
||||
:::::
|
||||
|
||||
Les couches partagées sont un gain non négligeable pour l'espace de stockage !
|
||||
|
||||
Par exemple, prenons le `Dockerfile` suivait :
|
||||
|
||||
<div lang="en-US">
|
||||
```Dockerfile
|
||||
FROM python:3.10
|
||||
COPY build /usr/lib/python/grapher
|
||||
EXPOSE 8080
|
||||
RUN pip install pillow pygal
|
||||
```
|
||||
</div>
|
||||
|
||||
Il y a de fortes chances pour que vous travailliez sur le code de
|
||||
l'application, le dossier `build` sera donc très souvent mis à jour, alors que
|
||||
les dépendances ne bougeront sans doute plus ...
|
||||
|
||||
Avec un tel `Dockerfile`, dès que le dossier `build` sera mis à jour les
|
||||
dépendances seront à nouveau téléchargées, puisque toutes les couches suivant
|
||||
la première qui change sont invalidées.
|
||||
|
||||
Une approche plus optimale serait donc de faire la `COPY` en dernier, car c'est
|
||||
l'opération qui changera le plus souvent. L'idéal étant que 90 % des
|
||||
reconstructions ne refassent que la dernière instruction, toutes les autres
|
||||
devraient être récupérées du cache.
|
||||
|
||||
|
||||
### Métadonnées pures
|
||||
|
|
@ -181,7 +321,7 @@ sous forme de clef/valeur.
|
|||
Une métadonnée courante[^MAINTAINER] est d'indiquer le nom du
|
||||
mainteneur de l'image :
|
||||
|
||||
[^MAINTAINER]: Voir par exemple : <https://github.com/nginxinc/docker-nginx/blob/master/stable/debian/Dockerfile#L8>
|
||||
[^MAINTAINER]: Voir par exemple : <https://github.com/nginxinc/docker-nginx/blob/master/stable/debian/Dockerfile#L8>
|
||||
|
||||
<div lang="en-US">
|
||||
```dockerfile
|
||||
|
|
@ -222,6 +362,9 @@ constatez via un `docker container ls` que le conteneur s'arrête directement,
|
|||
retirez cette option pour voir ce qui ne va pas, ou utilisez la commande
|
||||
`docker container logs`.
|
||||
|
||||
Comme les `LABEL`, ce n'est pas une instruction qui change régulièrement. On la
|
||||
place plutôt au début du `Dockerfile`.
|
||||
|
||||
|
||||
### Construire son application au moment de la construction du conteneur ?
|
||||
|
||||
|
|
@ -257,8 +400,8 @@ CMD ["/hello"]
|
|||
```
|
||||
</div>
|
||||
|
||||
Dans cet exemple, deux conteneurs distincts sont créés : le premier à partir de
|
||||
l'image `gcc`, il contient tout le nécessaire pour compiler notre
|
||||
Dans cet exemple, deux images distinctes sont créées : la première à partir de
|
||||
l'image `gcc`, elle contient tout le nécessaire pour compiler notre
|
||||
`hello.c`. Mais l'image finale (le dernier `FROM`{.dockerfile} de notre
|
||||
`Dockerfile`) est l'image vide, dans laquelle nous recopions simplement le
|
||||
produit de notre compilation.
|
||||
|
|
@ -302,10 +445,23 @@ sélectionnera ainsi avec l'option `--target` l'un ou l'autre en fonction de
|
|||
l'environnement dans lequel on souhaite se déployer.
|
||||
|
||||
|
||||
### Déclarer des volumes
|
||||
|
||||
Tout comme nous pouvons déclarer préalablement dans le `Dockerfile` les ports qui
|
||||
sont normalement exposés par le conteneur, nous pouvons déclarer les
|
||||
volumes. L'instruction pour cela est `VOLUME`.
|
||||
|
||||
Il convient de l'utiliser pour déclarer les emplacements qui vont par défaut
|
||||
contenir des données à faire persister. Ce serait le cas de `/var/lib/mysql`
|
||||
pour les conteneurs MariaDB ou MySQL, `/images/` pour notre image `youp0m` ...
|
||||
|
||||
|
||||
### D'autres instructions ?
|
||||
|
||||
Consultez <https://docs.docker.com/engine/reference/builder/> pour la liste
|
||||
complète des instructions reconnues.
|
||||
Nous avons fait le tour des principales instructions et de leurs différents
|
||||
usages *classiques*. Il existe quelques autres instructions que nous n'avons
|
||||
pas présentées ici, pour aller plus loin, consultez la référence sur :\
|
||||
<https://docs.docker.com/engine/reference/builder/>
|
||||
|
||||
|
||||
::::: {.exercice}
|
||||
|
|
@ -324,11 +480,16 @@ Pour compiler le projet, vous pouvez utiliser dans votre `Dockerfile`
|
|||
|
||||
<div lang="en-US">
|
||||
```dockerfile
|
||||
FROM golang:1.16
|
||||
FROM golang:1.18
|
||||
COPY . /go/src/git.nemunai.re/youp0m
|
||||
WORKDIR /go/src/git.nemunai.re/youp0m
|
||||
RUN go build -tags dev -v
|
||||
```
|
||||
</div>
|
||||
|
||||
Remarquez la puissance de Docker : vous n'avez sans doute pas de compilateur Go
|
||||
installé sur votre machine, et pourtant, en quelques minutes et à partir du
|
||||
seul code source de l'application et d'un `Dockerfile`, vous avez pu compiler sur
|
||||
votre poste le binaire attendu. WOW, non ?
|
||||
|
||||
:::::
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue