Création d’images¶
Avant de commencer¶
Dans la suite, nous allons utiliser le moteur de création d’images « buildkit », qui est plus intéressant (performances, fonctionnalités) que celui « par défaut » de docker.
Pour cela, vous devez exécuter :
docker buildx install
Note: avec les versions de docker récentes, il n’est plus nécessaire de faire docker buildx install.
Dockerfile¶
Créez un dossier « premier_dockerfile ».
Dans ce dossier écrivez un fichier hello.sh avec le contenu suivant :
#!/bin/sh
echo Bonjour tout le monde
Créez un second fichier, nommé Dockerfile avec le contenu suivant :
# syntax=docker/dockerfile:1
# L'instruction suivante indique qu'on souhaite se baser sur l'image ubuntu avec le tag 24.04
FROM ubuntu:24.04
# L'instruction suivante permet de copier hello.sh dans le dossier /bin/ de l'image en lui donnant le droit 755
COPY --chmod=755 hello.sh /bin/
Créez une image en exécutant :
docker build -t "ma_premiere_image:0.1" .
Remarquez que si vous lancez de nouveau cette commande, son exécution est bien plus rapide.
Lancez un conteneur à partir de cette image:
docker run -it ma_premiere_image:0.1 bash
Constatez que vous pouvez y lancer « hello.sh »
Layers¶
Exécutez la commande suivante :
docker image history ma_premiere_image:0.1
Dans quel ordre les couches sont elles indiquées ?
À quoi correspond la colonne SIZE ?
Remarquez la colonne « CREATED ». Relancez le build et observez de nouveau cette colonne : les temps n’ont pas changé, le nouveau build n’a en fait rien fait d’autre que de constater qu’il n’avait rien à faire.
Essayez de nouveau, mais cette fois ci en ajoutant l’option
--no-cacheà docker buid. Constatez que cette fois les images ont bien été recréées.
Essais¶
Créez un fichier README.txt avec quelques lignes. Ajoutez une instruction à la fin de votre Dockerfile pour que ce fichier soit copié dans /opt/.
Lancez le build avec ce nouveau Dockerfile. Constatez avec docker image history que seul le cache a été utilisé pour les anciennes couches.
Ajoutez l’instruction suivante à la fin de votre Dockerfile :
RUN <<EOF
apt update
apt install --no-install-recommends -y vim-tiny
rm -rf /var/lib/apt/lists/*
EOF
Observez la taille des couches avec docker history.
Constatez que si vous lancez à nouveau le build, docker utilise son cache et que tout est exécuté très rapidement.
Les instructions Dockerfile¶
Jusqu’ici nous avons utilisé trois instructions différentes : FROM, COPY et RUN :
FROMpermet de dire de quelle image on part. La bonne pratique voudra qu’on spécifie une version bien précise (ubuntu:22.04 plutôt que ubuntu ou que ubuntu:latest)COPYpermet de copier un fichier ou dossier dans le système de fichiers de l’image. L’option--chmodpermet de préciser les droits que l’on donne aux fichiers copiésRUNpermet d’exécuter une commande et si celle ci impacte les fichiers, les modifications feront partie de l’image.
Il y a en tout une quinzaine d’instructions, documentées ici : https://docs.docker.com/engine/reference/builder/ et avec une dizaine on est déjà très bien. Plus que quelques unes à connaître !
ENTRYPOINT et CMD¶
Dans la suite, nous nous assurerons systématiquement que notre conteneur contient les deux instructions suivantes :
ENTRYPOINT ["commande", "argument1", "argument2"]
CMD ["argument_supplémentaire_par_défaut1", "argument_supplémentaire_par_défaut2"]
Lorsqu’on lance un conteneur en faisant docker run -it NOM_IMAGE, le processus qui sera lancé à l’intérieur du conteneur sera : commande argument1 argument2 argument_supplémentaire_par_défaut1 argument_supplémentaire_par_défaut2.
Lorsqu’on lance un conteneur en faisant docker run -it NOM_IMAGE argument_supp1 argumentsupp2,
le processus qui sera lancé à l’intérieur du conteneur sera : commande argument1 argument2 argumentsupp1 argumentsupp2.
Par exemple, supposons qu’on ait une image essai_entrypoint construite à partir du Dockerfile suivant :
# syntax=docker/dockerfile:1
FROM alpine:3.16
ENTRYPOINT ["/bin/echo", "Bonjour"]
CMD ["tout","le","monde!"]
Sans essayer : quelle serait la sortie de la commande
docker run essai_entrypoint?Sans essayer : quelle serait la sortie de la commande
docker run essai_entrypoint Hello?Ecrivez un dockerfile ayant pour image de base alpine:3.16, avec comme ENTRYPOINT
["/bin/ls"]et comme CMD["-lah"]. Que cela fait-il ?Ecrivez un dockerfile ayant pour image de base alpine:3.16, avec comme ENTRYPOINT
["/bin/sh","-c"]et comme CMD["sh"]. Que cela fait-il ?
On peut ne pas spécifier ENTRYPOINT ou CMD, mais le fonctionnement n’est alors pas celui décrit ci-dessus. Dans la suite nous nous assurerons de systématiquement les renseigner.
principales instuctions pour Dockerfile¶
Commandes |
Utilisation |
|---|---|
|
IMAGE |
|
Ajouter des métadonnées |
|
Lancer une commande |
|
Ajout au conteneur |
|
Ajout au conteneur et aussi |
|
Répertoire de travail |
|
Port d’écoute |
|
Commande à lancer au démarrage du container |
|
Définition de variables d’environnemment |
|
Nom d’utilisateur à utiliser |
|
Passage arguments ex: docker build –build-arg machin=bidule |
Exemple plus complet¶
Ecrivons une image un peu plus complète pour finir avec une petite app nodejs dans un conteneur.
Créer un répertoire de base node-serv-fic.
Fabriquer le fichier lireFic.js et le placer à la racine :
let http=require('http'),fs=require('fs');
http.createServer(function (req, res) {
// Ouvre et lit servHello.js
fs.readFile('hello.txt','utf8',function(err, data) {
res.writeHead(200,{'Content-Type': 'text/plain'});
if (err)
res.write('Pb ouverture fichier\n');
else// On renvoie le fichier au client
res.write(data);
res.end();
});
}).listen(8200, function() {console.log('Connecte au port 8200');});
console.log('Serveur tourne sur port 8200');
On utilise un fichier package.json pour les dépendances :
{
"name": "nodejs-simple",
"version": "1.0.0",
"description": "Envoi fichier par serveur node",
"main": "lireFic.js",
"keywords": [
"node",
"serveur",
"fichier"
],
"author": "Super Geek",
"license": "ISC",
"dependencies": {
"http": "^0.0.1-security"
}
}
un fichier hello.txt pour publication (contenu à votre guise !)
Enfin le Dockerfile :
FROM node:23.11-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY lireFic.js .
COPY hello.txt .
EXPOSE 8200
ENTRYPOINT ["node", "lireFic.js"]
CMD []
On build et on lance :
docker build -t node-serv-fic .docker run -d --name node-serv -p 8000:8200 node-serv-ficon visite http://localhost:8000
Exemple avec votre llm favori¶
En partant d’une page blanche, demandez à chatGPT ou autre de :
Créer une application python qui sert le contenu d’un fichier sur le port 3004
Créer un Dockerfile pour faire tourner cette application
Donner une commande pour faire tourner cette application sur votre machine de façon à ce qu’elle soit accessible sur le port 8000
Avant de lancer, discutez et validez (si vous avez des doutes, ne lancez rien !). Discutez les éventuelles erreurs / approximations du llm.