Aller au contenu principal

Docker - Installation facile de Python sous Windows

Mettez en place facilement un environnement de développement Python sous Windows avec Docker et les devcontainers VSCode. Codez immédiatement, sans installer Python localement.

· 7 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Cet article a plus d'un an, mais il a été relu le 30 juillet 2026 — son contenu est toujours exact.

Docker - Installation facile de Python sous Windows

⚡
TL;DR

Cet article porte sous Windows la configuration du devcontainer Python déjà vue sous Linux : les mêmes fichiers Dockerfile, compose.yaml, .docker.env et .devcontainer/devcontainer.json sont réutilisés tels quels, mais GNU Make est remplacé par un script batch DOS make.bat. Les commandes make build, make up, make bash et make devcontainer fonctionnent à l'identique depuis une console MS-DOS — vous obtenez un environnement de développement Python sans aucune installation locale de Python.

Dans un article précédent, j'ai fourni quelques fichiers permettant de créer rapidement un environnement Python sous Linux. Aujourd'hui, amusons-nous à utiliser exactement les mêmes fichiers, mais cette fois sous Windows.

Le défi du jour est simple : créer un environnement Python sur ma machine Windows sans installer Python, évidemment, et sans devoir configurer VSCode. Il suffit de lancer un peu de magie et, voilà, en tant que débutant en Python, je peux commencer à coder sans perdre de temps à configurer mon ordinateur.

Dès que vous y écrivez du vrai code, ajoutez les outils de Python - Les outils de qualité de code : ils tournent eux aussi dans le container, donc votre machine Windows reste intacte.

Dans l'article Docker - Python devcontainer, j'ai donc fourni quelques fichiers et nous allons les réutiliser, sans les modifier, dans cet article. Partons du principe qu'ils se trouvent déjà dans un dossier de projet sur votre machine et que vous avez ouvert une console MS-DOS positionnée dessus — voici ce qui se passe quand vous lancez les mêmes commandes que sous Linux, directement depuis DOS.

C'est parti​

Toutes les commandes ci-dessous doivent être lancées depuis une console MS-DOS et vous devez vous trouver dans le dossier de votre projet (cd %USERPROFILE%\Documents\Python).

Construire l'image Docker Python​

La première chose à faire, une seule fois, est de créer l'image Docker. Cela se fait en lançant make build :

Construction de l'image Docker

Créer un container Docker​

Ensuite, une fois par jour, vous devez lancer make up :

Créer un container Docker

Vous ne devez le faire qu'une fois par jour, car le container sera très probablement arrêté quand vous éteindrez votre ordinateur. Lancez simplement make up le lendemain matin pour le réveiller.

Entrer dans le container​

Si vous devez entrer dans votre container Docker (démarré par make up), lancez simplement make bash.

Vous obtenez une console différente, comme illustré ci-dessous (voyez la baleine bleue, par exemple). La capture ci-dessous montre l'affichage du numéro de version de Python :

Entrer dans le container

Souvenez-vous des fichiers créés au chapitre précédent. L'un d'eux s'appelait main.py et contenait un script Python tout simple ; lançons-le :

Exécution de main.py

Il suffit de lancer le binaire python suivi du nom du script.

Information

Vous êtes donc bien à l'intérieur d'un container en cours d'exécution (voyez la baleine bleue). Tapez exit pour quitter le container (celui-ci continuera de tourner) et revenir à votre console MS-DOS.

Démarrer VSCode et commencer votre aventure de développeur​

Lancez simplement make devcontainer (dans votre console MS-DOS ; pas dans un container) et Visual Studio Code démarrera à l'intérieur de votre container Docker. Cette fonctionnalité s'appelle le devcontainer.

Lancement de VSCode - Devcontainer

Dans VSCode, si vous aimez cette façon de travailler, vous pouvez appuyer sur CTRL+` pour ouvrir un terminal (vous pouvez aussi cliquer sur le menu View puis sur l'entrée Terminal ; c'est la même chose).

Utiliser le terminal de VSCode

Ici, si vous voulez exécuter le script main.py, tapez simplement python src/main.py et appuyez sur Enter.

Exécution du script main.py depuis le terminal

Information

Pour les utilisateurs Windows, notez que le container (et donc VSCode) tourne sous Linux. Il y a évidemment de nombreuses différences. Ce qu'il faut savoir, c'est que Linux utilise / comme séparateur de dossiers et non \ comme DOS/Windows. C'est pourquoi nous avons tapé src/main.py et non src\main.py.

Puis-je ajouter des extensions Python dans VSCode ?​

Bien sûr, allez simplement dans la liste des extensions (appuyez sur CTRL+SHIFT+X) et... comme vous le voyez, certaines sont déjà installées. C'est l'un des avantages d'utiliser un devcontainer comme vous le faites en ce moment (voyez le fichier .devcontainer/devcontainer.json créé plus tôt).

Extensions VSCode

Je parle de magie, mais entrons maintenant dans le détail et voyons comment cette structure de fichiers/dossiers est réellement créée. Je pourrais vous fournir une archive ZIP, par exemple, avec tous les fichiers et la structure déjà prêts, mais ce serait moins... amusant, non ?

Créer une structure de fichiers/dossiers​

Créez un dossier sur votre machine Windows, par exemple un dossier Python dans vos documents (en MS-DOS, voici la commande à lancer : mkdir %USERPROFILE%\Documents\Python puis pour y aller : cd %USERPROFILE%\Documents\Python).

Vous pouvez bien sûr lancer l'Explorateur Windows, aller dans votre dossier Documents et créer le dossier et tous les fichiers ainsi :

Explorateur Windows

Créez tous les fichiers nécessaires (ceux de l'article précédent). Nous n'avons PAS modifié ces fichiers : nous pouvons donc utiliser exactement les mêmes, que l'on soit sous Linux ou sous Windows.

Ajoutez simplement un nouveau fichier dans votre dossier Windows et copiez/collez le contenu ci-dessous.

Copiez/collez le contenu ci-dessous dans un fichier appelé .devcontainer/devcontainer.json.

{
"name": "app_python",
"dockerComposeFile": [
"./../compose.yaml",
],
"service": "app_python",
"remoteUser": "python",
"workspaceFolder": "/app",
"customizations": {
"vscode": {
"extensions": [
"aaron-bond.better-comments",
"DavidAnson.vscode-markdownlint",
"eamodio.gitlens",
"EricSia.pythonsnippets3",
"foxundermoon.shell-format",
"gruntfuggly.todo-tree",
"mde.select-highlight-minimap",
"mgesbert.python-path",
"mikestead.dotenv",
"mrmlnc.vscode-duplicate",
"ms-azuretools.vscode-docker",
"ms-python.black-formatter",
"ms-python.debugpy",
"ms-python.isort",
"ms-python.mypy-type-checker",
"ms-python.pylint",
"ms-python.python",
"ms-python.vscode-pylance",
"ms-vscode-remote.remote-containers",
"ms-vscode.makefile-tools",
"njpwerner.autodocstring",
"redhat.vscode-xml",
"redhat.vscode-yaml",
"sirtori.indenticator",
"sonarsource.sonarlint-vscode",
"streetsidesoftware.code-spell-checker-dutch",
"streetsidesoftware.code-spell-checker-french",
"streetsidesoftware.code-spell-checker",
"tomoki1207.pdf",
"tyriar.sort-lines"
],
"settings": {
"[dockerfile]": {
"files.eol": "\n",
"editor.defaultFormatter": "ms-azuretools.vscode-docker"
},
"[json]": {
"editor.defaultFormatter": "vscode.json-language-features"
},
"[jsonc]": {
"editor.defaultFormatter": "vscode.json-language-features",
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80,
"editor.wrappingIndent": "indent"
},
"[markdown]": {
"editor.defaultFormatter": "DavidAnson.vscode-markdownlint",
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80,
"editor.wrappingIndent": "indent"
},
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll": "always",
"source.organizeImports": "always"
}
},
"[shellscript]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"[xml]": {
"editor.defaultFormatter": "redhat.vscode-xml",
"editor.wordWrap": "wordWrapColumn",
"editor.wordWrapColumn": 80,
"editor.wrappingIndent": "indent"
},
"[yaml]": {
"editor.defaultFormatter": "redhat.vscode-yaml",
"editor.insertSpaces": true,
"editor.tabSize": 2
},
"cSpell.language": "en,fr,nl",
"docker-explorer.enableTelemetry": false,
"editor.bracketPairColorization.enabled": true,
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"editor.defaultFoldingRangeProvider": null,
"editor.detectIndentation": false,
"editor.folding": true,
"editor.foldingStrategy": "auto",
"editor.formatOnSave": true,
"editor.guides.bracketPairs": "active",
"editor.guides.bracketPairsHorizontal": "active",
"editor.guides.highlightActiveIndentation": true,
"editor.guides.indentation": true,
"editor.multiCursorModifier": "ctrlCmd",
"editor.renderWhitespace": "all",
"editor.rulers": [
120,
70
],
"editor.stickyScroll.enabled": true,
"editor.tabCompletion": "on",
"editor.tabSize": 4,
"editor.wordBasedSuggestionsMode": "allDocuments",
"editor.wordWrapColumn": 120,
"explorer.compactFolders": false,
"explorer.confirmDelete": true,
"explorer.confirmDragAndDrop": true,
"extensions.autoCheckUpdates": false,
"files.autoSave": "onFocusChange",
"files.defaultLanguage": "${activeEditorLanguage}",
"files.eol": "\n",
"files.exclude": {
"**/.cache": true,
"**/.git": true
},
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"markdown.extension.toc.levels": "2..6",
"markdownlint.config": {
"MD033": false,
"MD036": false
},
"mypy-type-checker.args": [
"--config-file=.config/.mypy.ini"
],
"python.analysis.autoFormatStrings": true,
"python.analysis.autoImportCompletions": true,
"python.analysis.autoIndent": true,
"python.analysis.autoSearchPaths": true,
"python.analysis.fixAll": [
"source.convertImportFormat"
],
"python.analysis.typeCheckingMode": "strict",
"python.defaultInterpreterPath": "/usr/local/bin/python3",
"python.formatting.provider": "black",
"python.languageServer": "Pylance",
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.pylintEnabled": true,
"python.sortImports.args": [
"--profile",
"black"
],
"redhat.telemetry.enabled": false,
"sonarlint.output.showAnalyzerLogs": true,
"sonarlint.disableTelemetry": true,
"sonarlint.rules": {
"docker:S7031": {
"level": "off"
}
},
"telemetry.telemetryLevel": "off",
"terminal.integrated.profiles.linux": {
"bash": {
"path": "/bin/bash",
"icon": "terminal-bash"
}
},
"terminal.integrated.defaultProfile.linux": "bash",
"terminal.integrated.fontFamily": "MesloLGS NF",
"update.enableWindowsBackgroundUpdates": false,
"update.mode": "none",
"yaml.format.enable": true,
"yaml.completion": true,
"yaml.validate": true,
"workbench.editor.enablePreview": false,
"workbench.editor.wrapTabs": true
}
}
}
}

Ce fichier configure un environnement de développement VS Code pour un projet Python exécuté dans un conteneur Docker. Il spécifie le service Docker à utiliser, l'utilisateur distant, le répertoire de travail, puis installe une série d'extensions VS Code et configure leurs paramètres pour standardiser le formatage du code, l'analyse statique et l'expérience de l'éditeur.

Copiez/collez le contenu ci-dessous dans un fichier appelé src/main.py.

print("I'm your Python code")

Ce snippet affiche simplement un message texte à l'écran pour montrer que c'est du code Python qui fonctionne.

Oui, un fichier vide... Le fichier doit être présent mais, pour l'instant, nous n'avons aucune dépendance à y mettre.

Copiez/collez le contenu ci-dessous dans un fichier appelé .docker.env (dans le monde Linux, ce type de fichier est caché puisqu'il commence par un point).

# Application root directory in the container (PHP or NGINX) (--app-home)
DOCKER_APP_HOME=/app
# Name of the container to show in the bash prompt
DOCKER_CONTAINER_NAME=app
# Set OS groupid in your Docker Linux containers (1000 = root) (--os-groupid)
DOCKER_OS_GROUPID=1000
# Set OS userid in your Docker Linux containers (1000 = root) (--os-userid)
DOCKER_OS_USERID=1000
# Set OS username in your Docker Linux containers (--os-username)
DOCKER_OS_USERNAME="python"
# Version of Python to use
DOCKER_PYTHON_VERSION=3.13-slim

Ce fichier définit les variables de configuration pour un conteneur Docker qui exécute une application Python. Il spécifie le répertoire de base de l'application, le nom du conteneur, les identifiants d'utilisateur et de groupe du système d'exploitation, le nom d'utilisateur et la version de Python à utiliser.

Copiez/collez le contenu ci-dessous dans un fichier appelé compose.yaml.

Vos valeurs pour cette page
défaut
S'applique aux commandes de cette pageEnregistré uniquement sur cet appareil
name: app_python
services:
app_python:
build:
context: .
target: development
args:
# Version of Python to use
- DOCKER_PYTHON_VERSION=${DOCKER_PYTHON_VERSION}
# Application root directory in the container (PHP or NGINX) (--app-home)
- DOCKER_APP_HOME=${DOCKER_APP_HOME:-/app}
# Name of the container to show in the bash prompt
- DOCKER_CONTAINER_NAME=${DOCKER_CONTAINER_NAME:-python}
# Set OS groupid in your Docker Linux containers (1000 = root) (--os-groupid)
- DOCKER_OS_GROUPID=${DOCKER_OS_GROUPID:-1000}
# Set OS userid in your Docker Linux containers (1000 = root) (--os-userid)
- DOCKER_OS_USERID=${DOCKER_OS_USERID:-1000}
# Set OS username in your Docker Linux containers (--os-username)
- DOCKER_OS_USERNAME=${DOCKER_OS_USERNAME:-python}
user: ${DOCKER_OS_USERID:-1000}:${DOCKER_OS_GROUPID:-1000}
env_file:
- .docker.env
container_name: app_python
volumes:
# Our codebase on our host
- .:${DOCKER_APP_HOME}
# Keep installed VSCode extensions in a volume to avoid to reinstall them
- vscode-extensions:/home/${DOCKER_OS_USERNAME}/.vscode-server/extensions
# Remember the bash history
- bashhistory:/home/${DOCKER_OS_USERNAME}/commandhistory
volumes:
# Use a Docker volume self-managed volume to store vscode's cache
vscode-extensions:
# Use a Docker volume self-managed volume to store bash history
bashhistory:

Ce fichier Docker Compose définit un service Python appelé app_python qui construit une image Docker à partir du répertoire courant en utilisant l'étape de développement du Dockerfile. Il configure le conteneur avec des variables d'environnement pour la version de Python, le répertoire racine, l'identité de l'utilisateur et du groupe OS, puis monte le code source et deux volumes persistants pour préserver les extensions VSCode et l'historique bash entre les redémarrages.

Copiez/collez le contenu ci-dessous dans un fichier appelé Dockerfile.

# syntax=docker/dockerfile:1
# cspell:ignore PYTHONDONTWRITEBYTECODE,PYTHONUNBUFFERED,HISTFILE
# cspell:ignore addgroup,adduser,keyscan,hadolint,gecos,endregion
# Those variables are initialized in the .docker.env file
ARG DOCKER_APP_HOME="/app"
ARG DOCKER_CONTAINER_NAME="python"
ARG DOCKER_OS_GROUPID=1000
ARG DOCKER_OS_USERID=1000
ARG DOCKER_OS_USERNAME="python"
ARG DOCKER_PYTHON_VERSION=3.10-slim
# region - Our Python base image. We'll install Linux and Python dependencies here
# and do some other configuration work
FROM python:${DOCKER_PYTHON_VERSION} AS base
# Prevents Python from writing pyc files.
ENV PYTHONDONTWRITEBYTECODE=1
# Keeps Python from buffering stdout and stderr to avoid situations where
# the application crashes without emitting any logs due to buffering.
ENV PYTHONUNBUFFERED=1
ARG DOCKER_APP_HOME
WORKDIR "${DOCKER_APP_HOME}/src"
# hadolint ignore=DL3008
RUN --mount=type=cache,target=/var/cache/apk,rw \
set -e -x \
&& printf "\e[0;105m%s\e[0;0m\n" "Install required Linux binaries..." \
&& apt-get update -yqq \
&& apt-get install -y --no-install-recommends bash git openssh-client tree \
&& apt-get clean \
&& rm -rf /tmp/* /var/lib/apt/lists/*
# Install Python dependencies
#
# Download dependencies as a separate step to take advantage of Docker's caching.
# Leverage a cache mount to /root/.cache/pip to speed up subsequent builds.
# Leverage a bind mount to requirements.txt to avoid having to copy them into
# into this layer.
RUN --mount=type=cache,target=/root/.cache/pip \
--mount=type=bind,source=src/requirements.txt,target=requirements.txt \
printf "\e[0;105m%s\e[0;0m\n" "Install Python dependencies" \
&& python -m pip install --no-cache-dir -r requirements.txt
# Keep the container running
ENTRYPOINT ["tail", "-f", "/dev/null"]
# endregion
# region - Define our development image
FROM base AS development
ENV SHELL /bin/bash
# Our user will be part of the root group since we're building the development image
ARG DOCKER_OS_GROUPID
ARG DOCKER_OS_USERID
ARG DOCKER_OS_USERNAME
RUN set -e -x \
&& mkdir -p "/home/.vscode-server/bin" \
&& mkdir -p "/home/.vscode-server/extensions" \
&& mkdir -p "/home/.vscode-server/extensionsCache" \
&& printf "\e[0;105m%s\e[0;0m\n" "Create our ${DOCKER_OS_USERNAME} application user" \
&& mkdir -p "/home/${DOCKER_OS_USERNAME}/.vscode-server/bin" \
&& mkdir -p "/home/${DOCKER_OS_USERNAME}/.vscode-server/extensions" \
&& mkdir -p "/home/${DOCKER_OS_USERNAME}/.vscode-server/extensionsCache" \
# Create the application user home directory
&& mkdir -p "/home/${DOCKER_OS_USERNAME}" \
# Create our application user group
&& addgroup "${DOCKER_OS_USERNAME}" --gid "${DOCKER_OS_GROUPID}" \
# Create our application user
&& adduser \
--system \
--disabled-password \
--gecos "" \
--home "/home/${DOCKER_OS_USERNAME}" \
--uid "${DOCKER_OS_USERID}" \
"${DOCKER_OS_USERNAME}" \
# And, finally, set the correct permissions to the home folder of our user
&& chown -R "${DOCKER_OS_USERNAME}:${DOCKER_OS_USERNAME}" "/home/${DOCKER_OS_USERNAME}"
USER "${DOCKER_OS_USERNAME}"
ARG DOCKER_CONTAINER_NAME
RUN /bin/bash -c "echo \"PS1='\n\e[0;33m🐳 ${DOCKER_CONTAINER_NAME} \e[0;32mDEV\e[0m - \e[0;36m$(whoami)\e[0m \w # '\" >> /home/${DOCKER_OS_USERNAME}/.bashrc"
# Save the bash history in file /home/${OS_USERNAME}/commandhistory/.bash_history
# Like this we'll be able to map that folder using a volume in our
# compose.yaml file and then make the history persistent.
RUN set -e -x \
&& SNIPPET="export PROMPT_COMMAND='history -a' && export HISTFILE=/home/${DOCKER_OS_USERNAME}/commandhistory/.bash_history" \
&& mkdir -p "/home/${DOCKER_OS_USERNAME}/commandhistory" \
&& touch "/home/${DOCKER_OS_USERNAME}/commandhistory/.bash_history" \
&& echo "${SNIPPET}" >> "/home/${DOCKER_OS_USERNAME}/.bashrc" \
&& echo "${SNIPPET}" >> "/home/${DOCKER_OS_USERNAME}/.bashrc"
# endregion

Ce Dockerfile crée une image Docker pour une application Python en deux étapes. D'abord, on construit une image de base qui installe Python, les dépendances Linux et les packages Python depuis un fichier requirements.txt en utilisant le cache Docker pour accélérer les builds. Ensuite, on crée une image de développement dérivée de cette base en ajoutant un utilisateur non-root, en configurant VS Code Server et l'historique bash persistent.

Créer notre fichier batch DOS​

Voici la différence avec Linux : au lieu d'utiliser GNU Make, nous allons simplement utiliser un script batch MS-DOS. Nous l'appellerons make.bat afin de pouvoir utiliser des actions comme make build ou make up comme sous Linux ; mais cette fois, sous DOS.

Créez ce fichier supplémentaire :

@echo off
cls
if "%1"=="" goto :help
set APP_NAME=app_python
REM The code below is the hex representation of the APP_NAME here above i.e. "app_python"
REM You can get that value by running "make bash" then 'python -c "print('app_python'.encode().hex())"'
REM Needed by the "make devcontainer" action
set DEV_CODE=6170705f707974686f6e
if "%1"=="bash" goto bash
if "%1"=="build" goto build
if "%1"=="devcontainer" goto devcontainer
if "%1"=="up" goto up
if "%1"=="start" goto start "%2"
call :error "Invalid action."
goto :help
:help
echo Usage: %0 command
echo.
echo Available Commands:
echo.
echo bash Enter the Docker Python container
echo build Build the Python Docker image (to be done only once)
echo devcontainer Start VSCode and open the Docker container
echo up Create and start the Docker container (to be done once a day if you've turned off your computer)
echo start Start a Python script in the Docker container (call it like 'make start main.py')
goto :eof
:bash
echo Entering in our %APP_NAME% Docker Python container... Type exit to quit the session.
docker compose --env-file .docker.env exec -it %APP_NAME% /bin/bash
goto :eof
:build
echo Building our Python Docker image
docker compose --env-file .docker.env build
goto :eof
:devcontainer
echo Start vscode and open the Docker container
code --folder-uri vscode-remote://attached-container+%DEV_CODE%/app
goto :eof
:up
echo Create our container...
docker compose --env-file .docker.env up --detach
goto :eof
:start
if "%2"=="" (
call :error "Please specify the name of the script to execute, f.i. 'make start main.py'"
goto :eof
)
docker compose --env-file .docker.env exec -it %APP_NAME% python %2
goto :eof
:error
REM Trim double quotes from the beginning and end of the message
set "ERROR_MESSAGE=%*"
set "ERROR_MESSAGE=%ERROR_MESSAGE:~1,-1%"
echo ␛[31mERROR - %ERROR_MESSAGE%␛[0m
echo.
goto :eof
:eof

Ce script Batch est un utilitaire pour gérer un conteneur Docker Python. Il vérifie l'argument passé et exécute la commande correspondante : lancer un shell interactif, construire l'image, ouvrir le conteneur dans VSCode, démarrer le conteneur, ou exécuter un script Python. Si aucun argument ou un argument invalide est fourni, il affiche l'aide.

Notre configuration actuelle​

À ce stade, voici notre projet dans VSCode :

Le projet dans VSCode

Et voici à quoi il ressemble dans l'Explorateur Windows :

Explorateur Windows

Ouvrez une console MS-DOS (appuyez sur la touche Windows de votre clavier ou cliquez sur le menu Démarrer, puis tapez cmd)

Lancer MS DOS

Ouvrez la console et allez dans le dossier de votre projet, c'est-à-dire lancez cd %USERPROFILE%\Documents\Python.

Voici à quoi ressemble le projet maintenant :

À quoi ressemble le projet sous DOS

Puis-je utiliser une autre version de Python ?​

Bien sûr, éditez simplement le fichier .docker.env et vous y trouverez cette ligne : DOCKER_PYTHON_VERSION=3.13-slim. Changez le numéro de version, enregistrez le fichier, puis lancez make build, ensuite make up et, enfin, make devcontainer pour tout reconstruire et utiliser la version plus récente.


Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?