Laboratoire sur Docker
Exercice 4
Ajouter des fichiers à l’image, monter un répertoire local dans un container, réseau partie 2
Ajouter des fichiers à une image
Dans l’exercice 3, nous avons appris que le contenu persiste lorsqu’un container est arrêté. En utilisant un fichier Dockerfile pour construire nos images, nous pouvons exécuter des commandes pour installer des utilitaires. Sur le système hôte, créez un répertoire “dockertest2” et entrez-y puis téléchargez le fichier Dockerfile pour cet exercice wget https://raw.githubusercontent.com/matbilodeau/labos-cloud/main/exemples/laboDocker/Dockerfile2
. En vérifiant le contenu, vous remarquerez que deux commandes sont disponibles pour l’ajout de fichiers :
- COPY
- Ajoute des fichiers ou répertoires locaux dans le système de fichiers de l’image.
- ADD
- Ajoute des fichiers ou répertoires, locaux ou distants, dans le système de fichiers de l’image. Peut décompresser automatiquement les formats d’archivage connus à partir d’une source locale vers un répertoire du système de fichiers de l’image.
Téléchargez le fichier “https://raw.githubusercontent.com/matbilodeau/labos-cloud/main/exemples/laboDocker/index.html” dans le répertoire local afin de pouvoir l’ajouter lors de la construction. Pour créer un nouveau container, nous avons vu la commande run
qui inclut plusieurs étapes. Exécutons le tout manuellement.
sudo docker --help
Pour obtenir l’image de base il faut utiliser la commande pull
. Pour que Docker puisse construire l’image, le fichier Dockerfile doit porter exactement ce nom; renommez-le ainsi: mv Dockerfile2 Dockerfile
. Vous pouvez mainenant construire votre image avec le nom “monhttpd:v1”. Pour créer un container, la commande est create
. sudo docker create --help
liste parmi les options --name
, ce qui permet de choisir le nom du container plutôt que d’utiliser ceux générés automatiquement. Créez un container à partir de “monhttpd:v1” nommé “test1”. Démarrez le container, il s’est automatiquement envoyé en arrière plan, puis lancez-y un shell bash. Vérifiez que le serveur web est fonctionnel pour les deux fichiers avec curl localhost
et curl localhost/distant.html
.
La documentation explique en partie pourquoi le fichier “distant.html” n’est pas accessible. Lorsque le serveur Apache reçoit des requêtes, elles sont traitées par un daemon. En vérifiant la liste de processus en exécution, httpd est exécuté par le UID “daemon”. Pour afficher les informations sur les fichiers, l’utilitaire exa est une amélioration de ls. Installez-le et utilisez la commande exa -lh
pour afficher également les en-têtes de colonnes. Le fichier “distant.html” appartient à l’utilisateur root, différent de l’utilisateur daemon. Il faut donc ajouter la permission de lecture pour que daemon puisse y accéder, ce que nous ferons avec chmod +604 distant.html
. Ceci ne règle toutefois pas le problème dans le cas où un nouveau container serait démarré. Il serait possible d’utiliser un RUN dans le Dockerfile avec la command wget. Modifiez votre dockerfile et nommez l’image “monhttpd:v2” puis testez de nouveau. L’utilitaire wget télécharge le fichier dans le répertoire courrant. L’instruction Dockerfile WORKDIR indique dans quel répertoire exécuter les commandes. Comme nous avons utilisé une image de base httpd:2.4, celui-ci correspond à “/usr/local/apache2”. Les fichiers .html doivent se trouver dans le répertoire “/usr/local/apache2/htdocs”.
Bien que fonctionnel, le fichier Dockerfile ne respecte pas les bonnes pratiques. Des instructions sont disponibles pour l’utilisation de l’image de base httpd. Modifiez votre fichier Dockerfile pour qu’il puisse, tout en respectant les bonnes pratiques, afficher correctement “distant.html” et nommez l’image finale “monhttpd:v3”.
Monter un répertoire local dans un container
La manière recommandée pour persister de l’information entre les containers et le système hôte est le volume. Dans votre répertoire “dockertest2”, créez un répertoire “public-html” puis copiez-y le fichier “index.html” téléchargé préalablement avec mkdir public-html && cp index.html public-html/
. Modifiez le fichier avec un texte personnalisé. Créez une copie de ce fichier nommée “fichier2.html” et modifiez aussi le texte. Pour les besoins de cet exercice, nous utiliserons un bind mount pour la simplicité. L’option -v chemin/sur/hôte/:chemin/dans/image/
peut être utilisée avec run
ou create
; pour des raisons de sécurité, Docker ne permet pas de monter un répertoire dans un container déjà créé. Créez un nouveau container à partir de votre image “monhttpd:v3” et montez “/home/
Les fichiers montés appartiennent à l’utilisateur 1001, ce qui correspond à mon utilisateur sur le système hôte.
Le “fichier3.html” appartient à l’utilisateur root sur mon système hôte; c’est root qui a démarré le processus du container et qui écrit le fichier localement. Nous verrons comment changer d’utilisateur dans le container plus tard.
Réseau partie 2
Nos interactions avec le réseau ont été minimales, lorsque nous avons testé la connection au serveur web nous sommes restés sur localhost. La colonne PORTS affichée par sudo docker ps
indique le port 80/tcp, on dit que le port 80 est donc exposé. Ceci est possible avec l’instruction EXPOSE du fichier Dockerfile. Les bonnes pratiques indique effectivement d’utiliser les ports traditionnels. L’instruction EXPOSE ne fait qu’indiquer sur quel port le container s’attend à recevoir du trafic. Dans notre cas, le Dockerfile de notre image de base httpd indique bien EXPOSE 80 à la ligne 228.
Dans l’éxercie2, nous avons testé la communication entre deux containers sur un même réseau. Le default bridge network a été utilisé pour tous nos containers jusqu’à maintenant. Sur ce réseau, les containers peuvent communiquer entre-eux à partir de leur adresse IP. Pour les besoins de l’exercice ceci sera suffisant, mais devoir se fier à des adresses est peu pratique si on considère que les containers doivent être le plus éphémères possible. Les réseaux de type user-defined ont plusieurs avantages comme la résolution automatique DNS et une meilleure isolation.
Pour pouvoir lier le port exposé au système hôte, la documentation indique qu’il faut publier le port. De manière semblable au bind mount, publier un port doit se faire à la création du container. Avec l’option -P
, tous les ports exposés seront publiés vers un port aléatoire du système hôte.
Pour publier individuellement les ports, il faut utiliser l’option -p port_container
qui publiera “port_container” sur un port aléatoire du système hôte. Nous pouvons spécifier le port du système hôte avec - p port_hôte:port_container
.
Si votre système hôte peut être accessible publiquement par internet, assurez-vous que les règles de votre pare-feu sont bien configurées et votre container sera accessible sur le port publié.