nikkie-ftnextの日記

イベントレポートや読書メモを発信

PythonプロジェクトをDockerイメージにビルドする(マルチステージビルドでsite-packagesをCOPY!)

はじめに

もう6月も終わり!?光陰矢の如しすぎない!? nikkieです。

PythonプロジェクトのDockerイメージのマルチステージビルドについて、現時点の理解をまとめます。

目次

マルチステージビルド

Dockerのドキュメントを参照します1

1つのDockerfileの中に複数のFROMを書きます!

各FROM命令のベースイメージは、それぞれに異なるものとなり、各命令から新しいビルドステージが開始されます。

イメージ内に生成された内容を選び出して、一方から他方にコピーすることができます。
そして最終イメージに含めたくない内容は、放っておくことができます。

ドキュメントの例では

  • 1つ目のFROMソースコードをビルドするステージ
  • 2つ目のFROM:ビルドしたソースコードを動かすイメージ(=docker buildで最終的にできあがるイメージ)

となっています。
ビルドツールは最終的にできあがるイメージには不要であり、ビルドツールによる成果物だけを1つ目のステージから2つ目のステージにCOPYすることで、最終的にできあがるイメージを最小限の要素で作れています。

この書き方は、Docker Engine 17.05からサポートされました。

私がマルチステージビルドに関心を持っている理由は、サイズが小さいイメージは取り回ししやすいからです。

Pythonでマルチステージビルドの例

エキスパートPythonプログラミング 改訂3版』の2章(2.5.2内の「訳者より」)に例があります。

PythonにおけるDockerベストプラクティス

翻訳者の1人の澁川さんの執筆記事も紹介されています。

  • ビルド用のコンテナで依存関係をすべてインストール(pip install -r requirements.lock
  • 実行用のコンテナにsite-packages以下をコピー
    • COPY --from=builder /usr/local/lib/python3.8/site-packages /usr/local/lib/python3.8/site-packages
    • コマンドとしても使えるパッケージが含まれる場合は、/usr/local/bin/以下のコマンドもコピーする
  • 実行用のコンテナにソースコードもコピー

上記の方法(site-packages以下をCOPY)を試し始めたところ、なかなかいい感じです。

nikkieのプロジェクトでの例

直近でマルチステージビルドした例(この記事のきっかけ)はこちらです。

関連情報

Poetryでの例

Poetryを使った場合もsite-packages以下をCOPYするマルチステージビルドができそうに思います。

見つけた例はこちら:

  • site-packages以下をCOPYするためにPoetryで仮想環境は作らない(POETRY_VIRTUALENVS_CREATE=false
  • この記事では既存の記事では解決できない問題3つにアプローチするために工夫しています
    • 今の私にはsite-packages以下をCOPYするための工夫が知れただけで十分でした

pip install --no-cache-dir

サイズの小さなDockerイメージをbuildする方法として、キャッシュを削除する目的でpip install --no-cache-dirが紹介されることがあります。

私は--no-cache-dirというオプションが何を指定しているのかすごく分かりづらいな〜と思います2

# pip 23.1.2 で pip install --help
  --no-cache-dir              Disable the cache.
  • ローカルのキャッシュを無視してPyPIからインストールするってこと?
  • PyPIからインストールするときにキャッシュしないってこと?

(実験したところ両方ともやってそうな感じでしたが(※勘違いしてるかも)、時間を作ってソースコードを読むしかないかな〜と思っています)

マルチステージビルドを使うことで、--no-cache-dirに認識していた煩雑さからは解放されました。

終わりに

PythonプロジェクトのDockerイメージビルドについて、マルチステージビルドでsite-packagesをCOPYする方法をアウトプットしました。
この結論はあくまで現時点のもので、今後経験を重ねる中で別の方法にシフトする可能性もあります。

この記事を書く中で思い出したのですが、初めてみんなのPython勉強会本編で話したときもDockerでしたね。

Entrance of Docker for Pythonista 〜Dockerではじめる機械学習モデルのデプロイ〜

長い付き合いになったものだ〜


  1. 英語
  2. ドキュメント https://pip.pypa.io/en/stable/cli/pip_install/--no-cache-dirの説明は見つかりませんでした