virli/tutorial/1/dockerfile.md
2017-09-22 10:27:48 +02:00

4.5 KiB

\newpage

Dockerfile

Mon premier conteneur ... par Dockerfile

Pour construire une image, vous n'êtes pas obligé de passer par une série de commits. Docker dispose d'un mécanisme permettant d'automatiser la construction de nouvelles images. Vous pouvez arriver au même résultat que ce que l'on a réussi à faire précédemment en utilisant le Docker file suivant :

FROM ubuntu:latest

RUN apt-get update
RUN apt-get install -y nano

La syntaxe d'un Dockerfile est simple, le premier mot de chaque ligne est l'intitulé d'une instruction (que l'on écrit généralement en majuscule), elle est suivie de ses arguments.

Dans notre exemple, nous utilisons FROM qui indique une image de départ à utiliser ; RUN est une commande qui sera exécutée dans le conteneur, dans le but de le construire.

Pour lancer la construction de la nouvelle image, créer un nouveau dossier ne contenant que votre fichier Dockerfile, placez-vous dedans, puis utilisez la commande build :

docker build --tag=my_editor .

Une fois la construction de l'image terminée, vous pouvez la lancer et constater l'existence de notre éditeur favori :

docker run -it my_editor /bin/bash

RUN dans le Dockerfile

Dans un Dockerfile, chaque ligne est exécutée indépendamment des autres et correspondra à une nouvelle couche de notre image.

Cela signifie que l'exemple suivant ne fonctionne pas :

COPY db.sql /db.sql
RUN service mysqld start
RUN mysql -u root -p toor virli < /db.sql

Cet exemple ne fonctionne pas car le serveur MySQL est lancé dans le premier RUN, n'est plus lancé au moment du deuxième RUN. En effet, chaque commande du Dockerfile a pour but de modifier le système de fichiers.

Pour avoir le résultat escompté, il faut exécuter les commandes ensemble :

COPY db.sql /db.sql
RUN service mysqld start && mysql -u root -p toor virli < /db.sql

Après le RUN, MySQL sera de nouveau arrêté, si on veut l'utiliser dans le conteneur, il ne faudra pas oublier de lancer le processus.

Exposer des ports

Construisons maintenant un conteneur avec un serveur web :

FROM my_editor

RUN apt-get update
RUN apt-get install -y nginx

EXPOSE 80

L'instruction EXPOSE sera traité plus tard par le client Docker (équivalent à l'argument --expose). Il s'agit de préciser les ports sur lesquels votre image écoute.

En utilisant l'option -P du run, vous allez pouvoir assigner une redirection de port aléatoire sur la machine hôte vers votre conteneur :

docker build --tag=my_webserver .
docker run -it -P my_webserver /bin/bash
service nginx start

Dans un autre terminal, lancer un docker ps et consulter la colonne PORTS pour connaître le port choisit par Docker pour effectuer la redirection.

Rendez-vous ensuite dans votre navigateur sur http://localhost:49153/.

À vous de jouer : utilisez l'instruction COPY pour afficher votre propre index.html remplaçant celui installé de base par nginx.

Lancement de commande automatique

Vous pouvez placer dans un Dockerfile une instruction CMD qui sera exécutée si aucune commande n'est passée lors du run, par exemple :

CMD nginx -g "daemon off;"
docker build --tag=my_nginx .
docker run -d -P my_nginx

L'option -d passée au run lance le conteneur en tâche de fond. Si vous constatez via un docker ps que le conteneur s'arrête directement, retirer cette option pour voir ce qui ne va pas, ou utilisez la commande docker logs.

D'autres instructions ?

Consultez https://docs.docker.com/engine/reference/builder/ pour la liste complète des instructions reconnues.

Rendu

Exercice

Rendez le fichier Dockerfile et son contexte (index.html, fichiers de conf éventuels, ...) que vous avez utiliser pour réaliser votre image my_webserver.

Questions

  1. De combien de couches de systèmes de fichiers est composé votre image my_webserver ? Comment pourriez-vous en avoir moins ?

  2. On a vu comment créer une nouvelle image à partir d'une image existante (FROM). Mais comment sont créés les images de bases comme debian ou ubuntu (quelle(s) commande(s) et quels type(s) de fichier(s)) ?

  3. Quels sont les avantages de ce RUN :

RUN apt-get update && \
    apt-get install -y \
        nginx \
        php5-fpm \
        php5-mysql \
        php5-gd \
    && apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

par rapport aux précédents exemples :

RUN apt-get update
RUN apt-get install -y nginx php5-fpm