Pour vous familiariser avec Docker, vous continuerez à travailler en pair programming.

Problématique

Au sein d’un projet, l’équipe peut être amenée à nécessiter plusieurs outils, notamment par le biais de langages de programmation : python, PHP, node.js, ruby, etc. Dans un environnement local, il devient rapidement difficile de gérer tous ces outils, de les faire cohabiter, de les mettre à jour, etc. d’autant plus lorsque les versions diffèrent d’un projet à un autre.

Par ailleurs, il faut s’assurer que tous les membres de l’équipe utilisent exactement les mêmes outils, que ce soit pour les versions ou les dépendances (et leurs versions).

Les containers de Docker sont une solution à cette problématique par le biais de leur image qui peut être facilement partagée.

Vous allez créer un container intégrant python afin d’exécuter les scripts python nécessaires pour le projet et l’environnement local.

Avant-propos : container python

Il existe une image officielle de python sur Docker Hub : python, afin de créer des containers Docker “standalone” pour exécuter des scripts python, ou pour s’en servir de base pour une image plus étoffée et spécifique à un besoin particulier.

docker run --rm -it python:3.12 python --version

La commande crée un container anonyme à partir de l’image python avec le tag 3.12 et exécute la commande python --version à l’intérieur du container.

  • L’option --rm permet de supprimer le container une fois qu’il est arrêté, pour éviter d’avoir des containers inutiles qui utilisent de l’espace disque.
  • L’option -i (raccourci de --interactive) permet d’interagir avec le container.
  • L’option -t (raccourci de --tty) permet de créer un pseudo-terminal pour le container.
  • Ce sont les options de base et essentielles pour exécuter des commandes dans un container.
    Dans ce cas de figure où on exécute une commande qui ne nécessite pas d’interaction, on peut s’abstenir des options -it.
    Si on avait voulu entrer dans le container pour exécuter des commandes manuellement (avec la commande python ou tout simplement la commande bash), on aurait eu besoin de ces options.

Exécuter des scripts python

Avec l’image que vous avez récupérée, vous pouvez vous en servir pour construire des containers “standalone” qui pourront exécuter vos scripts python.

Admettons le script hello_there.py suivant :

print("General Kenobi!")

Vous pourrez l’exécuter avec la commande suivante :

docker run --rm -it -v $(pwd):/usr/src/app -w /usr/src/app python:3.12 python hello_there.py
  • L’option -v (raccourci de --volume) permet de monter un volume dans le container.
    C’est-à-dire qu’on va fournir un chemin local (directory ou fichier) que l’on va monter dans le container. Les deux seront alors synchronisés.
    Ici, on monte le répertoire courant ($(pwd)) dans le répertoire /usr/src/app du container.
  • L’option -w (raccourci de --workdir) permet de définir le répertoire courant du container lorsqu’on l’exécute.
    Cela revient à faire un cd vers le chemin indiqué avant d’exécuter la commande demandée.
    Ici, on définit le répertoire courant du container à /usr/src/app, là où on a monté le répertoire courant local.

Définir un utilitaire local

Pour simplifier l’exécution de la commande, vous pourriez définir un alias dans votre shell.

alias dpy='docker run --rm --interactive --tty --volume $(pwd):/usr/src/app --workdir /usr/src/app python:3.12 python'
alias dpyb='docker run --rm --interactive --tty --volume $(pwd):/usr/src/app --workdir /usr/src/app python:3.12 bash'

Ce qui vous permettra d’exécuter une commande python ou un script de cette manière : dpy hello_there.py.

Le deuxième alias vous permettrait d’exécuter un shell bash dans le container avec la commande dpyb.

⚠️ Si vous comptez écrire des scripts python au lieu de scripts bash pour vous aider dans vos tâches globales, je vous conseille toutefois à installer directement python sur votre machine et à l’utiliser au lieu de passer par Docker.
Ce n’est pas parce que vous en avez la possibilité qu’il faut le faire 😄 Ce serait dommage de surcharger votre python avec du Docker et faire, potentiellement, face à des problèmes divers et variés.
Ce que vous allez faire au final dans ce TP, c’est de définir une image sur-mesure pour votre projet.
Vous pouvez avoir un repository Git avec des scripts Python utiles pour une utilisation de tous les jours et ainsi définir un container Docker spécifique à ce besoin avec une image basée sur python et les dépendances nécessaires.

1. Création de l’image

Les images Docker sont définies par un fichier Dockerfile qui contient les instructions pour construire l’image. Vous allez en faire une pour ce projet, qui sera très basique pour commencer.

📋️ Instructions

  1. Créez la branche docker-python.
  2. Récupérez le fichier : dockerfile-python-01.
  3. Déplacez-le dans le dossier docker/python et renommez-le Dockerfile.
  4. Positionnez votre terminal à la racine du projet et construisez l’image Docker correspondante avec la commande suivante :
    docker build \
      --file docker/python/Dockerfile \
      --tag 3olen/tp-git-1-python \
      .
    


    Vous avez maintenant une image Docker nommée 3olen/tp-git-1-python qui est construite à partir du Dockerfile.

  5. Vérifiez que l’image est fonctionnelle avec un container :
    docker run --rm -it 3olen/tp-git-1-python python -c "print('Hello there!')"
    
  6. Complétez la liste de tâches du README.md :
    - [ ] **Python** : Définir des scripts utiles pour le projet.
      - [x] Utilisation de Docker.
      - [ ] Scripting Docker.
      - [ ] Gestion des dépendances.
      - [ ] Scripting projet.
    
  7. Commitez (message : 🐋 [Python] Init image), pushez, PR-ez, review-ez, mergez et nettoyez votre local.

2.1. Scripting Docker

Afin de faciliter l’utilisation des commandes Docker vues plus haut, vous allez définir des scripts permettant d’effectuer ces actions :

  • bin/setup/python : Build l’image Docker 3olen/tp-git-1-python.
  • bin/python : Exécute une commande python dans un container de l’image 3olen/tp-git-1-python.
    • Vérifiez que l’image existe. Si ce n’est pas le cas, faites appel au script de setup.
    • Vérifiez qu’un argument est passé à votre script afin de pouvoir le fournir à la commande python du container :
      bin/python -c print('General Kenobi!') devrait exécuter la commande python -c print('General Kenobi!') dans le container.
      Si vous faites preuve de curiosité, essayez de voir ce qu’il se passe si vous ne fournissez pas d’argument à votre script.

ℹ️ Vous aurez besoin du ROOT_PATH comme défini dans le script bin/setup/hooks pour manipuler correctement les chemins dans vos scripts (notamment pour le docker build).

📋️ Instructions

  1. Créez la branche local-python-docker.
  2. Créez les deux scripts définis ci-dessus.
  3. N’oubliez pas de cocher la tâche du README.md.
  4. Complétez les instructions du repository du README.md avec le contenu fourni ci-après.
  5. Commitez, avec un message plus long et explicite :
    🔨 [Python] Docker build / run
       
    🔨 Scripting
    ============
       
    * ✨ [setup::python] Build docker image
    * ✨ [.::python] Execute python command in container
    
  6. Pushez, puis faites la PR et demandez-moi la review.

📝 Contenu du README.md à ajouter

[//]: # (Dans la partie "### Setup du repository", à la suite de la liste :)
* [bin/setup/python](bin/setup/python) : Build l'image Docker `3olen/tp-git-1-python`.

[//]: # (Juste en-dessous, définissez une nouvelle sous-partie :)
### Utilitaires

Divers scripts sont définis dans le dossier [bin](bin) (et éventuellement dans les sous-dossiers) pour faciliter
l'utilisation d'outils utiles au sein du repository.

* [bin/python](bin/python) : Exécute une commande python dans le container de l'image `3olen/tp-git-1-python`.

2.2. Exécution de scripts python

Exécuter des commandes python c’est bien, mais exécuter des scripts c’est encore mieux ! Vous êtes sûr que ça fonctionne ? On va vérifier ça avec un script “assert”.

  1. Récupérez le fichier : assert-02-python-script.
  2. Déplacez-le dans le dossier bin/assert de votre dépôt et renommez-le 02-python-script.
  3. Assurez-vous qu’il est bien exécutable avec les commandes appropriées.
  4. Récupérez le fichier : assert-02a-hello_there.py.
  5. Déplacez-le dans le dossier bin/assert de votre dépôt et renommez-le 02a-hello_there.py.
  6. Exécutez le script bin/assert/02-python-script pour vérifier…

Normalement, vous devriez avoir un message d’erreur. C’est “normal”, mais vous allez y remédier !

📋️ Instructions

  1. Créez la branche local-python-script.
  2. Tentez d’exécuter le script python : bin/python bin/assert/02a-hello_there.py.
  3. Creusez un peu pour comprendre pourquoi ça ne fonctionne pas.
    • N’hésitez pas à exécuter un shell dans un container pour en apprendre plus : docker run --rm -it 3olen/tp-git-1-python bash
    • Un 🔎 indice ?
  4. Une fois le problème corrigé, commitez : 🔨 [Python] Run python scripts.
  5. Pushez, puis faites la PR et demandez-moi la review.

C’est tout ?

Non, il nous reste à ajouter la gestion des dépendances python pour notre container et bien sûr à définir des scripts utiles pour le projet afin que tout ceci n’ait pas été vain.