Passer au contenu principal

Images (Docker)

Dockerfile

Le Dockerfile est la recette de construction d'une image. Chaque instruction a des implications sur la taille de l'image, le cache de build, la sécurité et les performances à l'exécution. Les écrire correctement dès le départ évite des problèmes en production.

Instructions essentielles

FROM debian:13-slim

# Métadonnées OCI standard
LABEL maintainer="equipe@exemple.fr"
LABEL org.opencontainers.image.source="https://github.com/org/repo"

# Variable de build (remplaçable via --build-arg)
ARG APP_VERSION=1.0.0

# Variable d'environnement (visible dans le container)
ENV APP_ENV=production     APP_PORT=8080

# Répertoire de travail
WORKDIR /app

# Installation de dépendances (une seule couche, nettoyage dans le même RUN)
RUN apt-get update && apt-get install -y --no-install-recommends     curl     ca-certificates     && rm -rf /var/lib/apt/lists/*

# Copier un fichier
COPY requirements.txt .

# Copier plusieurs fichiers ou répertoires
COPY src/ ./src/

# Exposer un port (documentation, pas de mapping automatique)
EXPOSE 8080

# Utilisateur non-root
USER nobody

# Point d'entrée principal
ENTRYPOINT ["python3", "-m", "gunicorn"]

# Arguments par défaut (remplacables via docker run)
CMD ["--bind", "0.0.0.0:8080", "app:create_app()"]

CMD vs ENTRYPOINT

  • ENTRYPOINT : commande principale, non remplacée par les arguments de docker run
  • CMD : arguments par défaut, remplacés par ce qui suit docker run IMAGE
# Pattern recommandé : ENTRYPOINT fixe + CMD pour les options
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
# docker run nginx:custom -g "daemon off;" -c /etc/nginx/custom.conf

Toujours utiliser la forme JSON (tableau) pour ENTRYPOINT et CMD. La forme shell (CMD nginx -g "daemon off;") lance via /bin/sh -c et le processus ne reçoit pas les signaux Unix correctement (SIGTERM ignoré).

COPY vs ADD

Préférer COPY dans tous les cas sauf deux :

  • ADD décompresse automatiquement les archives tar locales
  • ADD peut télécharger depuis une URL (mais curl + COPY est plus explicite)

.dockerignore

.git
.env
*.log
node_modules/
__pycache__/
*.pyc
dist/
.DS_Store

Sans .dockerignore, le contexte de build envoie tout le répertoire courant au daemon, y compris .git et node_modules. Résultat : builds lents et invalidation de cache inutile.

Bonnes pratiques

  • Un seul RUN apt-get update && apt-get install && rm -rf /var/lib/apt/lists/* par Dockerfile
  • Épingler les versions (nginx:1.27-alpine plutôt que nginx:latest)
  • Utiliser --no-install-recommends avec apt pour éviter les paquets superflus
  • Ne jamais stocker de secrets dans le Dockerfile (ils restent dans les layers)
  • Terminer avec un utilisateur non-root