Dockerfile — Créer des Images Docker
Un Dockerfile est un fichier texte contenant les instructions pour construire une Docker Image. C'est le blueprint de votre environnement applicatif.
Qu'est-ce qu'un Dockerfile ?
Code source Docker Image
(centaines de fichiers)
+
Dockerfile ──────► Image ready to run
(instructions)
Le Dockerfile décrit étape par étape comment construire l'image :
- Quel OS de base utiliser
- Quelles dépendances installer
- Quels fichiers copier
- Quelle commande lancer au démarrage
Instructions Dockerfile — Référence
| Instruction | Description | Exemple |
|---|---|---|
FROM | Image de base (point de départ) | FROM node:20-alpine |
ENV | Variables d'environnement | ENV PORT=3000 |
RUN | Exécuter une commande lors du build | RUN mkdir -p /home/app |
COPY | Copier des fichiers de l'hôte vers l'image | COPY . /home/app |
WORKDIR | Définir le répertoire de travail | WORKDIR /home/app |
EXPOSE | Documenter le port exposé | EXPOSE 3000 |
CMD | Commande de démarrage du container | CMD ["node", "server.js"] |
ENTRYPOINT | Point d'entrée alternatif à CMD | ENTRYPOINT ["java", "-jar", "app.jar"] |
Différence CMD vs ENTRYPOINT :
CMD= commande par défaut, peut être surchargée audocker runENTRYPOINT= commande fixe, toujours exécutée- On peut avoir plusieurs
RUN, mais un seulCMD/ENTRYPOINT
Exemple — Application Node.js
FROM node:20-alpine
# Variables d'environnement disponibles dans le container
ENV MONGO_DB_USERNAME=admin \
MONGO_DB_PWD=password
# Créer le dossier de l'application
RUN mkdir -p /home/app
# Copier le code source dans l'image
COPY . /home/app
# Définir le répertoire de travail
WORKDIR /home/app
# Installer les dépendances
RUN npm install
# Démarrer l'application
CMD ["node", "server.js"]
Exemple — Application Java (Gradle)
FROM amazoncorretto:17-alpine-jdk
EXPOSE 8080
# Copier le JAR buildé dans l'image
COPY ./build/libs/java-app-1.0-SNAPSHOT.jar /usr/app/
WORKDIR /usr/app
ENTRYPOINT ["java", "-jar", "java-app-1.0-SNAPSHOT.jar"]
Layers (Couches) d'une Image
Chaque instruction dans un Dockerfile crée une couche (layer) dans l'image :
Dockerfile Image résultante
────────────── ──────────────────────────
FROM node:20 ┌──────────────────────┐
↓ │ CMD ["node","srv"] │ ← Layer 5
ENV PORT=3000 ├──────────────────────┤
↓ │ COPY . /home/app │ ← Layer 4
RUN mkdir /home/app ├──────────────────────┤
↓ │ RUN mkdir │ ← Layer 3
COPY . /home/app ├──────────────────────┤
↓ │ ENV PORT=3000 │ ← Layer 2
CMD ["node","srv"] ├──────────────────────┤
│ node:20-alpine │ ← Layer 1 (base)
└──────────────────────┘
Avantage des layers : cache Docker
- Docker ne rebuild que les layers modifiés et ceux qui les suivent
- Mettre les instructions qui changent rarement en haut du Dockerfile
- Mettre
COPYetRUN npm installaprès les instructions stables
# Optimisation du cache — ordre important
FROM node:20-alpine
WORKDIR /home/app
COPY package.json . # ← copier d'abord package.json seul
RUN npm install # ← installer les deps (cache tant que package.json ne change pas)
COPY . . # ← copier le reste du code (change souvent)
CMD ["node", "server.js"]
Construire une image : docker build
# Syntaxe
docker build -t <nom>:<tag> <contexte>
# Exemples
docker build -t mon-app:1.0 . # Répertoire courant comme contexte
docker build -t mon-app:1.0 ./backend # Sous-dossier comme contexte
docker build -f Dockerfile.prod -t mon-app:prod . # Dockerfile spécifique
-t: nom et tag de l'image (nom:tag).: contexte de build = ensemble des fichiers disponibles pendant le build (répertoire courant)- Chaque instruction dans le Dockerfile est exécutée dans l'ordre
Séquence complète build → push :
# 1. Builder l'image
docker build -t mon-app:1.0 .
# 2. Tagger pour le registry
docker tag mon-app:1.0 registry.exemple.com/mon-app:1.0
# 3. Push vers le registry
docker push registry.exemple.com/mon-app:1.0
Dockerfile dans le pipeline CI/CD
Le Dockerfile est commité dans Git avec le code source. Le CI/CD l'utilise pour construire et publier l'image automatiquement.
Développeur
├── code source
└── Dockerfile ──► git commit ──► Git repo
│
▼ trigger CI
CI Server (Jenkins)
│
docker build -t app:$VERSION .
docker push registry/app:$VERSION
│
▼ push
Docker Registry
│
▼ pull (déploiement)
Serveur de production
docker run app:$VERSION
.dockerignore
Comme .gitignore, .dockerignore exclut des fichiers du contexte de build :
# .dockerignore
node_modules/
.git/
*.log
.env
dist/
Pourquoi : éviter de copier des fichiers inutiles (alourdit l'image) ou sensibles (credentials).
À retenir
- Dockerfile = fichier texte avec instructions pour construire une Docker Image
- Instructions clés :
FROM(base),ENV(variables),RUN(commandes build),COPY(fichiers),CMD(démarrage)- Chaque instruction = 1 layer → Docker met les layers en cache pour accélérer les rebuilds
docker build -t nom:tag .→ construit l'image depuis le Dockerfile du répertoire courant- Dockerfile commité dans Git avec le code → CI/CD le build et push automatiquement
.dockerignore: exclurenode_modules/,.env,.git/... du contexte de build- Mettre les instructions stables en haut, le code source en bas (optimisation cache)