Intermédiaire60 min40 XP
Objectifs de cette leçon
- Écrire un Dockerfile optimisé
- Comprendre les instructions ADD, COPY, RUN, CMD
- Construire des images multi-étapes
Écrire un Dockerfile 📝
Anatomy d'un Dockerfile
# Commentaire : Étape 1 - Image de base FROM node:18-alpine # Étape 2 - Répertoire de travail WORKDIR /app # Étape 3 - Copier les dépendances (pour le cache) COPY package*.json ./ # Étape 4 - Installer les dépendances RUN npm ci --only=production # Étape 5 - Copier le code source COPY . . # Étape 6 - Variables d'environnement ENV NODE_ENV=production # Étape 7 - Exposer un port EXPOSE 3000 # Étape 8 - Commande par défaut CMD ["node", "server.js"]
Chaque instruction en détail
FROM
FROM node:18-alpine # Alpine = léger (178 Mo) FROM ubuntu:22.04 # Plus lourd (800 Mo) FROM scratch # Image vide (avancé)
Règle : Toujours commencer par FROM. C'est la première instruction.
WORKDIR
WORKDIR /app # Définit le répertoire de travail # Toutes les instructions suivantes s'exécutent dans /app
COPY
COPY . . # Copie tout le dossier actuel COPY package*.json ./ # Copie uniquement les fichiers package COPY --chown=node:node . . # Copie avec un propriétaire spécifique
ADD (avancé)
ADD archive.tar.gz /app # Extrait automatiquement les archives ADD https://example.com/file.txt /app # Télécharge depuis une URL
Conseil : Préférez COPY à ADD sauf pour les archives.
RUN
RUN apt-get update && apt-get install -y curl # Installation RUN npm ci --only=production # Installation npm RUN rm -rf /var/lib/apt/lists/* # Nettoyage
Astuce : Combinez les RUN pour réduire le nombre de couches.
CMD vs ENTRYPOINT
# CMD : commande par défaut (peut être écrasée) CMD ["node", "server.js"] # ENTRYPOINT : toujours exécutée (paramètre ajouté) ENTRYPOINT ["node"] CMD ["server.js"] # ENTRYPOINT avec CMD par défaut ENTRYPOINT ["python"] CMD ["app.py"]
ENV vs ARG
# ENV : variable disponible dans le conteneur ENV NODE_ENV=production ENV DB_HOST=localhost # ARG : variable disponible uniquement lors du build ARG VERSION=1.0 RUN echo "Building version $VERSION"
EXPOSE
EXPOSE 3000 # Documente le port (ne l'ouvre pas !) EXPOSE 80/tcp # Avec le protocole EXPOSE 443 # HTTPS
Note : EXPOSE ne fait qu'documenter. Vous devez quand même utiliser -p au docker run.
Dockerfile pour Node.js
FROM node:18-alpine WORKDIR /app # Dépendances d'abord (cache) COPY package*.json ./ RUN npm ci --only=production # Code source COPY . . # Port EXPOSE 3000 # Démarrage CMD ["node", "server.js"]
Dockerfile pour Python
FROM python:3.11-slim WORKDIR /app # Dépendances COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Code COPY . . EXPOSE 8000 CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
Dockerfile pour PHP/Laravel
FROM php:8.2-fpm-alpine # Extensions nécessaires RUN docker-php-ext-install pdo pdo_mysql mbstring # Composer COPY --from=composer:latest /usr/bin/composer /usr/bin/composer WORKDIR /var/www/html COPY . . RUN composer install --no-dev --optimize-autoloader EXPOSE 9000 CMD ["php-fpm"]
Bonnes pratiques
| Pratique | Mauvais | Bon |
|---|---|---|
| Image de base | FROM ubuntu | FROM node:18-alpine |
| Couches | 10 RUN séparés | 1-2 RUN combinés |
| Cache | Tout copier d'abord | Copier package.json d'abord |
| Sécurité | Root par défaut | USER node (non-root) |
| Nettoyage | Pas de nettoyage | rm -rf /var/lib/apt/lists/* |
Exercices 🎯
- Dockerfile Node : Écrivez un Dockerfile pour une app Express.js.
- Dockerfile Python : Écrivez un Dockerfile pour une app Django.
- Multi-stage : Créez un Dockerfile multi-stage pour une app React (build + nginx).
- Optimisation : Comparez la taille de votre image avant et après optimisation.
Prochaine leçon : Docker Compose pour les applications multi-services.
⚡ Simulateur — Exécution d'un Dockerfile
Étape 1/7📝 Pseudo-code
1FROM node:22-alpine
2WORKDIR /app
3COPY package*.json ./
4RUN npm ci --only=production
5COPY . .
6EXPOSE 3000
7CMD ["node", "server.js"]
🔍 Résultat de l'instruction
📥 FROM
base
node:22-alpine
taille
130MB
action
Image de base téléchargée
FROM : on part d'une image Node.js Alpine (130MB).