
はじめに
Docker上でPoetryの依存ファイルを使用した環境を構築したいと思い調査しました。
本記事はその手順の備忘録となります。
使用するプロジェクト
以下のプロジェクトを例に説明します。 詳細は割愛しますが、pythonでdashフレームワークを使用したwebアプリのプロジェクトになります。現状はpoetryコマンドで実行環境を構築できるようにしていますが、これをdocker環境でも構築できるようにします。
方針
作業ディレクトリにプロジェクトと同じフォルダ(dlSubscanStakingRewardsHistoryDash)を構築します。
そして、Docker環境ではアプリケーションの実行で必要となる後述するソースコード類(パッケージ管理ファイルも含む)が格納されたフォルダ、および、ファイルをコピーして同期することにします。
フォルダ構成
ソースコードはapp,ci,testフォルダに格納されています。
メインのプログラムはappフォルダ内のコードで、プロジェクト以下でpoetry run python appを実行することでDashフレームワークのWebアプリが起動します。
# 以下は一部記載を省略しています。
% tree -a -L 2
.
├── .DS_Store
├── .demofile
├── .git
├── .gitignore
├── .markdownlint.jsonc
├── .mypy_cache
├── .pre-commit-config.yaml
├── .ruff_cache
├── .venv
├── .vscode
├── Dockerfile
├── LICENSE
├── README.md
├── app
│ ├── __init__.py
│ ├── __main__.py
│ ├── __pycache__
│ ├── assets
│ ├── config.toml
│ ├── config_manage.py
│ ├── cryptact.py
│ ├── dcc_manage.py
│ ├── df_manage.py
│ └── subscan.py
├── ci
│ ├── run_git_tag_base_pyproject.py
│ └── update_pyproject_version.py
├── docker-compose.yaml
├── poetry.lock
├── pyproject.toml
├── requirements-dev.txt
├── requirements.txt
├── scripts
│ └── create_post-commit.sh
└── tests
├── __init__.py
└── test_cryptact.py
続けて方針に従いDockerfileとdocker-compose.yamlを作成します。
Dockerfile
# ベースとなるDockerイメージを指定
FROM python:3.10
# 作業ディレクトリを設定
WORKDIR /
# APTパッケージインストール / パッケージアーカイブのキャッシュ削除 / パッケージリストのキャッシュ削除
# 日本語のロケールを指定
RUN apt-get update && \
apt-get -y --no-install-recommends install locales && \
localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
# ターミナルエミュレーターにxtermを指定する
ENV TERM xterm
# Poetryのインストール
## https://python-poetry.org/docs/#installing-with-the-official-installer
### Linux, macOS, Windows (WSL)
RUN curl -sSL https://install.python-poetry.org | python3 -
# Poetryのパスをunix指定で設定
## https://python-poetry.org/docs/#installing-with-the-official-installer
### Add Poetry to your PATH
ENV PATH /root/.local/bin:$PATH
# Poetryが仮想環境を生成しないようにする
RUN poetry config virtualenvs.create false
# 作業ディレクトリを/dlSubscanStakingRewardsHistoryDashに設定
WORKDIR /dlSubscanStakingRewardsHistoryDash
# 依存関係のコピー
COPY pyproject.toml poetry.lock ./
# 依存関係のインストール
RUN poetry install
# アプリケーションのコピー
COPY ./app ./app
COPY ./tests ./tests
COPY ./ci ./ci
COPY README.md .
補足: Dockerfile用のlinterについて
pre-commitではpre-commit hookとして以下のDockerfile linterが公開されています。
Dockerfileの構文や指定について指摘されるため、pre-commitを利用している場合は下記指定で使用できます。
実際に、Dockerfileはフックの結果を元に作成しています。個人的には有用だと感じました。
.pre-commit-config.yaml
# https://github.com/pryorda/dockerfilelint-precommit-hooks#usage
- repo: https://github.com/pryorda/dockerfilelint-precommit-hooks
rev: v0.1.0
hooks:
- id: dockerfilelint
stages: [commit]
docker-compose.yaml
# Docker Composeのバージョン指定
version: '3'
services:
# アプリケーションサービスの設定
app:
# カレントディレクトリをベースにビルド
build: .
# コンテナの名前を指定
container_name: 'dlssrhd'
# ターミナルの割り当てを有効にする
tty: true
# ボリュームのマウント設定
volumes:
- ./app:/dlSubscanStakingRewardsHistoryDash/app
- ./tests:/dlSubscanStakingRewardsHistoryDash/tests
- ./ci:/dlSubscanStakingRewardsHistoryDash/ci
- ./pyproject.toml:/dlSubscanStakingRewardsHistoryDash/pyproject.toml
- ./poetry.lock:/dlSubscanStakingRewardsHistoryDash/poetry.lock
- ./README.md:/dlSubscanStakingRewardsHistoryDash/README.md
# ポートのマッピング
ports:
- 8050:8050
# アプリケーションの起動コマンド実行
command: ["poetry", "run", "python", "app"]
補足: docker compose ファイルが有効かどうかをチェックするpre-commit
pre-commitではpre-commit hookとして以下のdocker-pre-commitが公開されています。
docker-compose configコマンドを使用して、作成したdocker-compose.yamlについて環境変数の評価や、ファイルのインクルードなど、Composeファイルが正しく構成されているかどうかを確認するとができます。pre-commitを利用している場合は下記指定で使用できます。
実際に、docker-compose.yamlに適用し、指摘はありませんでしたが、docker-compose configをpre-commitで実行できるので有用だと思います。
.pre-commit-config.yaml
# https://github.com/IamTheFij/docker-pre-commit#installation
- repo: https://github.com/iamthefij/docker-pre-commit
rev: v3.0.1
hooks:
- id: docker-compose-check
Docker環境の構築
docker-compose upでappサービスのdlssrhdコンテナを起動する
処理の流れ
docker-compose upコマンド実行:docker-compose upコマンドを実行すると、Docker Composeは指定されたdocker-compose.yamlを読み込みます。
ベースとなるDockerイメージのダウンロード:
python:3.10というベースイメージがなければ、このイメージをDocker Hubからダウンロードします。
Dockerfileのビルド:
- ダウンロードしたベースイメージを元に、指定されたDockerfileがビルドされます。
- ビルドの際には、各命令が順番に実行されます。
Poetryのインストール:
Poetryのパスの設定:
- インストールしたPoetryのパスを環境変数に追加します。
Poetryの仮想環境生成設定:
- Poetryが仮想環境を生成しないように設定します。
作業ディレクトリの変更:
- 以降の作業は、
/dlSubscanStakingRewardsHistoryDashディレクトリで行います。
- 以降の作業は、
依存関係のコピーとインストール:
pyproject.tomlとpoetry.lockがコピーされ、Poetryを使用して依存関係がインストールされます。
アプリケーションのコピー:
./app、./tests、./ci、README.mdがコピーされます。
ポートのバインドとコンテナの起動:
docker-compose.yamlで指定されたポート8050がホストマシンのポート8050にバインドされ、dlssrhdという名前のコンテナが起動されます。
Pseudo-TTYの割り当て:
tty: trueが指定されているため、コンテナ内で対話的なシェルを使用できるようになります。
docker-compose.yamlのcommandの指定:
docker-compose.yamlでcommand: ["poetry", "run", "python", "app"]の指定からデフォルトのコンテナ起動時のコマンドとして使用されます。
これにより、docker-compose upコマンドによって、指定されたサービス(appサービス)に基づいたコンテナが構築、起動され、アプリケーションが実行されます。
補足:CMDとcommandの使い分け
プロジェクトの運用方針にもよりますが、CMDとcommandの両方を使用する場合はdocker-compose.yamlのcommandが優先されるようなので、個人的にはcommandでコマンド実行するのが良いと思います。
参考記事
CMDのみを使用する場合:
CMD ["poetry", "run", "python", "app"]- コンテナが実行されるときに、何もコマンドが指定されなかった場合は
CMDで指定されたコマンドが実行されます。
- コンテナが実行されるときに、何もコマンドが指定されなかった場合は
commandのみを使用する場合:
command: ["poetry", "run", "python", "app"]docker-compose.yamlのcommandでコンテナの起動時のコマンドを上書きします。CMDにコマンドの指定がある場合でも、docker-compose.yamlのcommandで指定したコマンドが優先されます。
CMDとcommandの両方を使用する場合:
CMD ["poetry", "run", "python", "app"]command: ["poetry", "run", "python", "app"]- この場合、
docker-compose.yamlのcommandが優先されます。
- この場合、
補足:コンテナの起動方法
参考記事
コンテナ一覧を表示
% docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 5c41a6c6a8ca dlsubscanstakingrewardshistorydash-app "poetry run python a…" 5 hours ago Up 22 seconds 0.0.0.0:8050->8050/tcp dlssrhd
単一コンテナ起動: docker start "CONTAINER ID"
% docker start 5c41a6c6a8ca 5c41a6c6a8ca
複数コンテナ(アプリケーション)の起動: docker compose up
appサービスのdlssrhdコンテナを起動する
% docker compose up [+] Building 0.0s (0/0) docker:desktop-linux [+] Running 1/0 ✔ Container dlssrhd Created 0.0s Attaching to dlssrhd dlssrhd | Skipping virtualenv creation, as specified in config file. dlssrhd | Dash is running on http://0.0.0.0:8050/ dlssrhd | dlssrhd | * Serving Flask app '__main__' dlssrhd | * Debug mode: on # Ctrl+Cで停止 ^CGracefully stopping... (press Ctrl+C again to force) Aborting on container exit... [+] Stopping 1/1 ✔ Container dlssrhd Stopped 0.3s canceled # -d(デタッチドモード) でバックグラウンドでサービスを実行 % docker compose up -d [+] Building 0.0s (0/0) docker:desktop-linux [+] Running 1/1 ✔ Container dlssrhd Started
まとめ
実際のプロジェクトを例にPoetryを使用したDocker環境の構築方法について紹介しました。
環境構築について、プロジェクトではフォルダ構成を維持して、全てのファイルをコピーせず、必要なファイルをコピーしたかったので、実際に作成することで処理の流れを理解することができました。
Docker環境のインストールは必要ですが、実際にMacとWindows(WSL)でgitクローンしてdocker-compose upコマンドを実行してwebアプリを起動できることを確認できました。
今後や他のプログラミング言語やDBと組み合わせたサービスについても、調査して作成してみたいと思います。
以上です。