Pythonで開発を始めるとき、毎回venvで仮想環境を作ったり、PCごとにバージョン差異に悩まされたりしていないでしょうか。
Dockerを使えば、Python本体からライブラリ、OSレベルの依存関係までを1つのイメージに閉じ込めて管理できます。
本記事では、「DockerでPython開発環境を構築するための最小かつ実用的な手順」を、Docker初心者でも迷わないように図解とサンプルコード付きで詳しく解説します。
Python開発環境をDockerで構築するメリット
DockerでPython開発環境を作るメリット

DockerでPython開発環境を作る最大の魅力は、「同じ環境をどこでも再現できること」です。
Pythonのバージョンやライブラリの組み合わせをイメージに閉じ込めてしまうため、次のようなメリットが生まれます。
まず、PCを変えても、OSが違っても、同じDockerイメージさえあれば同一のPython環境を一瞬で再現できます。
また、環境が壊れたりライブラリの依存関係がぐちゃぐちゃになっても、コンテナを削除してイメージから作り直せば、すぐにクリーンな状態に戻せます。
さらに、Pythonだけでなく、システムパッケージ(curlやbuild-essentialなど)も含めて「環境ごとバージョン管理」できるため、「このライブラリはLinuxでしか動かない」「ローカルMacだと動くのに本番サーバでは動かない」といったトラブルも大きく減らせます。
仮想環境(venv)不要になる理由

従来のPython開発では、プロジェクトごとにpython -m venv venvで仮想環境を作り、その中でpip installを行うのが一般的でした。
これは、「同じPC上でプロジェクトごとにライブラリのバージョンを分離する」ための仕組みです。
一方で、DockerはPythonよりも一段下のOSレイヤー全体を分離します。
各コンテナは、それぞれが独立した小さなLinux環境を持ち、そこにPython本体とライブラリをインストールします。
結果として、プロジェクトごとに別のコンテナを用意すれば、そもそもグローバルのPythonに触れることがなくなり、仮想環境(venv)を使う理由がほぼ消えていきます。
もちろん、Dockerコンテナの中でさらにvenvを使うことも可能ですが、通常の開発用途では「コンテナが仮想環境の役割を兼ねる」と考えて問題ありません。
ローカル環境を汚さない開発フロー

Dockerを使うと、ローカルPCにインストールするものを最小限に抑えられます。
基本的には、Docker自体とエディタ(VS Codeなど)さえあれば足ります。
開発フローとしては、ローカルにはソースコードだけを置き、Pythonやpip、各種ライブラリはすべてコンテナ内に閉じ込める形になります。
これにより、ローカルのグローバルPythonやグローバルpipを一切使わない運用が可能になります。
例えば、あるプロジェクトで実験的なバージョンのライブラリをたくさん試したとしても、それはコンテナの中だけの話です。
ローカルの他のプロジェクトに影響を与えないので、環境を壊す不安なく、思い切って試行錯誤することができます。
Python用Dockerイメージの選び方と準備
python公式イメージの種類

Docker Hubには、Python用の公式イメージが多数公開されています。
代表的なタグは次の通りです。
| タグ例 | ベースOS / 特徴 | 用途の目安 |
|---|---|---|
| python:3.12 | Debian系(フルサイズ) | 開発用・学習用で使いやすい標準 |
| python:3.12-slim | Debian系・不要パッケージ削減版 | 軽量化したい開発・本番環境 |
| python:3.12-alpine | Alpine Linuxベース・非常に軽量 | 要件が合う場合の軽量構成 |
| python:3.11 | 一世代前など、バージョン固定に使う | 既存システム準拠 |
| python:3.12-bullseye | Debian bullseye明示・長期サポート向き | OSバージョンまで厳密に揃えたいとき |
学習や一般的なWeb開発では、まずpython:3.xもしくはpython:3.x-slimを選ぶのがおすすめです。
alpineは非常に軽量ですが、ビルドに追加作業が必要なライブラリも多く、初心者には少しハードルが高くなります。
プロジェクトに合ったバージョン選定

Pythonバージョンを選ぶときは、プロジェクトの状況に応じて考えます。
新規プロジェクトでは、基本的に最新の安定版(例: 3.12系)を選ぶのが合理的です。
最新の言語機能や最適化が利用でき、ライブラリ側も最新バージョンへの対応が進んでいるためです。
一方で、既存システムの開発や保守の場合は、本番サーバで使われているPythonバージョンに合わせることが重要です。
例えば本番がPython 3.10ならpython:3.10を、3.11ならpython:3.11をDockerイメージとして利用するようにします。
このように、Dockerイメージのタグを工夫することで、「Pythonバージョンの固定」が簡単かつ明示的に行えます。
Docker DesktopとDocker CLIのインストール確認

PythonのDocker環境を構築する前に、Docker本体が使える状態かを確認します。
ここではWindows/MacのDocker Desktop、LinuxのDocker Engineを問わず、コマンドラインでの確認手順を紹介します。
まず、ターミナル(またはPowerShell)で次のコマンドを実行します。
docker -v
Dockerのバージョン情報が表示されれば、CLIは正しくインストールされています。
続いて、Dockerが正しくコンテナを起動できるかを確認するために、次のコマンドを実行します。
docker run --rm hello-world
問題なく動作すれば、Docker Engineが正常に動いていることが確認できます。
ここでエラーが出る場合は、Docker Desktopが起動していない、権限設定に問題があるなどの可能性があるため、先にそちらを解決しておきましょう。
DockerでPython開発環境を構築する基本手順
最小構成のDockerfile例

ここでは、最小限の構成でPython開発用のDockerfileを作成します。
次のようなファイル構成を想定します。
| ファイル名 | 役割 |
|---|---|
| Dockerfile | Dockerイメージの設計図 |
| requirements.txt | Pythonパッケージ一覧 |
| app.py | 動作確認用のPythonスクリプト |
まずはシンプルなDockerfileを用意します。
# ベースとなるPython公式イメージを指定
# ここでは3.12のslim版を使用 (軽量で扱いやすい)
FROM python:3.12-slim
# コンテナ内の作業ディレクトリを指定
WORKDIR /app
# 依存パッケージ一覧をコンテナにコピー
# (requirements.txtがある前提)
COPY requirements.txt .
# 必要なパッケージをインストール
# --no-cache-dir でキャッシュを残さず、イメージを軽量に保つ
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションのソースコードをコピー
COPY . .
# デフォルトの実行コマンドを指定
# ここでは app.py を起動する例
CMD ["python", "app.py"]
このDockerfileは、Pythonのベースイメージを元に、requirements.txtで指定したライブラリをインストールし、最後にpython app.pyを実行するという、ごく標準的な構成になっています。
requirements.txtでPythonパッケージを管理する

Pythonの依存パッケージ管理には、requirements.txtを用いるのが最もシンプルです。
たとえば、次のような内容になります。
requests==2.32.3
pandas==2.2.3
これをDockerfileのRUN pip install -r requirements.txtで読み込むことで、コンテナ内に必要なライブラリを一括インストールできます。
また、ローカル開発時にもpip freeze > requirements.txtのようにして、現在の依存関係をファイルに吐き出し、チームメンバーと共有することが可能です。
Dockerではこのファイルがそのままイメージ作成時のインストールに使われるため、環境の再現性が非常に高くなります。
docker buildでPythonイメージを作成する手順

Dockerfileを作成したら、次はDockerイメージをビルドします。
ターミナルでDockerfileがあるディレクトリに移動し、次のコマンドを実行します。
docker build -t python-app:latest .
ここでのポイントは次の通りです。
-t python-app:latestはイメージ名とタグを指定しています。- 最後の
.は、ビルドコンテキスト(=Dockerfileやソースコードが置いてあるディレクトリ)を意味します。
ビルドが完了すると、ローカルのDockerイメージ一覧にpython-app:latestが追加されます。
docker images
このコマンドを実行すると、作成されたイメージが確認できます。
REPOSITORY TAG IMAGE ID CREATED SIZE
python-app latest 123456789abc 10 seconds ago 250MB
docker runでコンテナ内Python環境を起動する

ビルドしたイメージからコンテナを起動するには、docker runを使います。
docker run --rm python-app:latest
ここでは、DockerfileのCMD ["python", "app.py"]が実行されます。
--rmを付けることで、コンテナの停止時に自動的に削除され、不要なコンテナが溜まるのを防げます。
試しに、app.pyを次のようにしておくと、Dockerによる実行結果が確認しやすくなります。
# app.py
# 動作確認用のシンプルなスクリプト
import platform
import sys
def main():
print("Hello from Dockerized Python!")
print(f"Python version: {sys.version}")
print(f"Platform: {platform.platform()}")
if __name__ == "__main__":
main()
この状態でdocker runを実行すると、次のような出力が得られます。
Hello from Dockerized Python!
Python version: 3.12.0 (main, ...)
Platform: Linux-6.6.0-...-x86_64-with-glibc2.36
ここでのポイントは、ホストOSに依存せず、常にコンテナ内のLinux+Python環境で実行されているという点です。
ボリュームマウントでソースコードを共有する方法

開発中に毎回イメージをビルドし直すのは効率が悪いため、ボリュームマウントを使って、ローカルのソースコードをコンテナ内と共有するのが一般的です。
例えば、次のようなコマンドでコンテナを起動します。
docker run --rm -it \
-v $(pwd):/app \
-w /app \
python:3.12-slim \
bash
ここでのオプションの意味は次の通りです。
-v $(pwd):/app: 現在のディレクトリをコンテナ内の/appにマウント-w /app: コンテナ内の作業ディレクトリを/appに設定-it bash: 対話的なbashシェルを起動
この状態でコンテナ内からlsすると、ローカルと同じソースコードが見えるようになります。
ローカルでファイルを編集すると、その変更が即座にコンテナ内にも反映されるため、「ローカル編集+コンテナ実行」という自然な開発スタイルが実現できます。
コンテナ内でpip install・実行する流れ

ボリュームマウントしたコンテナ内では、通常のLinux環境と同様に作業できます。
具体的な流れの一例は次のようになります。
# コンテナに入る (前節の例と同じ)
docker run --rm -it \
-v $(pwd):/app \
-w /app \
python:3.12-slim \
bash
コンテナに入った後の操作例です。
# コンテナ内のシェル上での操作例
# 必要なライブラリをインストール
pip install requests
# 動作確認用のスクリプトを実行
python app.py
このとき、pipでインストールされたライブラリはコンテナ内にのみ反映され、ホストのPython環境には一切影響しません。
気軽にライブラリを試しつつ、問題があればコンテナごと破棄する、という使い方ができるため、試行錯誤がとても快適になります。
docker-composeでPython開発環境をさらにシンプルに
docker-compose.ymlでPythonサービスを定義する

Dockerコマンドを毎回手入力するのは面倒になりがちです。
そこで、docker-compose.ymlを使って設定をファイル化すると、環境構築がさらにシンプルになります。
まずは、単一のPythonサービスを定義した最小構成の例を示します。
# docker-compose.yml
version: "3.9"
services:
app:
image: python:3.12-slim # ベースイメージ
working_dir: /app # コンテナ内の作業ディレクトリ
volumes:
- ./:/app # カレントディレクトリをマウント
command: bash -c "pip install --no-cache-dir -r requirements.txt && python app.py"
stdin_open: true # 対話的な入出力を許可
tty: true # 擬似端末を割り当て
この定義では、docker compose upを実行するだけで、次の処理が自動的に行われます。
- Python 3.12 slimイメージを取得(なければ自動ダウンロード)
- カレントディレクトリを
/appとしてマウント pip install -r requirements.txtで依存パッケージをインストールpython app.pyを実行
手で長いdocker runコマンドを書く代わりに、設定をファイル化して再利用できる点が大きなメリットです。
docker compose upだけで環境を立ち上げる手順

先ほどのdocker-compose.ymlがあるディレクトリで、次のコマンドを実行します。
docker compose up
(古い環境ではdocker-compose upというコマンド名の場合もあります。)
これにより、定義されたappサービスが起動し、ログがターミナルに表示されます。
実行を止めたい場合は、Ctrl + Cで中断すればコンテナが停止します。
バックグラウンドで動かしたい場合は、-dオプションを付けます。
docker compose up -d
この場合、コンテナはバックグラウンドで動作し続けるので、別のターミナルからログを確認したり、コンテナに入って作業したりできます。
デバッグやログ確認の基本コマンド

docker composeを使うと、複数のコンテナをまとめて扱えるだけでなく、デバッグ用のコマンドも非常に分かりやすくなります。
代表的なものをいくつか紹介します。
# 起動中コンテナの一覧
docker compose ps
# ログの確認 (appサービスのみ)
docker compose logs app
# ログをリアルタイムで追いかける
docker compose logs -f app
# appサービスのコンテナに入って対話的に操作
docker compose exec app bash
# すべてのコンテナを停止
docker compose stop
# すべてのコンテナとネットワークを削除
docker compose down
特にdocker compose exec app bashは、実行中のコンテナに入って、その場でpip installやpythonの実行ができるため、デバッグ時に非常に便利です。
チーム開発でのDocker環境共有のポイント

Dockerとdocker-composeを組み合わせることで、チーム開発における「環境差異問題」を大幅に軽減できます。
ポイントは、環境構築に必要な情報をすべてリポジトリに含めることです。
具体的には、次のファイルをGitなどのバージョン管理に含めます。
- Dockerfile
- docker-compose.yml
- requirements.txt (もしくはpoetry.lockなど)
- 必要に応じて.envファイルの雛形
これにより、新しいメンバーが参加したときの手順は、基本的に次の2ステップで済むようになります。
- リポジトリをクローンする
- プロジェクトディレクトリで
docker compose upを実行する
こうすることで、「Pythonのバージョンが違った」「ローカルにインストールしたライブラリのバージョンが微妙に違った」といった典型的なトラブルを回避できます。
さらに、本番環境も同じDockerイメージをベースに構築すれば、開発・ステージング・本番の差異も小さく抑えられます。
まとめ
Dockerを使ったPython開発環境の構築は、一度仕組みを理解してしまえば「venvいらずでどこでも同じ環境を再現できる強力な方法」になります。
Python公式イメージを選び、Dockerfileとrequirements.txtで環境を定義し、docker build・docker runで動作確認を行う流れが基本です。
さらにdocker-compose.ymlを用意すれば、docker compose upだけで開発環境を立ち上げられ、チーム全員が同じコマンド・同じ挙動で開発できるようになります。
ローカル環境を汚さず、安心して試行錯誤できるDockerベースのPython開発フローを、ぜひ自身のプロジェクトでも取り入れてみてください。
