virli/tutorial/dockerfiles/entrypoint.md

187 lines
5.2 KiB
Markdown
Raw 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
Le point d'entrée du conteneur
==============================
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
Afin de faire bénéficier à nos utilisateurs d'une immersion parfaite, nous
allons faire en sorte que notre image puisse être utilisée ainsi :
<div lang="en-US">
```bash
docker run -d -p 80:80 youp0m -bind :80
```
</div>
Plutôt que de laisser l'utilisateur se débrouiller avec le chemin interne dans
lequel il va trouver le bon binaire :
<div lang="en-US">
```bash
docker run -d -p 80:80 youp0m /srv/youp0m -bind :80
```
</div>
Essayez les deux commandes, si vous avez utilisé l'instruction
`CMD`{.dockerfile} dans votre `Dockerfile` jusqu'à présent, vous devriez vous
trouver dans le deuxième cas.
Pour améliorer la situation, définissez
l'[`ENTRYPOINT`{.dockerfile}](https://docs.docker.com/engine/reference/builder/#entrypoint)
de votre image sur le binaire `/srv/youp0m`.
## Point d'entrée avancé
Dans certains cas, il peut être nécessaire au lancement d'un conteneur de
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
(pouvant passer le contrôle d'accès <http://localhost:8080/admin/>) :
<div lang="en-US">
```bash
docker run -i --rm -p 8080:8080 -e YOUP0M_PASSWORD=admin youp0m
```
</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`.
C'est donc l'`ENTRYPOINT`{.dockerfile} qui est responsable de la bonne
utilisation de ceux-ci, de leur modification, ...
À 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
`execve(2)`, sans `fork(2)` :
<div lang="en-US">
```bash
exec /srv/youp0m $@
```
</div>
Dans cet exemple : `exec` est la commande interne à notre shell pour lui
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é).
### Format du fichier `htpasswd`
Le format attendu est celui d'un fichier `htpasswd` typique d'Apache. Nous
pouvons obtenir un fichier valide avec :
<div lang="en-US">
```bash
(
echo -n "$YOUP0M_USERNAME"
echo -n ":"
openssl passwd -crypt "$YOUP0M_PASSWORD"
) > myhtpasswd
```
</div>
Il faut ensuite passer le chemin du fichier créé sur la ligne de commande grâce
à l'option `-htpasswd`.
### Exercice {-}
É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.
Par exemple :
<div lang="en-US">
```
42sh$ docker run -d -p 8081:8081 -e YOUP0M_USERNAME=admin \
-e YOUP0M_PASSWORD=admin youp0m -bind=:8081
42sh$ curl -u admin:badpasswd http://localhost:8081/admin/
You are not allowed to perform this request.
42sh$ curl -u admin:admin http://localhost:8081/admin/
<!DOCTYPE html>
```
</div>