本ページはプロモーションが含まれています

Docker

DockerでPython環境構築の手順|Mac/Win対応

CATEGORY
REV.
DRAWN BY
TOM
SHEETS
10枚
Docker × Python(環境構築の手順)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

「自分のPCでは動いたのに、サーバーだと動かない…」

「新しいプロジェクトのたびにPythonのバージョン管理で混乱する」

「チームメンバーと開発環境をそろえるのが面倒」

こんにちは。これまで多くのPythonプロジェクトに携わってきましたが、開発初期の「環境構築」はいつも悩みのタネでした。

venvやpyenvを駆使しても、OSの違いやライブラリの依存関係でエラーが起きることは日常茶飯事でした。

しかし、Dockerと出会ってから、私のPython開発は劇的に変わりました。

この記事は、過去の私と同じように「DockerでPython環境を構築したいけれど、何から手をつければいいか分からない」という方に向けて書いています。

結論から言うと、DockerでのPython環境構築は(1) Docker Desktopを入れる (2) python:3.14-slim などの公式イメージを元にDockerfileを書く (3) docker compose up で起動する、の3ステップで終わる。Mac・Windowsどちらでも手順は同じだ。

Dockerfileの書き方、venvが不要になる理由、そしてPermission deniedやビルドエラーといった実際につまずいた地雷の避け方まで、現場で踏んだ順番のまま並べてある。

読み終える頃には、次のプロジェクトのDockerfileがそのまま書けているはずだ。

この記事でわかること

  • DockerでPython環境をゼロから構築する手順(Mac・Windows共通)
  • venvが不要になる理由と、コンテナ内でのライブラリ管理の考え方
  • Permission denied・ビルドエラーなど、つまずきやすいポイントの対処法

PARTS LIST /目次

DockerでPython環境を構築するメリット

Dockerは、コンテナという技術を使ってアプリケーションを動かすためのプラットフォームです。

Python開発にDockerを導入すると、開発効率と安定性が飛躍的に向上します。主なメリットを3つ紹介します。

あわせて読む

ローカル環境を汚さずに開発できる

Dockerコンテナは、あなたのPCとは隔離された空間です。

Python本体や、pandas Flask といったライブラリはすべてコンテナの中にインストールされます。

PC本体には何もインストールしないため、ローカル環境は常にクリーンな状態に保てます。

プロジェクトが終わればコンテナを削除するだけ。PCに不要なファイルが残る心配もありません。

環境差異によるエラーを防げる

開発で最も避けたい「環境差異」の問題を根本から解決できます。

「AさんのWindows PCでは動くのに、BさんのMacでは動かない」

「開発PCでは動いたのに、本番サーバーでエラーが出る」

この2つの環境差異は、OSやPythonのバージョン、ライブラリのわずかな違いが原因で発生します。

DockerではDockerfileという設定ファイルに、「どのOSを使い、どのバージョンのPythonを入れ、どのライブラリをインストールするか」をすべて記述します。

このファイルさえ共有すれば、誰でも、どこでも、ほぼ同じ環境を再現できるのです。

複数プロジェクトの切り替えが簡単

開発者は複数のプロジェクトを同時に担当することも多いです。

  • プロジェクトA:Python 3.8 + Django 3.2
  • プロジェクトB:Python 3.10 + FastAPI 0.88
  • プロジェクトC:Python 3.7 + 古いライブラリ (事情があって更新できない)

従来のvenv (仮想環境) では、これらを切り替えるたびに activate や deactivate を実行する必要があり、手間がかかりました。

Dockerなら、プロジェクトごとにコンテナが独立しています。プロジェクトAのコンテナとプロジェクトBのコンテナを同時に起動することも可能です。

環境が互いに干渉しないため、プロジェクトの切り替えがストレスなく行えます。

DockerでPython環境を作るための準備

必要なのはDocker Desktopのインストールと、公式Pythonイメージの選定、この2つだけだ。

メリットを理解したところで、早速準備を始めましょう。必要なものは多くありません。

Docker Desktop のインストール

まずはDockerを動かすためのソフトウェア「Docker Desktop」をインストールします。

公式サイトから、お使いのOS (Windows, Mac, Linux) に合わせたインストーラーをダウンロードし、画面の指示に従ってインストールしてください。

インストールが完了したら、ターミナルを開き、docker --version と入力してバージョン情報が表示されれば準備OKです。

Windowsの場合はWSL 2バックエンドで動かすのが標準で、公式ドキュメントではWindows 10 22H2以降またはWindows 11 23H2以降、WSL 2.1.5以降、メモリ8GBなどが要件として挙げられています。なお、Docker Desktopは個人利用・教育・小規模事業(従業員250人未満かつ年間売上1,000万ドル未満)なら無料ですが、それを超える企業での業務利用には有料プランが必要です。

Python公式イメージの種類を理解する

Dockerでは「イメージ」と呼ばれるひな形を基にコンテナを作ります。Pythonには幸いなことに公式イメージが用意されています。

ただし、公式イメージにはいくつか種類(タグと呼ばれます)があり、特徴が異なります。

  • python:3.13 (full版)
    • Debianベースの標準的なイメージ。
    • ビルドに必要なライブラリなどが一通り含まれており、多くのPythonパッケージが問題なく動きます。
    • ただし、イメージのサイズは大きめです (約1GB)。
  • python:3.13-slim
    • full 版から不要なファイルを削減した軽量版。
    • イメージサイズが小さい (約140MB) ため、ビルド時間の短縮やディスク容量の節約になります。
    • 開発環境では、まず slim 版を試すのがおすすめです。
  • python:3.13-alpine
    • Alpine Linuxという軽量なOSをベースにしたイメージ。
    • サイズは驚異的に小さい (約55MB) です。
    • ただし、標準のLinux (Debian系) と仕組みが異なる部分があり、特定のPythonライブラリ (pandas など) のインストールでエラーが起きやすい「罠」があります (後述)。
イメージサイズ目安特徴
python:3.13(full版)約1GBビルドツール込みで安定
python:3.13-slim約140MB開発ではまずこれ
python:3.13-alpine約55MB最軽量だがビルドエラーの罠あり
特別な理由がなければ python:3.13-slim (バージョン数字は適宜変更) を選ぶと良いでしょう。

python:latest や python:3 は、その時点の安定版の最新系列を指します(2026年9月時点では3.14のDebian trixieベース)。3.13系も引き続き提供されています。この記事のサンプルは3.13で書いていますが、新規プロジェクトなら python:3.14-slim に置き換えても基本的にはそのまま使えます(利用ライブラリが3.14に対応しているかだけは確認してください)。latest はPythonやDebianの更新で中身が変わるため、python:3.14-slim-trixie のようにバージョンとDebianのコードネームまで固定しておくと、ある日突然ビルドが壊れる事態を防げます。

作業ディレクトリの構成例

Dockerを使った開発では、特定のファイル構成がよく用いられます。

PC上にプロジェクト用のフォルダ (例: my_project) を作り、以下のようなファイルを配置するのが一般的です。

my_project/
├── .dockerignore         # Dockerにコピーしないファイルを指定
├── .env                  # 環境変数 (APIキーなど)
├── Dockerfile            # コンテナの設計図
├── docker-compose.yml    # 複数のコンテナを管理する設定
├── requirements.txt      # Pythonライブラリ一覧
└── src/                  # Pythonコード置き場
    └── main.py

Dockerfileを使ったPython環境の作り方

Dockerfileは、コンテナの中身を上から順に定義する設計図であり、この章で完成させる。

いよいよコンテナの設計図である Dockerfile を書いていきます。

Dockerfileからコンテナが動き出すまでの流れを図にすると、次のようになります。

Dockerfileからコンテナが動き出すまで
1
DOCKER HUB公式イメージ python:3.13-slim
2
FILE / 設計図Dockerfile + requirements.txt
3
IMAGEイメージPython+ライブラリ入り
4
CONTAINERコンテナアプリが動く
HOST / 自分のPCホストのソースコード

最小構成のDockerfileを書く

Dockerfile は、コンテナをどう作るかを上から順に記述するテキストファイルです。

先ほどの my_project フォルダ直下に、Dockerfile という名前で以下のファイルを作成します。

# 1. ベースにするイメージを指定
FROM python:3.13-slim

# 2. 環境変数を設定 (バッファリング無効化など)
ENV PYTHONUNBUFFERED=1

# 3. コンテナ内の作業ディレクトリを指定
WORKDIR /app

# 4. 必要なファイルをコンテナにコピー
COPY ./requirements.txt /app/requirements.txt

# 5. ライブラリをインストール
RUN pip install -r requirements.txt

# 6. アプリケーションのコードをコピー
COPY ./src /app/src

# 7. コンテナ起動時に実行するコマンド
CMD ["python", "src/main.py"]

このDockerfileは、以下の処理を行います。

  1. python:3.13-slim イメージを土台にします。
  2. Pythonのログがすぐに見られるように設定します。
  3. コンテナ内の /app というフォルダを基準に作業します。
  4. まず requirements.txt だけをコピーします。
  5. ライブラリをインストールします。
  6. src フォルダ以下のPythonコードをコンテナにコピーします。
  7. コンテナが起動したら python src/main.py を実行します。

requirements.txtで依存パッケージを管理

requirements.txt は、プロジェクトで使うPythonライブラリとそのバージョンを記載するファイルです。

my_project フォルダ直下に、requirements.txt を作成します。

例えばFlaskを使う場合は、以下のように記述します。

Flask==3.1.3

ローカル環境ですでに開発を進めている場合は、ターミナルで pip freeze > requirements.txt を実行しよう。

現在インストールされているライブラリ一覧を生成できる。

Dockerfileでは、このファイルを RUN pip install -r requirements.txt コマンドで読み込み、ライブラリをまとめてインストールします。

仮想環境(venv)が不要になる理由

「Dockerを使うとき、コンテナの中で venv を作る必要はありますか?」

これはよくある質問です。

結論から言うと、venv は不要です。

venv の目的は、「プロジェクトごとにPythonライブラリの環境を分離すること」でした。

しかし、Dockerコンテナ自体が、OSレベルで隔離された「独立した環境」です。

コンテナAとコンテナBは互いに干渉しません。コンテナAでインストールしたライブラリが、コンテナBに影響することはありません。

Dockerコンテナそのものが、venv よりも強力な仮想環境の役割を果たしているため、コンテナ内でさらに venv を使うのは二重の手間であり、不要なのです。

普段Anacondaを使っている方は「Anacondaも環境を分離できるのでは」と思うかもしれません。

ただしAnacondaが分離するのはPythonのパッケージ環境までで、OSやシステムライブラリのレベルでは分離されません。

コンテナ単位でOSごと隔離するDockerとは、役割そのものが異なります。

docker-composeで開発環境を自動化する

docker-composeを使えば、長いdocker runコマンドを打たずに、設定ファイル1つでコンテナを起動できる。

Dockerfileはコンテナの「設計図」ですが、実際にビルドして起動するにはターミナルで docker build や docker run といった長いコマンドを打つ必要があります。

docker-compose は、この作業を自動化し、複数のコンテナ (例: Pythonアプリとデータベース) をまとめて管理するためのツールです。

なお、現在のDocker Desktopに同梱されているのはCompose V2で、コマンドはハイフンなしの docker compose です。旧来の docker-compose(V1)はサポートが終了しているため、この記事のコマンドもV2の書き方にそろえています。設定ファイル名は docker-compose.yml のままでも問題なく読み込まれます。

あわせて読む

docker-compose.yml の基本構造

docker-compose.yml という設定ファイルに、コンテナの起動設定を記述します。

my_project フォルダ直下に、docker-compose.yml を作成します。

services:
  app:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - ./src:/app/src
    env_file:
      - .env

この設定の意味は以下の通りです。

  • services:: 起動するコンテナ群を定義します。
  • app:: app という名前のサービス (コンテナ) を定義します。
  • build: .: カレントディレクトリにある Dockerfile を使ってビルドします。
  • ports:: PCの8000番ポートと、コンテナの8000番ポートをつなぎます。
  • volumes:: PCの src フォルダと、コンテナの /app/src フォルダを同期します。
  • env_file:: .env ファイルを読み込んで環境変数として使います。

ボリュームでコードをホットリロードする

docker-compose.yml に記述した volumes が、開発効率を劇的に上げる鍵となります。

volumes: ['./src:/app/src']

この設定により、PC (ホスト) の src フォルダと、コンテナ内の /app/src フォルダが「同期」されます。

PC側で src/main.py を編集して保存すると、コンテナを再ビルドしなくても、その変更が即座にコンテナ内のファイルに反映されます。

FlaskやFastAPIの「リロードモード」と組み合わせれば、コードを保存するたびにWebサーバーが自動で再起動し、変更内容をすぐにブラウザで確認できます。

ボリュームでコードを共有するしくみ
1
HOST / 自分のPCホストのソース(./src)エディタで編集して保存
2
VOLUMEボリューム共有同じフォルダをコンテナに見せる
3
CONTAINERコンテナ内 /app/src変更を検知して再読み込み
NOTEコードを直すたびにイメージを作り直さなくても、すぐ動作確認できる。

環境変数を.envで管理する方法

データベースのパスワードやAPIキーといった機密情報を、Dockerfile や docker-compose.yml に直接書き込むのは危険です。

これらの情報は .env ファイルに分離して管理するのが定石です。

my_project フォルダ直下に .env ファイルを作成します。

# .env ファイル
API_KEY=abcdefg123456
DATABASE_URL=postgres://user:pass@db:5432/mydb

そして、.gitignore ファイルに .env を追加し、Gitリポジトリに含まれないように設定します。

docker-compose.yml の env_file: .env 設定により、.env の内容がコンテナ内の環境変数として読み込まれます。

Pythonコードからは os.environ.get('API_KEY') のようにして値を取得できます。

PythonアプリをDocker上で実行する方法

docker-compose.yml ができたら、ターミナルで以下のコマンドを実行するだけです。

docker compose up --build

これで Dockerfile がビルドされ、コンテナが起動します。

Flask/Djangoの開発環境を立ち上げる

FlaskやDjangoのようなWebフレームワークを動かす際は、コンテナ外部からアクセスできるように設定する必要があります。

DockerfileのCMD命令:

CMD で指定する開発サーバーのホストを 0.0.0.0 に設定します。

# Flaskの場合
CMD ["flask", "run", "--host=0.0.0.0", "--port=8000"]

# Djangoの場合
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

127.0.0.1 (localhost) ではなく 0.0.0.0 を指定するのには理由がある。

127.0.0.1 はコンテナ内部からのアクセスしか許可しない。

一方 0.0.0.0 は、コンテナ外部(つまりあなたのPCのブラウザ)からのアクセスも許可する。

FastAPIをuvicornで動かす構成例

FastAPIを uvicorn サーバーで動かす場合も同様です。

開発中は --reload オプションを付けると、前述のボリュームマウントと合わせて最強のホットリロード環境が完成します。

DockerfileのCMD命令:
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

src.main:app の部分は、FastAPIのインスタンス ( app ) が src/main.py 内で定義されていることを示します。

なお、Docker Desktopのデフォルトのメモリ割り当て(ホストメモリの50%が既定値)のままだと、pandas や numpy のビルドが理由の分からないまま途中で無言落ちすることがある。

ビルドがエラーメッセージも出さずに止まる場合は、Docker Desktopの設定(Resources)でメモリを4GB以上に増やすと解決するケースが多い。

Jupyter Notebookをコンテナで動かす場合

ここまではFlaskやFastAPIといったWebアプリを想定してきましたが、データ分析用途で Jupyter Notebook をコンテナ内で使いたいケースもあるでしょう。

requirements.txt に jupyter を追加し、CMD命令を以下のように変更するだけで最小構成が完成します。

CMD ["jupyter", "notebook", "--ip=0.0.0.0", "--allow-root", "--no-browser"]

あわせて docker-compose.yml の ports に "8888:8888" を追加してブラウザからアクセスできるようにします。

Webアプリと同様に volumes でソースフォルダを同期しておけば、ノートブックの編集内容もホスト側にそのまま残ります。

ログ出力とエラーハンドリングのポイント

Dockerで動かすアプリケーションのログは、ファイルに書き出すのではなく、標準出力 (STDOUT) または 標準エラー出力 (STDERR) に出すのが原則です。

Pythonの print() 関数や logging モジュール (標準設定) は、標準出力にログを出します。

Dockerはこれらの出力を自動的に収集する。

何か問題が起きたときは docker logs コマンド(または docker compose logs)で、コンテナが出力したログをすぐに確認できる。

# appサービス (コンテナ) のログを表示する
docker compose logs app

# ログを監視し続ける (tail -f と同じ)
docker compose logs -f app

よくあるエラーと対処法

Docker環境構築は、特有の「ハマりどころ」があります。よくあるエラーと対処法を知っておけば、時間を無駄にせずに済みます。

Permission denied が出るとき

コンテナとホストでマウントしたフォルダ(volumes で共有した src など)を操作すると、Permission denied (権限がありません) というエラーが出ることがある。

これは、コンテナ内ではデフォルトで root(管理者)ユーザーでプロセスが動くため、コンテナが作ったファイルがホスト側で root 所有になることが主な原因だ。

ホストPCのファイルは一般ユーザーの所有物であるため、両者の間で権限のズレが生じる。特にLinuxホストで起きやすく、Docker DesktopのMac・Windowsでは共有フォルダの所有者がホストのユーザーとして扱われるため、この症状は出にくい。

対処法:

Dockerfile 内で root ではない一般ユーザーを作成し、そのユーザーでプロセスを実行するように USER 命令を追加します。

FROM python:3.13-slim
# ... (中略) ...

# 1. 権限問題を避けるため、一般ユーザー (appuser) を作成
RUN useradd -m -u 1000 appuser

# 2. 作業ディレクトリの所有者を変更
RUN chown -R appuser:appuser /app

# 3. 以降の命令を実行するユーザーを指定
USER appuser

# ... (COPY や CMD) ...

pip install が遅すぎるときの改善

docker build を実行するたびに pip install が走り、ライブラリのダウンロードに時間がかかる。

対処法1: Dockerfileの命令順を工夫する (キャッシュの活用)

(詳細は次のセクションで説明します)

対処法2: pipのキャッシュをマウントする (BuildKit)

Dockerの新しいビルド機能 (BuildKit) を使うと、pip のキャッシュをビルド間で共有できます。

RUN 命令を以下のように書き換えます。

# Dockerfile
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -r requirements.txt

これにより、2回目以降のビルドではキャッシュが使われ、pip install が劇的に速くなります。

ただし、GitHub Actions等のCI環境ではローカルのDockerキャッシュがそのまま引き継がれないため、BuildKitのキャッシュ指定だけでは高速化されない場合がある。

CI側でも --cache-from に加えて --cache-to でレジストリへのキャッシュ書き出し先を明示する必要がある点には注意したい。

コンテナがすぐ落ちるときのデバッグ方法

docker compose up を実行した直後、コンテナが起動したように見えてすぐに Exited with code 1 (エラーで終了) となり、落ちる場合があります。

これは、CMD で指定したPythonスクリプトが起動時にエラー (文法エラーやインポートエラーなど) を起こしている可能性が高いです。

対処法:

docker compose logs でエラー内容を確認するのが基本です。

それでも原因が分からない場合は、コンテナに入って中を調査します。

docker-compose.yml の CMD を一時的に「何もしないで待機する」コマンドに変更します。

services:
  app:
    build: .
    # ... (中略) ...
    # CMDを上書きして、コンテナを起動し続ける
    command: tail -f /dev/null

この状態で docker compose up -d を実行し、コンテナを起動させたままにします。

次に、docker compose exec コマンドで、起動中のコンテナの内部 (シェル) に入ります。

Bash

# appコンテナに入り、bashを起動する
docker compose exec app bash

コンテナ内部に入れたら、そこで初めて python src/main.py を手動で実行してみます。

すると、画面に直接エラーメッセージが表示されるため、デバッグが容易になります。

あわせて読む

Docker × Python 開発を効率化するTips

基本をマスターしたら、さらに開発を快適にするテクニックも見てみましょう。

キャッシュを活用してビルド時間を短縮する

Dockerは、Dockerfile の各命令 ( FROM, RUN, COPY ) をレイヤーとしてキャッシュします。

ファイルに変更がなければ、前回のキャッシュを使ってビルド時間を短縮します。

この仕組みを最大限に活かすには、変更頻度の低いものを先に実行するのが鉄則です。

悪い例:
# コードもライブラリ一覧も全部コピー
COPY . .
RUN pip install -r requirements.txt

これでは、src/main.py を1行修正しただけでも、COPY が実行され、キャッシュが破棄されます。

その結果、変更がない requirements.txt の pip install も毎回実行されてしまいます。

良い例 (最小構成で示した例):
# 1. 変更頻度の低いライブラリ一覧だけ先にコピー
COPY ./requirements.txt /app/requirements.txt

# 2. ライブラリをインストール (ここがキャッシュされる)
RUN pip install -r requirements.txt

# 3. 変更頻度の高いコードをコピー
COPY ./src /app/src

この順番なら、Pythonコード (src) を変更しても、requirements.txt に変更がない限り pip install はキャッシュが使われる。ビルドは一瞬で終わる。

src/main.py を1行直して再ビルドしたとき(レイヤーキャッシュ)
BAD / 悪い例pip install まで毎回やり直しCOPY . . ✕ 再実行
RUN pip install -r requirements.txt ✕ 再実行
GOOD / 良い例やり直すのは COPY ./src だけCOPY ./requirements.txt ✓ キャッシュ
RUN pip install -r requirements.txt ✓ キャッシュ
COPY ./src /app/src 再実行
NOTE悪い例は COPY . . でキャッシュが破棄され、変更のない requirements.txt の pip install まで再実行される。良い例は変更のない行でキャッシュを使う。

マルチステージビルドで本番用イメージを軽量化する

ここまでのDockerfileは、開発時にそのまま使う分には問題ありません。しかし本番環境にデプロイするイメージとしては、少し「重い」ままです。

ライブラリのビルドに必要なツール(コンパイラ等)や、開発用の中間ファイルまで最終イメージに含まれてしまうためです。

これを解決するのがマルチステージビルドという手法です。

1つのDockerfile内に「ビルド用ステージ」と「実行用ステージ」を分けて記述し、実行用イメージにはビルド成果物だけをコピーします。

# --- ビルド用ステージ ---
FROM python:3.13-slim AS builder
WORKDIR /app
COPY ./requirements.txt /app/requirements.txt
RUN pip install --user -r requirements.txt

# --- 実行用ステージ ---
FROM python:3.13-slim
WORKDIR /app
# ビルドステージからライブラリだけをコピー
COPY --from=builder /root/.local /root/.local
COPY ./src /app/src
ENV PATH=/root/.local/bin:$PATH

CMD ["python", "src/main.py"]

この方法により、最終的なイメージサイズを削減でき、不要なツールが含まれない分、攻撃対象領域(アタックサーフェス)も小さくできます。

開発中は前述のシンプルなDockerfileで十分ですが、本番デプロイ前の最適化として覚えておく価値があります。

あわせて読む

Poetry・pipenv・uvをコンテナで使う方法

requirements.txt の代わりに、Poetry や pipenv といったモダンなパッケージ管理ツールを使いたい場合もあるでしょう。

基本的な考え方は同じです。

Dockerfile 内で poetry (または pipenv) をインストールし、ライブラリをインストールします。

FROM python:3.13-slim

# Poetryをインストール
RUN pip install poetry

WORKDIR /app

# 依存ファイルだけ先にコピー
COPY poetry.lock pyproject.toml /app/

# 仮想環境を作らず、システムにインストールする設定
# (この時点ではコード本体が無いので --no-root で依存だけ入れる)
RUN poetry config virtualenvs.create false \
    && poetry install --only main --no-root --no-interaction --no-ansi

# コードをコピー
COPY . .

CMD ["poetry", "run", "python", "src/main.py"]

Poetry 2.0以降では --no-dev オプションが廃止されたため、本番用の依存だけを入れる場合は上記のように --only main を指定します。

最近はRust製の高速なパッケージマネージャー uv を使う構成も増えています。uvの公式ドキュメントには、公式イメージから uv のバイナリをコピーして uv sync で依存を入れるDockerfileの書き方が載っており、pipやPoetryよりインストールが速いのが特長です。pyproject.toml と uv.lock で管理しているプロジェクトなら、次のように書けます。

FROM python:3.14-slim

# uv本体を公式イメージからコピー(本番ではバージョンを固定する)
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

ENV UV_COMPILE_BYTECODE=1 \
    UV_LINK_MODE=copy

WORKDIR /app

# 依存ファイルだけ先にコピーしてキャッシュを効かせる
COPY pyproject.toml uv.lock ./
RUN uv sync --locked --no-install-project

# コードをコピーしてプロジェクト本体をインストール
COPY . .
RUN uv sync --locked

CMD ["uv", "run", "python", "src/main.py"]

UV_COMPILE_BYTECODE=1 は起動を速くするためのバイトコード事前コンパイル、UV_LINK_MODE=copy はビルドキャッシュを使うときの警告を避ける設定です。uv:latest の部分は、チーム開発では uv:0.x.y のようにバージョンを固定しておくと再現性が保てます。

VSCode Dev Containersとの連携

Visual Studio Code (VSCode) をお使いの場合、Dev Containers (Remote - Containers) 拡張機能は必須です。

これは、VSCodeの編集画面ごとDockerコンテナの中に入り込んでしまうような機能です。

.devcontainer という設定フォルダを用意するだけで、以下のことができます。

  • PC本体にPythonやVSCode拡張機能を一切インストールする必要がなくなる。
  • Gitリポジトリをクローンして「コンテナで開く」を押すだけで、開発環境が自動構築される。
  • ターミナルもデバッガーも、すべてコンテナ内で完結する。

チーム開発において、全員のVSCode設定まで含めて環境を統一できる強力な手法です。

DockerでPython環境を構築する際の注意点

最後に、Dockerを使う上で知っておきたい注意点 (罠) を共有します。

Alpineベースの罠(ビルドエラー・musl問題)

イメージサイズが最小の python:3.13-alpine は魅力的だが、安易に手を出すと痛い目を見る。

Alpine Linuxは、多くのLinux (Debian, Ubuntu) が使う標準ライブラリ glibc ではなく、musl libc という軽量なライブラリを採用しています。

多くのPythonパッケージ (特に pandas, numpy, scipy など) は、glibc がある前提で高速化されたバイナリ (wheel) が提供されています。

musl 環境ではこのバイナリが使えないため、pip install 時にC言語のソースコードからコンパイル (ビルド) が始まってしまいます。

結果、ビルドに必要なツール (gcc, build-base など) がコンテナにないため、インストールが失敗します。

対処法:

初心者は alpine を避け、slim 版 (Debianベース) を使いましょう。

どうしても alpine を使う必要がある場合は、必要なビルドツールを追加でインストールする必要がありますが、手間がかかります。

コンテナとホストでファイル権限がズレるとき

「よくあるエラー」でも触れましたが、権限問題はDockerでよく遭遇する問題です。

特にLinuxホストでDockerを動かしている場合、コンテナが root 権限で作成したファイル (ログファイルなど) は、ホスト側で編集・削除できなくなる。

Dockerfile で USER 命令を使い、一般ユーザーでプロセスを実行する習慣をつけるのが、最も堅実な対策です。

不要なイメージ・ボリュームの掃除方法

Dockerを使っていると、ビルドに失敗した中間イメージや、使わなくなったコンテナ、ボリュームがPCのディスク容量を圧迫していきます。

「DockerのせいでPCの空き容量がなくなった」とならないよう、定期的な掃除が必要です。

  • 停止中のコンテナをすべて削除:docker container prune
  • 使われていない (ぶら下がり) イメージをすべて削除:docker image prune
  • 使われていないボリュームをすべて削除:docker volume prune
  • 上記すべて+ビルドキャッシュも削除 (強力):docker system prune

docker system prune は強力ですが、必要なキャッシュまで消してしまうこともあるため、実行タイミングには注意してください。

あわせて読む

よくある質問

Q1. DockerでPython環境を構築するには何が必要ですか?

A1. Docker Desktopと、Dockerfile・requirements.txt・docker-compose.ymlの3つの設定ファイルがあれば十分です。特別なライブラリのインストールは不要です。

Q2. DockerでPython環境を作るときvenvは必要ですか?

A2. 不要です。Dockerコンテナ自体がOSレベルで隔離された環境のため、コンテナ内でさらにvenvを使うのは二重の手間になります。

Q3. python:3.13-slimとpython:3.13-alpineはどちらを選ぶべきですか?

A3. 特別な理由がなければslim版がおすすめです。alpine版は軽量ですが、pandasなどのビルドでエラーが起きやすい「罠」があります。

Q4. Dockerfile内でPermission deniedエラーが出たときの対処法は?

A4. Dockerfile内でUSER命令を使い、root以外の一般ユーザーでプロセスを実行するように設定すると、多くの場合解消します。

Q5. pip installが遅いときはどう改善すればいいですか?

A5. Dockerfileの命令順を工夫してキャッシュを活用するか、BuildKitのキャッシュマウント機能を使うと高速化できます。

Q6. docker compose upしてもコンテナがすぐ落ちる場合はどうすればいいですか?

A6. CMDを一時的に待機コマンドに変更してコンテナに入り、python src/main.pyを手動実行するとエラー内容を直接確認できます。

Q7. Docker Desktopで作ったPython環境はMacとWindowsで違いがありますか?

A7. Dockerfileがある限り基本的に同じ環境が再現されます。OSの差異はDocker Desktopのインストーラーを選ぶ段階が中心ですが、Apple Silicon搭載Macはarm64、多くのWindows PCはamd64とCPUアーキテクチャが異なるため、一部のライブラリでは追加のビルドが必要になる場合があります。

Q8. 本番環境向けにDockerイメージを軽量化する方法はありますか?

A8. マルチステージビルドを使い、ビルド用ステージと実行用ステージを分けることで、最終イメージから不要なビルドツールを除外できます。

まとめ:DockerでPython環境構築は劇的に楽になる

Dockerは、現代のPython開発において欠かせないツールです。

最初は Dockerfile や docker-compose.yml の書き方に戸惑うだろう。

しかし一度その恩恵を知れば、もうDockerなしの開発には戻れなくなる。

再現性の高い開発環境を作れる

Dockerfileという「環境の設計図」があるおかげで、「誰がやっても」「いつやっても」同じ環境が手に入ります。

これは、バグの特定や安定した運用に絶大な効果を発揮します。

チーム開発・学習用でも扱いやすい

新しいメンバーがプロジェクトに参加したとき、以前は環境構築マニュアルを渡して半日かかることもありました。

Dockerなら、Gitリポジトリをクローンして docker compose up を実行するだけ。わずか数分で開発を開始できます。

これはPythonを学習する初学者が、環境構築で挫折するのを防ぐためにも役立ちます。

REVISIONS / 改訂履歴
REV.DATE内容
52026-10-15図解を描き直し(図面のデザインにそろえた)
42026-10-14雰囲気だけの挿絵を外した
32026-10-06記載内容の事実確認と修正
22026-08-242026年8月時点の情報で全体を見直し(古い記述を7件更新)
12025-11-15初版
NEXT READ本棚から1本

AIで開発を組み直すなら、まずこの5冊から

入門・実践・設計まで、Claude Codeの本をレベル別に5冊選んで比べました。

→ おすすめ5冊を見る

  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

Docker