Exercice Dockerfile C

Objectifs

  • Choisir une image de base adaptée.

  • Structurer un Dockerfile avec bonnes pratiques : LABEL, ARG, ENV, WORKDIR, COPY, RUN, EXPOSE, VOLUME, HEALTHCHECK, USER, ENTRYPOINT/CMD.

  • Réduire la taille d’image via multi-stage build et couche cache.

  • Exécuter le service en non-root.

  • Comprendre .dockerignore, variables d’env, et ports.

  • Donner toutes les commandes Docker utilisées.


Énoncé

Vous devez conteneuriser une petite API Flask qui expose :

  • GET /{"msg":"Hello from Docker!"}

  • GET /health{"status":"ok"}

Contraintes :

  1. Écrire un Dockerfile multi-stage:

  • Stage builder : installation des dépendances (roue/compilation si nécessaire).

  • Stage runtime : image plus légère, copie minimaliste.

  1. Ajouter des LABEL (auteur, version, description).

  2. Gérer un ARG APP_ENV (valeurs: dev ou prod) avec une ENV par défaut.

  3. Définir WORKDIR, COPY (en respectant un .dockerignore).

  4. Créer un utilisateur non-root et exécuter l’appli avec cet utilisateur.

  5. Ouvrir le port 8000 (EXPOSE 8000).

  6. Ajouter un HEALTHCHECK qui vérifie http://localhost:8000/health.

  7. Utiliser ENTRYPOINT + CMD correctement (ENTRYPOINT = processus, CMD = args).

  8. Déclarer un VOLUME /app/logs (les logs y sont écrits).

Livrables :

  • Dockerfile

  • .dockerignore

  • Code minimal de l’API (app.py, requirements.txt)

  • Commandes pour build, run, test, inspecter la santé.


Squelette de projet

project/
├─ app.py
├─ requirements.txt
├─ Dockerfile
└─ .dockerignore

app.py

from flask import Flask, jsonify
import os, sys, pathlib

app = Flask(__name__)

LOG_DIR = pathlib.Path("/app/logs")
LOG_DIR.mkdir(parents=True, exist_ok=True)
open(LOG_DIR / "app.log", "a").close()

@app.route("/")
def root():
    return jsonify(msg="Hello from Docker!", env=os.getenv("APP_ENV", "dev"))

@app.route("/health")
def health():
    return jsonify(status="ok")

if __name__ == "__main__":
    # Bind sur 0.0.0.0 pour être accessible depuis le conteneur
    app.run(host="0.0.0.0", port=8000)

requirements.txt

flask==3.0.3

.dockerignore

Voici une version incomplete, veuillez le completer pour éviter que des fichiers ou répertoires non désirés ce retrouvent dans l’image Docker.

__pycache__/
*.pyc
*.log
.git
.gitignore
.env
.cache/

Tips

  • Voici les packages apt qui seront utiles d’installer : build-essential, curl, ca-certificates

  • Utiliser de préférence pip wheel pour optimiser la taille de l’image - Pip Wheel Doc

  • Pour le health check utiliser curl comme ceci :

HEALTHCHECK --interval=10s --timeout=2s --retries=3 CMD curl -f http://localhost:8000/health || exit 1

Pour aller plus loin

  • Mesurer la taille de l’image et la réduire (changer de base : slim vs alpine).

  • Ajouter un USER ID via --build-arg UID=10001.

  • Multi-stage avancé : figer pip wheel dans le builder puis copier uniquement les wheels.