203 lines
6.5 KiB
Markdown
203 lines
6.5 KiB
Markdown
Mon premier webservice
|
||
----------------------
|
||
|
||
C'est parti, nous allons déployer notre premier service !
|
||
|
||
Il s'agit d'un service montrant une image aléatoire à chaque chargement de
|
||
page :\
|
||
<https://you.p0m.fr/>.
|
||
|
||
|
||
Nous pouvons télécharger et lancer le service grâce à :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
docker container run -i registry.nemunai.re/youp0m
|
||
```
|
||
</div>
|
||
|
||
Cette fois-ci, ce n'est pas un shell que nous obtenons[^defaultcmd] : il semblerait que le
|
||
service soit lancé et écoute sur le port 8080. Est-ce le cas ?
|
||
|
||
<http://localhost:8080>
|
||
|
||
[^defaultcmd]: Chaque conteneur dispose d'une commande par défaut : les images
|
||
de base telles que les distributions vont lancer un shell, tandis que les
|
||
conteneurs de service vont lancer leur service directement.
|
||
|
||
Non ! Car le service est contenerisé ! Il s'exécute dans son coin, sans
|
||
interférer avec son hôte.
|
||
|
||
![L'hôte n'arrive pas à joindre le port 8080](not-published-ports.png "L'hôte n'arrive pas à joindre le port 8080"){ width=70% }
|
||
|
||
|
||
### Redirection de ports
|
||
|
||
Nous pouvons rediriger le port avec l'argument <span lang="en-US">`--publish dst_host:src_cntr`</span> :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
docker container run --publish 8080:8080 registry.nemunai.re/youp0m
|
||
```
|
||
</div>
|
||
|
||
Cet argument va faire effectuer à Docker une étape supplémentaire lorsqu'il
|
||
démarerra le conteneur : il va devoir mettre en place une redirection du port
|
||
de notre système local (8080) vers le port 8080 du conteneur.
|
||
|
||
![Le port 8080 est redirigé vers le conteneur](published-ports.png "Le port 8080 est redirigé vers le conteneur"){ width=70% }
|
||
|
||
::::: {.question}
|
||
|
||
#### Peut-on démarrer plusieurs conteurs utilisant le même port de notre système local ? {-}
|
||
|
||
Si l'on essai de lancer deux fois la commande de notre dernier `run`, nous
|
||
obtenons l'erreur suivante :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
42sh$ docker container run --publish 8080:8080 registry.nemunai.re/youp0m
|
||
docker: Error response from daemon: driver failed programming external connectivity on endpoint: Bind for 0.0.0.0:8080 failed: port is already allocated.
|
||
```
|
||
</div>
|
||
|
||
En effet, un port de la pile réseau de notre système ne peut être associé qu'à
|
||
un seul et unique processus. Puisqu'il a déjà été attribué à notre précédent
|
||
conteneur, il ne peut pas être à nouveau alloué.
|
||
|
||
En revanche, nous pouvons tout-à-fait lancer deux conteneurs `youp0m` sans
|
||
rediriger leur port 8080, car le conteneur ne partage pas la pile réseau de
|
||
l'hôte. Une nouvelle pile réseau est créée pour chaque conteneur.
|
||
|
||
:::::
|
||
|
||
Cette fois, nous pouvons bien accéder au service depuis notre navigateur.
|
||
|
||
Pour le moment, le service ne dispose d'aucune image à afficher, vous pouvez
|
||
utiliser cette syntaxe pour ajouter une image :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
base64 monimage.jpg | \
|
||
curl --data @- http://localhost:8080/api/images/monimage
|
||
```
|
||
</div>
|
||
|
||
Si vous n'êtes pas particulièrement inspiré, vous pouvez ajouter ces images :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
for IMG in lynx4 otters DNcrZ6u raccoons; do
|
||
wget -O- https://you.p0m.fr/images/$IMG | base64 | \
|
||
curl --data @- http://localhost:8080/api/images/$IMG
|
||
done
|
||
```
|
||
</div>
|
||
|
||
|
||
### Prêt pour la production ?
|
||
|
||
Avec l'option `-i`, nous pouvons encore transmettre les signaux de terminaison
|
||
au conteneur. C'est pratique lorsque l'on développe, mais en production, notre
|
||
service ne s'exécutera pas dans notre terminal !
|
||
|
||
On utilise l'option `-d` pour lancer le conteneur en tâche de fond :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
docker container run -d -p 8080:8080 registry.nemunai.re/youp0m
|
||
```
|
||
</div>
|
||
|
||
::::: {.question}
|
||
|
||
#### Où est la sortie standard ? {-}
|
||
|
||
À partir de l'identifiant renvoyé par cette commande (que l'on peut également
|
||
obtenir avec un `docker container ls`), nous pouvons consulter les logs du
|
||
service (en fait, les sorties standard et d'erreur) :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
docker container logs 0a1b2c3d4e
|
||
```
|
||
</div>
|
||
|
||
:::::
|
||
|
||
|
||
### Une autre instance ?
|
||
|
||
Maintenant que nous avons un clone de <https://you.p0m.fr/>, nous voulons
|
||
absolument un clone de <https://food.p0m.fr/> !
|
||
|
||
Il s'agit du même service, mais ce ne sont pas les mêmes images.
|
||
|
||
On ne peut pas utiliser le même port sur la machine hôte, mais pour le reste,
|
||
il s'agit des mêmes options :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
docker container run -d -p 8081:8080 registry.nemunai.re/youp0m
|
||
```
|
||
</div>
|
||
|
||
Voyons le résultat : <http://localhost:8081>
|
||
|
||
Nous avons réussi à lancer deux conteneurs à partir de la même image, et on
|
||
voit bien que ceux-ci ne partagent pas leur système de fichiers : notre
|
||
nouvelle instance est encore immaculée.
|
||
|
||
|
||
### Paramètres de lancement
|
||
|
||
`youp0m` dispose d'une interface d'administration minimaliste, pour modérer les
|
||
images soumises. Celle-ci est accessible par mot de passe (ou est désactivée si
|
||
aucun identifiant n'est trouvé). L'aide du programme indique que cela est géré
|
||
par l'argument `-htpasswd`, mais encore faut-il pouvoir recopier un fichier
|
||
créé à l'extérieur du conteneur...
|
||
|
||
Outre les arguments que l'on peut passer au premier processus du conteneur, la
|
||
plupart des images peuvent adapter leur comportement en fonction de variables
|
||
d'environnement que l'on passe en paramètre.
|
||
|
||
Cette bonne pratique est recommandée par
|
||
[`12factor.net`](https://12factor.net/), qui détaille les raisons qui devraient
|
||
pousser les développeurs à privilégier les variables d'environnements aux
|
||
arguments sur la ligne de commande.
|
||
|
||
Il se trouve que les conteneurs `youp0m` peuvent créer le fichier `htpasswd`,
|
||
s'ils sont démarrés avec les variables d'environnement :
|
||
|
||
- `YOUP0M_USERNAME` : nom d'utilisateur pour l'administrateur (par défaut admin) ;
|
||
- `YOUP0M_PASSWORD` : mot de passe de l'utilisateur.
|
||
|
||
Pour ajouter une variable d'environnement, cela se passe dans la commande
|
||
`run`, en ajoutant une ou plusieurs options `-e` :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
docker container run -e YOUP0M_PASSWORD=foobar -p 8080:8080 registry.nemunai.re/youp0m
|
||
```
|
||
</div>
|
||
|
||
Une fois lancé, ce conteneur exposera une interface d'administration à cette
|
||
adresse :\
|
||
<http://localhost:8080/admin/>.
|
||
|
||
|
||
### Arrêt des conteneurs et persistance des données
|
||
|
||
Lorsque l'on souhaite stopper un conteneur lancé en tâche de fond, on utilise
|
||
son identifiant dans la commande suivante :
|
||
|
||
<div lang="en-US">
|
||
```bash
|
||
docker container stop 0123456789abcdef
|
||
```
|
||
</div>
|
||
|
||
Maintenant, si l'on relance un conteneur `youp0m`, il aura perdu toutes les
|
||
magnifiques images que l'on aura ajoutées. Nous allons voir dans la partie
|
||
suivante comment rendre les données persistantes entre deux lancements.
|