docker+poetryでpythonを使う
はじめに
今までpythonを使う時はdocker+pipを使ってきた。
pythonのパッケージマネージャーとして、poetryの存在を知り、興味があったので使ってみた。
この記事ではpoetryで使用するpyproject.tomlファイルを作成するために、docker-compose.yamlやpoetry new
コマンドを使用してますが、正直効率が悪いと思います。
poetry new
コマンドで作成されるディレクトリを再利用しようと思い、このような流れになっていますが、適宜やりやすい方法でやった方が早く作業ができると思います。
前提環境
pc: MacBookPro(2017)
os: Big Sur
Homebrew 3.4.10
Docker version 20.10.13
docker-compose version 1.29.2
Dockerで作成したコンテナ上でpoetryでPython環境を構築します。
poetryは仮想環境を構築できるメリットがありますが、dockerコンテナ上では特に意味がないと思ったので、今回は仮想環境を作らないように設定します。
インストール関連(事前準備)
Homebrewのインストール
Homebrewのページからインストール用のコマンドをコピペして、ターミナルなどで実行します。
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
$ brew -v
Homebrew 3.4.10
Docker, docker-composeのインストール
下記のコマンドにより、homebrewでDocker, docker-composeをインストールしていきます。
$ brew search docker
==> Formulae
docker ✔ docker-machine docker-squash
docker-clean docker-machine-completion docker-swarm
docker-completion docker-machine-driver-hyperkit docker2aci
docker-compose ✔ docker-machine-driver-vmware dockerize
docker-compose-completion docker-machine-driver-vultr lazydocker
docker-credential-helper docker-machine-driver-xhyve powerman-dockerize
docker-credential-helper-ecr docker-machine-nfs mockery
docker-gen docker-machine-parallels
docker-ls docker-slim
==> Casks
docker ✔ docker-edge docker-toolbox dockey dozer
$ brew install docker
$ brew install docker-compose
手順やコード
手順としては下記のような流れとなります。
事前準備(poetryプロジェクト初期化) -> Dockerfile作成 -> docker-compose.yaml作成 -> build
事前準備(poetryプロジェクト初期化)
事前準備用のDockerfileとdocker-compose.yaml
ARG python_image_v="python:3.10-buster"
# python3.10のイメージをダウンロード
FROM ${python_image_v}
ARG work_dir="/src/"
# コンテナにアクセスした際のデフォルトディレクトリ
WORKDIR ${work_dir}
# poetryのインストール先の指定
ENV POETRY_HOME=/opt/poetry
# poetryインストール
RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python && \
# シンボリックによるpathへのpoetryコマンドの追加
cd /usr/local/bin && \
ln -s /opt/poetry/bin/poetry && \
# 仮想環境を作成しない設定(コンテナ前提のため,仮想環境を作らない)
poetry config virtualenvs.create false
version: '3'
services:
test-app:
build: .
volumes:
- ./src:/src
# ports:
# - 8000:8000
tty: true # retain container up
コンテナ上でのpoetryプロジェクト初期化
下記のdocker-composeコマンドでコンテナを作成し、コンテナにアクセスします。
$ docker-compose up -d
$ docker-compose exec test-app bash
root@a6c27148c534:/src#
poetry version
でpoetryがインストールされていることを確認したら、プロジェクトを作成します。
poetry new <project-name>
でプロジェクトのディレクトリを作成してくれます。
オプションで--name <dir-name>
を入れるとプロジェクトディレクトリ配下に作成されるソースコードを入れるディレクトリの名前を指定できます。
(poetry new --src <project-name>
オプションでsrcディレクトリを作成できますが、ディレクトリ構成がややこしくなるので今回はやめておきます。)
対話形式でやりたい場合は、poetry init
コマンドで行います。
(pyproject.tomlファイルのみ作成されます。)
root@a6c27148c534:/src# poetry new myProject --name myFlask
Created package myflask in myProject
$ tree
myProject
├── README.rst
├── myflask
│ └── __init__.py
├── pyproject.toml
└── tests
├── __init__.py
└── test_myflask.py
poetry add <package-name>
コマンドでパッケージの追加ができます。
今回は一例として、flaskを入れてみます。
root@a6c27148c534:/src/myProject# poetry add Flask
Skipping virtualenv creation, as specified in config file.
Using version ^2.1.2 for Flask
Updating dependencies
Resolving dependencies... (14.6s)
Writing lock file
Package operations: 14 installs, 0 updates, 0 removals
• Installing markupsafe (2.1.1)
• Installing pyparsing (3.0.8)
• Installing attrs (21.4.0)
• Installing click (8.1.3)
• Installing itsdangerous (2.1.2)
• Installing jinja2 (3.1.2)
• Installing more-itertools (8.13.0)
• Installing packaging (21.3)
• Installing pluggy (0.13.1)
• Installing py (1.11.0)
• Installing wcwidth (0.2.5)
• Installing werkzeug (2.1.2)
• Installing flask (2.1.2)
• Installing pytest (5.4.3)
pyproject.tomlファイル内にFlaskが追加されます。
root@a6c27148c534:/src/myProject# cat pyproject.toml
[tool.poetry]
name = "myFlask"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.10"
Flask = "^2.1.2"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Dockerfile, docker-compose.yamlの作成
ARG python_image_v="python:3.10-buster"
# python3.10のイメージをダウンロード
FROM ${python_image_v}
ARG work_dir="/work/"
#ARG project_name="myProject"
#ARG src_dir="myflask"
RUN mkdir /work && mkdir /work/src && mkdir /work/tests
# コンテナにアクセスした際のデフォルトディレクトリ
WORKDIR ${work_dir}
# poetryのインストール先の指定
ENV POETRY_HOME=/opt/poetry
# poetryインストール
RUN curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python && \
# シンボリックによるpathへのpoetryコマンドの追加
cd /usr/local/bin && \
ln -s /opt/poetry/bin/poetry && \
# 仮想環境を作成しない設定(コンテナ前提のため,仮想環境を作らない)
poetry config virtualenvs.create false
# 仮想環境をprojectディレクトリで作成する
#RUN poetry config virtualenvs.in-project true
# poetryの定義ファイルをコピー (./src/配下に存在すると想定)
COPY ./src/myProject/pyproject.toml* ./src/myProject/poetry.lock* ./
# poetryでライブラリをインストール (pyproject.tomlが既にある場合)
RUN if [ -f pyproject.toml ]; then poetry install; else poetry new ${project_name} --name ${src_dir}; fi
version: '3'
services:
test-app:
build: .
volumes:
- ./src/myProject/myflask:/work/src
- ./src/myProject/tests:/work/tests
# ports:
# - 8000:8000
tty: true # retain container up
buildとflaskの確認、パッケージの追加
下記のコマンドでコンテナを起動します。
$ docker-compose up -d
コンテナにアクセスし、対話形式でimport flask
を実施するとインポートできます。
$ docker-compose exec test-app bash
root@ab019553223e:/work# python
Python 3.10.4 (main, Apr 20 2022, 18:32:02) [GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import flask
>>>
パッケージを追加または削除する場合は下記のコマンドpoetry add(remove) <package-name>
で実施可能です。
(今回はpyproject.tomlファイルがあるディレクトリで行いましたが、違うディレクトリでも可能?仮想環境を作っていないため?仮想環境を作っている場合はそのディレクトリでないとダメ?試していないため未確認です。)
root@ab019553223e:/work# ls
poetry.lock pyproject.toml src tests
root@ab019553223e:/work# cat pyproject.toml
[tool.poetry]
name = "myFlask"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.10"
Flask = "^2.1.2"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
root@ab019553223e:/work# poetry add selenium
Skipping virtualenv creation, as specified in config file.
Using version ^4.1.5 for selenium
Updating dependencies
Resolving dependencies... (0.3s)
Writing lock file
Package operations: 17 installs, 0 updates, 0 removals
• Installing pycparser (2.21)
• Installing cffi (1.15.0)
• Installing async-generator (1.10)
• Installing cryptography (37.0.2)
• Installing h11 (0.13.0)
• Installing idna (3.3)
• Installing outcome (1.1.0)
• Installing sniffio (1.2.0)
• Installing sortedcontainers (2.4.0)
• Installing certifi (2021.10.8)
• Installing pyopenssl (22.0.0)
• Installing pysocks (1.7.1)
• Installing trio (0.20.0)
• Installing wsproto (1.1.0)
• Installing trio-websocket (0.9.2)
• Installing urllib3 (1.26.9)
• Installing selenium (4.1.5)
root@ab019553223e:/work# poetry remove selenium
Skipping virtualenv creation, as specified in config file.
Updating dependencies
Resolving dependencies... (0.1s)
Writing lock file
Package operations: 0 installs, 0 updates, 17 removals
• Removing async-generator (1.10)
• Removing certifi (2021.10.8)
• Removing cffi (1.15.0)
• Removing cryptography (37.0.2)
• Removing h11 (0.13.0)
• Removing idna (3.3)
• Removing outcome (1.1.0)
• Removing pycparser (2.21)
• Removing pyopenssl (22.0.0)
• Removing pysocks (1.7.1)
• Removing selenium (4.1.5)
• Removing sniffio (1.2.0)
• Removing sortedcontainers (2.4.0)
• Removing trio (0.20.0)
• Removing trio-websocket (0.9.2)
• Removing urllib3 (1.26.9)
• Removing wsproto (1.1.0)
コンテナを停止する場合は下記のコマンドでできます。オプションで--rmi all
を付けるとdocker-compose
コマンドで作成されたコンテナとイメージなどを削除してくれます。
$ docker-compose down (--rmi all)
その他
poetryでのversion指定
poetryでパッケージをインストールする際にバージョン指定が可能ですが、今回は指定していません。
詳しくはpoetryドキュメントを見てください。
docker内でのpoetry操作の自動化について
今回はpoetryによるpoetry install
コマンドをpyproject.tomlがある前提でDockerfileやdocker-compose.yamlなどを書いた。しかし、poetry new or init
などの操作も自動化したい。他の記事もpyproject.tomlを前提に書いているのが多いため、現在お勉強中です。
下記のサイトが参考になるかも。
Poetry と Docker を併用する試み
docker-composeでのvolumeのタイミング
RUN -> volume -> CMDらしい?
なので、マウントするvolume上で何かしらのコマンドを実行したい場合は、CMDの方が良い?
(# 最後に)
Discussion
get-poetry.py
使ったやり方は現在deprecated みたいです。
返信が遅くなり、すみません。
ご指摘ありがとうございます。
上記に加えてdocker-composeにも更新がありますね。
暫定のnote記載するようにします。