はじめに
前回はC言語のソースビルドについてdocker image の size を小さくする方法をメモリました。
今回は python についてです。忘れないうちにメモメモします。
内容
削減方法
docker image を build と実行用に分けるのは同じ考え方です。こちらのサイトで学ばせていただきました。
ここで紹介されているのは、
-
pip install --user を使う
--user オプションをつけると、ホームディレクトリの.local に全ての必要なファイルがインストールされる。ので、これをコピーすればよい。 -
virtualenv を使う
virtualenv で使用したディレクトリをコピーし、PATHを通す。
というものです。いずれもビルド用イメージでpip や virtualenv を実行し、実行用イメージに必要なものだけ持ってくるという作戦です。
実行例
おじさんは頑張って動かしたので、こちらにメモします。Flask を使いました。以下のファイルが全て同じフォルダにあれば、再現できるかと思います。
.
├── main.py
├── multi-stage.Dockerfile
├── requirements.txt
└── single-stage.Dockerfile
通常のコンテナを作成
まず、実行するpython スクリプト。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
pip でインストールするためのあれ。
Flask==2.0.1
そして、普通の?Dockerfile
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y python3 python3-pip
COPY requirements.txt .
RUN python3 -m pip install --user -r requirements.txt
RUN ls /root/.local/
COPY main.py /root/app/main.py
EXPOSE 8080
CMD ["python3", "/root/app/main.py"]
もちろん動きます。
$ docker build -f single-stage.Dockerfile -t py-single .
$ docker run -p 5000:8080 --rm py-single
ブラウザを立ち上げても良いですが、別のterminal で
$ curl localhost:5000
Hello World!
となります。
マルチステージ
ここで、Dockerfile を変更します。pip install するとき、--user オプションをつけると、user の ~/.local/ というディレクトリにpython module が保存されます。なので、それをコピーする作戦です。
FROM ubuntu:18.04 AS compile-image
RUN apt-get update && apt-get install -y python3 python3-pip
COPY requirements.txt .
RUN python3 -m pip install --user -r requirements.txt
RUN ls /root/.local/
FROM ubuntu:18.04 AS build-image
COPY --from=compile-image /root/.local /root/.local
RUN apt-get update && apt-get install -y python3
COPY main.py /root/app/main.py
EXPOSE 8080
CMD ["python3", "/root/app/main.py"]
同様に実行できます。
イメージサーズの比較
私の所では、こんな感じでした。
REPOSITORY TAG IMAGE ID CREATED SIZE
py-multi latest bbdb7bfc547b 2 days ago 140MB
py-single latest a16f61635f65 2 days ago 487MB
小さくなりました。良かった良かった。
まとめ
python でも docker image の size を小さくする方法を調査し、動作確認した。pip install するとき、--user オプションをつけて、~/.local をコピーすればよい。
更に考えられるこの先の調査は
- pip でそもそも何がインストールされるのか、を理解できれば、必要なファイルを細かく選別できて、もっと小さくできるかもしれない
- virtualenv も試す
ですが、とりあえず目的が達せられそうなので、これで良しとしました。
(2021/08/26 翌日の深夜1:22)