virli/tutorial/dockerfiles/entrypoint.md

187 lines
5.2 KiB
Markdown
Raw Normal View History

2015-10-29 04:45:40 +00:00
\newpage
2021-09-23 00:55:18 +00:00
Le point d'entrée du conteneur
==============================
2015-10-29 04:45:40 +00:00
2021-09-23 00:55:18 +00:00
Le point d'entrée ou l'*entrypoint* correspond à la ligne de commande qui sera
exécutée au lancement du conteneur. Deux paramètres de notre `Dockerfile`
permettent de changer cette ligne de commande : `CMD`{.dockerfile} et
`ENTRYPOINT`{.dockerfile}.
- **`CMD`{.dockerfile}** est la commande par défaut : lorsqu'au moment de
`run`, aucun paramètre n'est passé après le nom de l'image, le contenu du
dernier `CMD`{.dockerfile} rencontré sera utilisé.
- `ENTRYPOINT`{.dockerfile}, s'il est défini, sera réellement exécuté, qu'il y
ait ou non des arguments pour remplacer la ligne de commande. Lorsque des
arguments sont passés ou qu'un `CMD`{.dockerfile}, ceux-ci sont passés en
argument de l'`ENTRYPOINT`{.dockerfile}.
Par exemple, avec le `Dockerfile` suivant, construisant l'image `sample-echo` :
<div lang="en-US">
```dockerfile
FROM ubuntu
CMD ["world"]
ENTRYPOINT ["/bin/echo", "Hello"]
```
</div>
Nous obtenons les résultats suivants :
<div lang="en-US">
```bash
42sh$ docker run sample-echo
Hello world
```
</div>
Dans ce premier cas, il n'y a pas d'argument après le nom de l'image, c'est
donc le contenu de `CMD`{.dockerfile} qui est utilisé ; il est donc passé en
argument à l'`ENTRYPOINT`{.dockerfile}. Concrètement, la première ligne de
commande exécutée est :
<div lang="en-US">
```json
["/bin/echo", "Hello", "world"]
```
</div>
Essayons maintenant avec des arguments :
<div lang="en-US">
```sh
42sh$ docker run sample-echo $USER
Hello neo
```
</div>
Le contenu de la variable `$USER`, interprété par notre shell, est utilisé à la
place de `CMD`{.dockerfile}.
Si l'on a besoin d'exécuter un `ENTRYPOINT`{.dockerfile} différent, il reste la
possibilité de le surcharger au moyen d'un argument :
<div lang="en-US">
```sh
42sh$ docker run --entrypoint /bin/sh sample-echo
01abc345# _
```
</div>
## Personnalisation basique
2015-10-29 04:45:40 +00:00
2018-10-18 05:05:36 +00:00
Afin de faire bénéficier à nos utilisateurs d'une immersion parfaite, nous
2021-09-23 00:55:18 +00:00
allons faire en sorte que notre image puisse être utilisée ainsi :
2015-10-29 04:45:40 +00:00
2017-10-17 06:29:07 +00:00
<div lang="en-US">
```bash
2021-09-23 00:55:18 +00:00
docker run -d -p 80:80 youp0m -bind :80
2015-10-29 04:45:40 +00:00
```
2017-10-17 06:29:07 +00:00
</div>
2015-10-29 04:45:40 +00:00
2018-10-18 05:05:36 +00:00
Plutôt que de laisser l'utilisateur se débrouiller avec le chemin interne dans
2021-09-23 00:55:18 +00:00
lequel il va trouver le bon binaire :
2018-10-18 05:05:36 +00:00
<div lang="en-US">
```bash
2021-09-23 00:55:18 +00:00
docker run -d -p 80:80 youp0m /srv/youp0m -bind :80
2018-10-18 05:05:36 +00:00
```
</div>
Essayez les deux commandes, si vous avez utilisé l'instruction
2021-09-23 00:55:18 +00:00
`CMD`{.dockerfile} dans votre `Dockerfile` jusqu'à présent, vous devriez vous
trouver dans le deuxième cas.
2018-10-18 05:05:36 +00:00
Pour améliorer la situation, définissez
l'[`ENTRYPOINT`{.dockerfile}](https://docs.docker.com/engine/reference/builder/#entrypoint)
2018-10-18 05:05:36 +00:00
de votre image sur le binaire `/srv/youp0m`.
## Point d'entrée avancé
2021-09-23 00:55:18 +00:00
Dans certains cas, il peut être nécessaire au lancement d'un conteneur de
2018-10-18 05:05:36 +00:00
faire un minimum d'étapes d'initialisation avant que le conteneur ne soit
opérationnel (rappelez-vous les options que l'on passait à l'image `mysql` pour
créer un utilisateur et une base).
Notre but, dans cette partie, sera de créer un utilisateur administrateur
2021-09-23 00:55:18 +00:00
(pouvant passer le contrôle d'accès <http://localhost:8080/admin/>) :
2018-10-18 05:05:36 +00:00
<div lang="en-US">
```bash
docker run -i --rm -p 8080:8080 -e YOUP0M_PASSWORD=admin youp0m
2018-10-18 05:05:36 +00:00
```
</div>
### Bases du script
Notre script d'`ENTRYPOINT`{.dockerfile} sera appelé avec en argument, ceux
passés par l'utilisateur après le nom de l'image, ou, à défaut, le contenu de
`CMD`.
2018-10-18 05:05:36 +00:00
C'est donc l'`ENTRYPOINT`{.dockerfile} qui est responsable de la bonne
utilisation de ceux-ci, de leur modification, ...
2018-10-18 05:05:36 +00:00
À la fin d'un script d'`ENTRYPOINT`{.dockerfile}, afin de garder comme premier
processus du conteneur le programme qui nous intéresse, on réalise un
2021-09-23 00:55:18 +00:00
`execve(2)`, sans `fork(2)` :
2018-10-18 05:05:36 +00:00
<div lang="en-US">
```bash
exec /srv/youp0m $@
2018-10-18 05:05:36 +00:00
```
</div>
2021-09-23 00:55:18 +00:00
Dans cet exemple : `exec` est la commande interne à notre shell pour lui
2018-10-18 05:05:36 +00:00
indiquer de remplacer son fil d'exécution par cette commande (sans `exec`, il
va `fork(2)` avant). `$@` est ici pour transmettre tel quel la liste des
arguments passés au script (il s'agit de ceux donnés par l'utilisateur, sur la
ligne de commande du `run`, ou du contenu de `CMD`{.dockerfile} si
l'utilisateur n'a rien précisé).
2018-10-18 05:05:36 +00:00
### Format du fichier `htpasswd`
2021-09-23 00:55:18 +00:00
Le format attendu est celui d'un fichier `htpasswd` typique d'Apache. Nous
pouvons obtenir un fichier valide avec :
2018-10-18 05:05:36 +00:00
<div lang="en-US">
```bash
(
echo -n "$YOUP0M_USERNAME"
echo -n ":"
openssl passwd -crypt "$YOUP0M_PASSWORD"
) > myhtpasswd
2018-10-18 05:05:36 +00:00
```
</div>
2021-09-24 15:12:07 +00:00
Il faut ensuite passer le chemin du fichier créé sur la ligne de commande grâce
à l'option `-htpasswd`.
2018-10-18 05:05:36 +00:00
### Exercice {-}
2018-10-18 05:05:36 +00:00
Écrivez un script d'`ENTRYPOINT`{.dockerfile}, analysant les variables
d'environnement, à la recherche de `YOUP0M_USERNAME` et `YOUP0M_PASSWORD` pour
initialiser le fichier `.htpasswd` qui sera ajouté à la liste des arguments à
passer au service.
2018-10-18 05:05:36 +00:00
2021-09-23 00:55:18 +00:00
Par exemple :
2018-10-18 05:05:36 +00:00
<div lang="en-US">
```
2021-09-23 00:55:18 +00:00
42sh$ docker run -d -p 8081:8081 -e YOUP0M_USERNAME=admin \
-e YOUP0M_PASSWORD=admin youp0m -bind=:8081
2018-10-18 05:05:36 +00:00
42sh$ curl -u admin:badpasswd http://localhost:8081/admin/
You are not allowed to perform this request.
2018-10-18 05:05:36 +00:00
42sh$ curl -u admin:admin http://localhost:8081/admin/
<!DOCTYPE html>
2018-10-18 05:05:36 +00:00
```
</div>