215 lines
7.6 KiB
Markdown
215 lines
7.6 KiB
Markdown
|
\newpage
|
||
|
|
||
|
# Retour sur les bonnes pratiques
|
||
|
|
||
|
http://docs.docker.com/articles/dockerfile_best-practices/
|
||
|
|
||
|
## Utilisez le fichier `.dockerignore`
|
||
|
|
||
|
Dans la plupart des cas, vos Dockerfile seront dans des dossiers contenant
|
||
|
beaucoup de fichiers qui ne sont pas nécessaire à la construction de votre
|
||
|
conteneur (par exemple, vous pouvez avoir un `Dockerfile` placé à la racine
|
||
|
d'un dépôt git : il va avoir besoin des binaires compilés, mais pas des
|
||
|
sources).
|
||
|
|
||
|
Afin d'améliorer les performances lors de la construction, vous pouvez exclure
|
||
|
les fichiers et dossiers inutiles au conteneur en ajoutant un fichier
|
||
|
`.dockerignore` dans le répertoire de votre `Dockerfile`.
|
||
|
|
||
|
Ce fichier fonctionne de la même manière que le `.gitignore` : vous pouvez
|
||
|
utiliser du globing.
|
||
|
|
||
|
Pour plus d'informations, vous pouvez consulter la documentation accessible à
|
||
|
<http://docs.docker.com/reference/builder/#dockerignore-file>.
|
||
|
|
||
|
|
||
|
## N'installez rien de superflu
|
||
|
|
||
|
Afin de réduire la quantité de dépendances à installer, n'installez pas de
|
||
|
paquets dont vous n'avez pas vraiment l'utilité : il n'y a pas de raison par
|
||
|
exemple d'avoir un éditeur de texte dans un environnement qui sera utilisé
|
||
|
comme serveur web. Un autre conteneur pourra contenir cet éditeur de texte dans
|
||
|
les cas où vous avez besoin de modifier des données.
|
||
|
|
||
|
En plus, cela réduira le temps de build et la taille des images produites !
|
||
|
|
||
|
|
||
|
## Minimisez le nombre de couches
|
||
|
|
||
|
Vous devez trouver l'équilibre idéal entre la lisibilité de votre `Dockerfile`
|
||
|
(qui assure la maintenabilité sur le long-terme) et le nombre de couches
|
||
|
créées. Le nombre de couches idéal devrait être égal au nombre de branches
|
||
|
distincte partant d'une image de base, afin d'utiliser au mieux le cache du
|
||
|
système de fichiers.
|
||
|
|
||
|
|
||
|
## Ordonnez vos lignes de commandes complexes
|
||
|
|
||
|
### Allez à la ligne pour séparer les longues lignes de commandes complexes
|
||
|
|
||
|
Aérez vos `Dockerfile` !
|
||
|
|
||
|
N'hésitez pas à commenter et séparer les blocs logiques ensemble, comme lorsque
|
||
|
vous codez.
|
||
|
|
||
|
Lorsqu'une ligne devient complexe, allez à la ligne :
|
||
|
|
||
|
```
|
||
|
RUN apt-get update && apt-get install -y \
|
||
|
nginx \
|
||
|
php5-fpm
|
||
|
```
|
||
|
|
||
|
Notez les backslashs à la fin des lignes, indiquant qu'elle n'est pas terminée.
|
||
|
|
||
|
### Triez les arguments par ordre alphabétique
|
||
|
|
||
|
Lorsque c'est possible, ordonnez vos lignes suivant un ordre logique. Par
|
||
|
exemple :
|
||
|
|
||
|
```
|
||
|
RUN apt-get update && apt-get install -y \
|
||
|
bzr \
|
||
|
cvs \
|
||
|
git \
|
||
|
mercurial \
|
||
|
subversion
|
||
|
```
|
||
|
|
||
|
|
||
|
## Profitez du système de cache
|
||
|
|
||
|
Le processus de construction de votre image Docker va lire les informations de
|
||
|
votre Dockerfile dans l'ordre. Pour chaque instruction, Docker va essayer de
|
||
|
trouver si une image n'est pas déjà disponible dans le cache (plutôt que de
|
||
|
créer une nouvelle image identique).
|
||
|
|
||
|
Il y a un certain nombre de règles à connaître pour bien utiliser ce mécanisme :
|
||
|
|
||
|
- En démarrant d'une image de base déjà présente dans le cache (`docker
|
||
|
images`), l'instruction suivante est comparée avec toutes les autres images
|
||
|
existantes qui en dérivent directement. Si aucune image correspondant n'est
|
||
|
trouvé pour l'instruction, le cache est invalidé pour le reste de cette
|
||
|
construction.
|
||
|
- Dans la plupart des cas, Docker va simplement comparer l'instruction lue avec
|
||
|
le(s) différente(s) image(s) qui dérive(nt) de la commande précédente. Si
|
||
|
aucune commande correspondante n'est trouvé, le cache se retrouve invalidé
|
||
|
pour les instructions suivantes.
|
||
|
- Pour les instructions `ADD` et `COPY`, en plus de la comparaison précédente,
|
||
|
la somme de contrôle du fichier est ajoutée. Si le fichier a été modifié, le
|
||
|
cache se retrouve invalidé.
|
||
|
- Une fois que le cache est invalidé, toutes les commandes restantes à exécuter
|
||
|
dans le `Dockerfile` vont être exécutées.
|
||
|
|
||
|
|
||
|
## Concevez des conteneur éphémères
|
||
|
|
||
|
Les conteneurs que vous générez doivent aussi éphémères que possible : ils
|
||
|
devraient pouvoir être arrêtés, détruits et recréés sans nécessité d'étape de
|
||
|
reconfiguration. La configuration devrait se faire au lancement du conteneur ou
|
||
|
lors de sa construction.
|
||
|
|
||
|
|
||
|
## Cas d'`apt-get` et des gestionnaires de paquets
|
||
|
|
||
|
- N'exécutez pas `apt-get update` seul sur une ligne. Cela risque de poser des
|
||
|
problèmes de cache, car la ligne ne va jamais changer et le cache sera
|
||
|
toujours utilisé. Vous risquez de récupérer des paquets qui ne sont pas à
|
||
|
jour.
|
||
|
- Évitez de mettre à jour le système fourni (via `apt-get upgrade` ou `apt-get
|
||
|
update`). Si l'image n'est pas à jour, contactez son mainteneur. Si vous avez
|
||
|
besoin d'une version à jour d'un paquet distribué avec l'image, préférez
|
||
|
l'utilisation d'`apt-get install -y foo` qui mettra à jour exclusivement le
|
||
|
paquet `foo`, sans altérer le reste du système.
|
||
|
- Pour assurer une bonne gestion du cache, n'hésitez pas à indiquer les
|
||
|
versions des programmes que vous voulez installer sur votre ligne de commande
|
||
|
`apt-get`.
|
||
|
|
||
|
|
||
|
## Exposez les ports standards
|
||
|
|
||
|
La commande `EXPOSE` vous permet d'indiquer les ports sur lesquels votre
|
||
|
conteneur s'attend à recevoir des paquets venant de l'extérieur. Ces ports ne
|
||
|
sont pas partagés avec l'hôte ou les autres conteneur, donc vous n'avez pas de
|
||
|
raison de ne pas utiliser les ports standards.
|
||
|
|
||
|
Si vous faites cela, il y a de forte chance qu'il n'y ait pas besoin de
|
||
|
modifier la configuration des autres logiciels contenu dans d'autres conteneurs
|
||
|
puis qu'ils sont généralement configurés pour se connecter aux ports standards.
|
||
|
|
||
|
S'il y a un conflit sur la machine hôte, il sera toujours temps de créer une
|
||
|
redirection à ce moment là.
|
||
|
|
||
|
|
||
|
## La bonne utilisation de l'`ENTRYPOINT`
|
||
|
|
||
|
L'entrypoint peut être utilisé de deux manières différentes :
|
||
|
|
||
|
- Vous pouvez l'utiliser de telle sorte que la commande passée au `docker run`,
|
||
|
après le nom de l'image, corresponde aux arguments attendu par le programme
|
||
|
indiqué dans l'entrypoint. Par exemple pour nginx :
|
||
|
|
||
|
```
|
||
|
ENTRYPOINT ["nginx"]
|
||
|
CMD ["-g daemon off;"]
|
||
|
```
|
||
|
|
||
|
- Vous pouvez aussi utiliser un script qui servira à faire les initialisations
|
||
|
ou les configurations nécessaire au bon fonctionnement du conteneur
|
||
|
(rappelez-vous, il doit être éphémère !). Par exemple, le `Dockerfile` pour
|
||
|
l'image de PostgreSQL possède cet entrypoint :
|
||
|
|
||
|
```
|
||
|
#!/bin/bash
|
||
|
set -e
|
||
|
|
||
|
if [ "$1" = 'postgres' ]; then
|
||
|
chown -R postgres "$PGDATA"
|
||
|
|
||
|
if [ -z "$(ls -A "$PGDATA")" ]; then
|
||
|
gosu postgres initdb
|
||
|
fi
|
||
|
|
||
|
exec gosu postgres "$@"
|
||
|
fi
|
||
|
|
||
|
exec "$@"
|
||
|
```
|
||
|
|
||
|
|
||
|
## `[""]`, `'` et sans `[]`
|
||
|
|
||
|
Les instructions `ENTRYPOINT` et `CMD` peuvent prendre deux formes :
|
||
|
|
||
|
- `["cmd", "arg1", "arg2"]` : ici, un simple `exexve` sera effectué avec ces
|
||
|
arguments. Si d'éventuels variables se trouve dans les arguments, elles ne
|
||
|
seront pas remplacées.
|
||
|
- `cmd arg1 arg2` : ici l'exécution se fera au sein d'un `sh -c`, donc les
|
||
|
variables seront remplacés et étendues.
|
||
|
|
||
|
Les commandes sous forme de tableau étant parsées par un parser JSON, vous ne
|
||
|
pouvez pas utiliser les simple quotes.
|
||
|
|
||
|
|
||
|
## Volumes
|
||
|
|
||
|
L'instruction `VOLUME` doit être utilisée pour exposer tous les espaces de
|
||
|
stockage
|
||
|
|
||
|
|
||
|
## Réduisez les privilèges
|
||
|
|
||
|
Utilisez l'instruction `USER` dès que vous le pouvez, lorsqu'un service ne
|
||
|
réclame pas de privilège particulier.
|
||
|
|
||
|
Il vous faudra sans doute créer l'utilisateur et son groupe dans le Dockerfile.
|
||
|
|
||
|
|
||
|
## Exécutez un seul processus par conteneur
|
||
|
|
||
|
Dans la majorité des cas, vous ne devriez jamais lancer plus d'un seul
|
||
|
processus par conteneur. Il est préférable de répartir chaque application dans
|
||
|
un conteneur distinct qui n'effectue que le travail pour lequel il est
|
||
|
chargé. Les options de liaison entre conteneur sont à votre disposition pour
|
||
|
vous aider à cette tâche.
|