2020年7月25日土曜日

dockerのpythonコンテナをビルドしなおさずpip installでライブラリを更新可能にする方法


背景

dockerでpythonのコンテナを利用する際に、関連するライブラリが増える度にpip install実行のためにコンテナをビルドし直さなくても良い方法を探していました。
ビルドせずともpip installの実行でライブラリを更新する仕組みを作れたので、備忘録を兼ねて設定方法を共有します。

使ったもの

docker
docker-compose

docker-compose.ymlの設定

ファイル全体を共有してから要所を説明します。
実際に動くdocker-compose.ymlはリポジトリに上げています。
version: '3.8'

services:
app:
image: python:3.8-alpine
working_dir: /app
volumes:
- [ソースコードを管理するフォルダ]:/app
- [ライブラリを管理するフォルダ]:/pip-lib
environment:
PYTHONUSERBASE: /pip-lib

imageとworking_dirを指定

    image: python:3.8-alpine
working_dir: /app
pythonのコンテナで/appをworking_dirとして動かすことにします。

ソースコード、ライブラリのvolumesを指定

    volumes:
- [ソースコードを管理するフォルダ]:/app
- [ライブラリを管理するフォルダ]:/pip-lib

/appにソースコードを、/app/libにライブラリを管理するフォルダを、/root/.cache/pipにキャッシュのフォルダを、コンテナの外のフォルダとリンクさせます。

/pip-libフォルダにインストールしたライブラリをコンテナの外で管理することで、コンテナを起動し直してもそのフォルダへの変更を維持できるようにします。

ライブラリの読み込み先を指定

    environment:
PYTHONUSERBASE: /pip-lib
PYTHONUSERBASEという環境変数でフォルダを指定しておくことにより、--userオプションを付けてpip installを実行することでそのフォルダにライブラリをインストールしてくれます。

ライブラリのインストール方法

ソースコードを管理するフォルダに、利用するライブラリを記述したrequirements.txtを置きます。

例:
requirements.txt
fire

requirements.txtに記述したライブラリを--userオプションを付けてPYTHONUSERBASEで指定したフォルダ(/pip-lib)にインストールします。
docker-compose run app pip install -r requirements.txt --user

上記のコマンドの実行によりpip-libにライブラリがインストールされ、コンテナでライブラリを実行できるようになります。

コンテナのpythonプログラムを実行

仕組みが出来たので関連ライブラリをインストールしてコンテナのpythonプログラムを実行します。
今回の試行錯誤に利用したプログラムをgithubのリポジトリとして公開しているので、それを実行します。

リポジトリをダウンロードしてフォルダの中に入ります。
git clone https://github.com/asukiaaa/docker-python-pip-practice.git
cd docker-python-pip-practice

pipを実行せずにプログラムを実行すると依存が満たせずエラーが発生します。
docker-compose run app python main.py hello
Traceback (most recent call last):
File "main.py", line 1, in <module>
import fire
ModuleNotFoundError: No module named 'fire'

コンテナ内でpip installを--userオプション付きで実行してライブラリをインストールします。
docker-compose run app pip install -r requirements.txt --user

pip実行後にプログラムを実行すると、エラー無く動きました。
docker-compose run app python main.py hello
Hello!

まとめ

pythonのpipで扱うライブラリの保存先をPYTHONUSERBASEで指定し、そのフォルダに対する変更をコンテナの外部で維持し、pip install時に--userオプションを付けてそのフォルダにライブラリをインストールすることで、コンテナをビルドし直さずともライブラリを更新できる環境が作れました。

通信速度が遅い場所で開発する時に便利だと思います。

参考

pip cache
PYTHONUSERBASE
asukiaaa / docker-python-pip-practice

0 件のコメント :