2022-02-24 19:43:43 +00:00
|
|
|
|
Ma première image ... par `Dockerfile`
|
2021-09-23 00:55:18 +00:00
|
|
|
|
--------------------------------------
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-04 23:42:56 +00:00
|
|
|
|
Pour construire une image, nous ne sommes pas obligés de passer par une série
|
2018-10-18 05:05:36 +00:00
|
|
|
|
de *commits*. Docker dispose d'un mécanisme permettant d'automatiser la
|
|
|
|
|
construction de nouvelles images. Nous pouvons arriver au même résultat que ce
|
2021-09-23 00:55:18 +00:00
|
|
|
|
que l'on a réussi à faire précédemment en utilisant le `Dockerfile` suivant :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
2022-09-20 04:02:53 +00:00
|
|
|
|
FROM ubuntu:jammy
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2018-11-16 01:38:41 +00:00
|
|
|
|
RUN apt-get update
|
|
|
|
|
RUN apt-get install -y nano
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
La syntaxe d'un `Dockerfile` est simple : le premier mot de chaque ligne est
|
2015-10-22 03:25:20 +00:00
|
|
|
|
l'intitulé d'une instruction (que l'on écrit généralement en majuscule), elle
|
|
|
|
|
est suivie de ses arguments.
|
|
|
|
|
|
2018-11-16 01:38:41 +00:00
|
|
|
|
Dans notre exemple, nous utilisons `FROM`{.dockerfile} qui indique une image de
|
2022-02-24 19:43:43 +00:00
|
|
|
|
départ à utiliser ; `RUN`{.dockerfile} est une commande qui sera exécutée dans
|
2022-09-20 04:02:53 +00:00
|
|
|
|
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`.
|
|
|
|
|
|
|
|
|
|
:::::
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2018-10-18 05:05:36 +00:00
|
|
|
|
Pour lancer la construction de la nouvelle image, créons un nouveau dossier ne
|
2021-09-24 15:12:07 +00:00
|
|
|
|
contenant que notre fichier `Dockerfile`, plaçons-nous ensuite dedans, puis
|
2021-09-23 00:55:18 +00:00
|
|
|
|
lançons la commande `build` :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```bash
|
|
|
|
|
docker image build --tag=my_editor .
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
:::::
|
|
|
|
|
|
2018-10-18 05:05:36 +00:00
|
|
|
|
Une fois la construction de l'image terminée, nous pouvons la lancer et
|
2021-09-23 00:55:18 +00:00
|
|
|
|
constater l'existence de notre éditeur favori :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```bash
|
|
|
|
|
docker container run -it my_editor /bin/bash
|
2020-09-14 13:46:13 +00:00
|
|
|
|
(in_cntr)# nano
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
### `RUN` dans le `Dockerfile`
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-16 20:59:22 +00:00
|
|
|
|
Dans un `Dockerfile`, chaque ligne est exécutée indépendamment des autres et
|
2020-10-28 22:16:34 +00:00
|
|
|
|
correspondra à une nouvelle couche de notre image. Exactement comme on a
|
2021-09-24 15:12:07 +00:00
|
|
|
|
réalisé le script à la fin de la partie précédente.
|
2016-09-08 01:44:20 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
Cela signifie que l'exemple suivant **ne fonctionne pas** :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
|
|
|
|
COPY db.sql /db.sql
|
|
|
|
|
RUN service mysqld start
|
|
|
|
|
RUN mysql -u root -p toor virli < /db.sql
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2018-10-18 05:05:36 +00:00
|
|
|
|
Cet exemple ne fonctionne pas car le serveur MySQL est bien lancé dans le
|
2021-09-23 00:55:18 +00:00
|
|
|
|
premier `RUN`{.dockerfile}, mais il se trouve brutalement arrêté dès lors que
|
2018-11-16 01:38:41 +00:00
|
|
|
|
la commande `service` se termine. En fait, à chaque instruction, Docker réalise
|
2020-09-14 13:46:13 +00:00
|
|
|
|
automatiquement l'équivalent un `docker run` suivi d'un `commit`. Et vous
|
|
|
|
|
pouvez constater par vous-même que, en créant l'image `tinysql` à partir d'un
|
2021-09-23 00:55:18 +00:00
|
|
|
|
simple `apt install mysql` :
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```bash
|
|
|
|
|
docker container run tinysql service mysqld start
|
2018-10-18 05:05:36 +00:00
|
|
|
|
```
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
rend la main directement, sans laisser de `mysqld` dans l'arborescence de
|
2021-09-24 15:12:07 +00:00
|
|
|
|
processus.\
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
Pour avoir le résultat escompté, il faut exécuter les commandes ensemble :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
|
|
|
|
COPY db.sql /db.sql
|
|
|
|
|
RUN service mysqld start && mysql -u root -p toor virli < /db.sql
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
Après le `RUN`{.dockerfile}, MySQL sera de nouveau tué, mais la seconde
|
|
|
|
|
commande aura entre-temps pu ajouter des données.\
|
|
|
|
|
|
|
|
|
|
::::: {.warning}
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
**En aucun cas, une commande exécutée par un `RUN`{.dockerfile} se retrouvera en
|
2018-11-16 01:38:41 +00:00
|
|
|
|
cours d'exécution lorsque l'on invoquera un conteneur par `docker container
|
2018-10-18 05:05:36 +00:00
|
|
|
|
run`. Seul la commande fournie par l'utilisateur ou la commande par défaut de
|
2022-09-20 04:02:53 +00:00
|
|
|
|
l'image sera exécutée au lancement d'un conteneur.**
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
:::::
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
### Exposer des ports
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
Construisons maintenant un conteneur avec un service web :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
|
|
|
|
FROM my_editor
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2018-11-16 01:38:41 +00:00
|
|
|
|
RUN apt-get update
|
|
|
|
|
RUN apt-get install -y nginx
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2018-11-16 01:38:41 +00:00
|
|
|
|
EXPOSE 80
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2020-09-14 13:46:13 +00:00
|
|
|
|
L'instruction `EXPOSE`{.dockerfile} sera traitée plus tard par le client Docker
|
|
|
|
|
(équivalent à l'argument `--expose`). Il s'agit d'une métadonnée qui sera
|
2021-09-24 15:12:07 +00:00
|
|
|
|
attachée à l'image (et à toutes ses images filles). Elle ne crée d'ailleurs pas
|
|
|
|
|
de couche supplémentaire dans notre image.\
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
En précisant tous les ports qu'expose une image dans ses métadonnées, ces
|
|
|
|
|
ports seront automatiquement exposés en utilisant l'option `-P` du `run` : cela
|
2018-10-18 05:05:36 +00:00
|
|
|
|
assigne une redirection de port aléatoire sur la machine hôte vers votre
|
2021-09-23 00:55:18 +00:00
|
|
|
|
conteneur :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2018-11-16 01:38:41 +00:00
|
|
|
|
42sh$ docker image build --tag=my_webserver .
|
|
|
|
|
42sh$ docker container run -it -P my_webserver /bin/bash
|
|
|
|
|
(cntnr)# service nginx start
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2021-09-24 15:12:07 +00:00
|
|
|
|
Dans un autre terminal, lançons un `docker container ls`, pour consulter la colonne
|
|
|
|
|
*PORTS* afin de connaître le port choisi par Docker pour effectuer la redirection.
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
|
|
|
|
Rendez-vous ensuite dans votre navigateur sur <http://localhost:49153/>.
|
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
|
|
|
|
|
### 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é.
|
|
|
|
|
|
|
|
|
|
:::::
|
|
|
|
|
|
2022-04-08 20:39:14 +00:00
|
|
|
|
:::::: {.exercice}
|
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
#### À vous de jouer {-}
|
|
|
|
|
|
|
|
|
|
Utilisez l'instruction `COPY`{.dockerfile} pour afficher votre propre
|
2022-02-24 19:43:43 +00:00
|
|
|
|
`index.html` remplaçant celui installé de base par `nginx`. <!--Si vous manquez
|
2018-10-18 05:05:36 +00:00
|
|
|
|
d'inspiration, utilisez [cette page de compte à
|
2022-02-24 19:43:43 +00:00
|
|
|
|
rebours](https://virli.nemunai.re/countdown.html).-->
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
2022-04-08 20:39:14 +00:00
|
|
|
|
:::::
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
### Les caches
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
Nous avons vu que chaque instruction de notre `Dockerfile` est exécutée dans un
|
|
|
|
|
conteneur, qui génère une image intermédiaire. Cette image intermédiaire sert
|
|
|
|
|
ensuite d'image de base pour le conteneur qui sera lancé avec l'instruction
|
|
|
|
|
suivante.
|
|
|
|
|
|
|
|
|
|
Lorsqu'on lance la reconstruction du même `Dockerfile`, les images
|
|
|
|
|
intermédiaires sont réutilisées, comme un cache d'instructions. Cela permet de
|
2022-05-12 00:46:31 +00:00
|
|
|
|
gagner du temps sur les étapes qui n'ont pas changé. Ainsi, lorsque vous
|
2018-10-18 05:05:36 +00:00
|
|
|
|
modifiez une instruction dans votre `Dockerfile`, les instructions précédentes
|
|
|
|
|
ne sont pas réexécutées mais sont ressorties du cache.
|
|
|
|
|
|
|
|
|
|
Le cache se base principalement sur le contenu de chaque instruction du
|
|
|
|
|
`Dockerfile` (pour les `COPY` et `ADD`, il va aussi regarder la date de
|
|
|
|
|
dernière modification de fichier à copier ou à ajouter). Donc tant qu'une
|
|
|
|
|
instruction n'est pas modifiée dans le `Dockerfile`, le cache sera utilisé.
|
|
|
|
|
|
|
|
|
|
Il est possible de ne pas utiliser le cache et de relancer toutes les étapes du
|
|
|
|
|
`Dockerfile` en ajoutant l'option `--no-cache` au moment du `docker image
|
|
|
|
|
build`.
|
|
|
|
|
|
2022-05-12 00:46:31 +00:00
|
|
|
|
Les couches du cache peuvent être partagées entre plusieurs conteneurs, c'est
|
2018-10-18 05:05:36 +00:00
|
|
|
|
ainsi que vous pouvez partager facilement une plus grosse partie du système de
|
2022-09-20 04:02:53 +00:00
|
|
|
|
fichiers.\
|
|
|
|
|
|
|
|
|
|
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>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
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.
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
### Métadonnées pures
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
2018-11-16 01:38:41 +00:00
|
|
|
|
L'instruction `LABEL`{.dockerfile} permet d'ajouter une métadonnée à une image,
|
|
|
|
|
sous forme de clef/valeur.
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
2022-02-24 19:43:43 +00:00
|
|
|
|
Une métadonnée courante[^MAINTAINER] est d'indiquer le nom du
|
|
|
|
|
mainteneur de l'image :
|
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
[^MAINTAINER]: Voir par exemple : <https://github.com/nginxinc/docker-nginx/blob/master/stable/debian/Dockerfile#L8>
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
|
|
|
|
LABEL maintainer="Pierre-Olivier Mercier <nemunaire@nemunai.re>"
|
2018-10-18 05:05:36 +00:00
|
|
|
|
```
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
Dans notre `Dockerfile`, indiquez juste après l'image de base, vos noms,
|
2018-11-16 01:38:41 +00:00
|
|
|
|
prénoms et mails de contact avec l'instruction `LABEL maintainer`{.dockerfile},
|
|
|
|
|
pour indiquer que c'est vous qui maintenez cette image, si des utilisateurs ont
|
2018-10-18 05:05:36 +00:00
|
|
|
|
besoin de vous avertir pour le mettre à jour ou s'ils rencontrent des
|
|
|
|
|
difficultés par exemple.
|
|
|
|
|
|
2022-05-12 00:46:31 +00:00
|
|
|
|
On le place dès le début, car comme c'est une information qui n'est pas amenée
|
2018-10-18 05:05:36 +00:00
|
|
|
|
à changer, elle sera toujours retrouvée en cache.
|
|
|
|
|
|
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
### Commande par défaut
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2018-11-16 01:38:41 +00:00
|
|
|
|
Vous pouvez placer dans un `Dockerfile` une instruction `CMD`{.dockerfile} qui
|
2021-09-23 00:55:18 +00:00
|
|
|
|
sera exécutée si aucune commande n'est passée lors du `run`, par exemple :
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
|
|
|
|
CMD nginx -g "daemon off;"
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-17 06:29:07 +00:00
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```bash
|
|
|
|
|
42sh$ docker image build --tag=my_nginx .
|
|
|
|
|
42sh$ docker container run -d -P my_nginx
|
2015-10-22 03:25:20 +00:00
|
|
|
|
```
|
2017-10-17 06:29:07 +00:00
|
|
|
|
</div>
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2017-10-16 20:59:22 +00:00
|
|
|
|
L'option `-d` passée au `run` lance le conteneur en tâche de fond. Si vous
|
|
|
|
|
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`.
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
Comme les `LABEL`, ce n'est pas une instruction qui change régulièrement. On la
|
|
|
|
|
place plutôt au début du `Dockerfile`.
|
|
|
|
|
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2022-02-24 19:43:43 +00:00
|
|
|
|
### Construire son application au moment de la construction du conteneur ?
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
Comment faire lorsque l'on a besoin de compiler une application avant de
|
2022-02-24 19:43:43 +00:00
|
|
|
|
l'intégrer dans le conteneur ?
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
On peut vouloir lancer la compilation sur notre machine, mais cela ne sera pas
|
|
|
|
|
très reproductible et cela aura nécessité d'installer le compilateur et les
|
|
|
|
|
outils liés au langage que l'on souhaite compiler. Peut-être que plusieurs
|
2022-02-24 19:43:43 +00:00
|
|
|
|
versions de ces outils existent, laquelle choisir ? ... Ok c'est trop
|
2018-10-18 05:05:36 +00:00
|
|
|
|
compliqué.
|
|
|
|
|
|
|
|
|
|
D'un autre côté, si l'on fait cela dans un conteneur, celui-ci contiendra dans
|
2021-09-23 00:55:18 +00:00
|
|
|
|
ses couches des données inutiles à l'exécution : les sources, les produits
|
2018-10-18 05:05:36 +00:00
|
|
|
|
intermédiaires de compilation, le compilateur, n'ont rien à faire dans les
|
|
|
|
|
couches de notre image.
|
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
Le meilleur des deux mondes se trouve dans les *Multi-stage builds* : au sein
|
2018-10-18 05:05:36 +00:00
|
|
|
|
du même `Dockerfile`, on va réaliser les opérations de préparation dans un ou
|
|
|
|
|
plusieurs conteneurs, avant d'agréger le contenu compilé au sein du conteneur
|
2021-09-23 00:55:18 +00:00
|
|
|
|
final :
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
|
|
|
|
FROM gcc:4.9
|
|
|
|
|
COPY . /usr/src/myapp
|
|
|
|
|
WORKDIR /usr/src/myapp
|
|
|
|
|
RUN gcc -static -static-libgcc -o hello hello.c
|
|
|
|
|
|
|
|
|
|
FROM scratch
|
|
|
|
|
COPY --from=0 /usr/src/myapp/hello /hello
|
|
|
|
|
CMD ["/hello"]
|
2018-10-18 05:05:36 +00:00
|
|
|
|
```
|
|
|
|
|
</div>
|
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
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
|
2018-11-16 01:38:41 +00:00
|
|
|
|
`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.
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
L'image ainsi générée est minime, car elle ne contient rien d'autre que le
|
|
|
|
|
strict nécessaire pour s'exécuter.
|
|
|
|
|
|
2022-04-09 00:50:14 +00:00
|
|
|
|
#### Étapes nommées
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
Nous avons utilisé `--from=0` pour désigner la première image de notre
|
2021-09-23 00:55:18 +00:00
|
|
|
|
`Dockerfile`. Lorsque l'on réalise des montages plus complexes, on peut vouloir
|
2018-10-18 05:05:36 +00:00
|
|
|
|
donner des noms à chaque image, plutôt que de devoir jongler avec les
|
2021-09-23 00:55:18 +00:00
|
|
|
|
numéros. Dans ce cas, on indiquera :
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
<div lang="en-US">
|
2018-11-16 01:38:41 +00:00
|
|
|
|
```dockerfile
|
|
|
|
|
FROM gcc:4.9 as builder
|
|
|
|
|
COPY . /usr/src/myapp
|
|
|
|
|
WORKDIR /usr/src/myapp
|
|
|
|
|
RUN gcc -static -static-libgcc -o hello hello.c
|
|
|
|
|
|
|
|
|
|
FROM scratch
|
|
|
|
|
COPY --from=builder /usr/src/myapp/hello /hello
|
|
|
|
|
CMD ["/hello"]
|
2018-10-18 05:05:36 +00:00
|
|
|
|
```
|
|
|
|
|
</div>
|
|
|
|
|
|
2021-09-23 00:55:18 +00:00
|
|
|
|
Par défaut la dernière étape du `Dockerfile` est retenue comme étant l'image que
|
2018-10-18 05:05:36 +00:00
|
|
|
|
l'on souhaite `tagger`, mais il est possible de préciser quelle image
|
2021-09-23 00:55:18 +00:00
|
|
|
|
spécifiquement on souhaite construire avec l'option `--target` :
|
2018-10-18 05:05:36 +00:00
|
|
|
|
|
|
|
|
|
<div lang="en-US">
|
|
|
|
|
```
|
2018-11-16 01:38:41 +00:00
|
|
|
|
42sh$ docker build --target builder -t hello-builder .
|
2018-10-18 05:05:36 +00:00
|
|
|
|
```
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
Cela peut être particulièrement utile si l'on dispose d'une image de debug,
|
|
|
|
|
incluant tous les symboles, et une image de production, plus propre. On
|
|
|
|
|
sélectionnera ainsi avec l'option `--target` l'un ou l'autre en fonction de
|
|
|
|
|
l'environnement dans lequel on souhaite se déployer.
|
|
|
|
|
|
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
### 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` ...
|
|
|
|
|
|
|
|
|
|
|
2022-02-24 19:43:43 +00:00
|
|
|
|
### D'autres instructions ?
|
2015-10-22 03:25:20 +00:00
|
|
|
|
|
2022-09-20 04:02:53 +00:00
|
|
|
|
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/>
|