🐍

Dev Containerを使ってPythonのプロジェクトのテンプレートを作る

2023/04/14に公開

以前にpoetryとmkdocsとsphinxを使ってpythonプロジェクトを作っていきました。

https://zenn.dev/okojomoeko/articles/python-project-with-mkdocs

今回はvs codeのdev containerを使って、みんなが共通のvs codeでチーム開発できるようにdev containerを使ったプロジェクトテンプレートを作成し、どのようにpythonプロジェクトのテンプレートを環境をdev containerで作っていくかというところをメインでメモします。

今回試した環境

  • Ubuntu 22.04.2 LTS (MacBook Air M1のLima 0.15.0上で動かしてます)
  • docker: Docker version 23.0.3, build 3e7cbfd
  • docker compose: Docker Compose version v2.17.2
  • vs code: 1.77.1
  • Dev Containers: v0.288.0

先に結論

下記に今回作ったテンプレートを置いてあります。何かもっとこうしたほうがいいとか誤っている点があれば教えて下さると幸いです。

https://github.com/okojomoeko/devcontainer-python-template

dev containerを設定する

vs code自体はエディターという位置づけですが、dev containerを使えば、containerを使ったプロジェクトに特化した開発環境を簡単に構築できて便利です。

具体的に言うと、devcontainer.jsonという設定ファイルと必要に応じてcontainerで使うDockerfileを用意してvs codeでworkspaceとして開いてあげるだけで、開発環境として使えるようになります。

devcontainer.jsonについては公式でテンプレートとか出してくれていたり、公式のdev containerのコミュニティにテンプレートが転がっており、たまたまですが、pyenvとpoetryな環境のdev containerのテンプレートを作ってくれている方がいたので今回はそれを利用します。

ここから、以前の記事であるpoetryとmkdocsとsphinxのpythonプロジェクトができ上がっている前提から話を進めていきます。

vs codeのコマンドパレットを使ってテンプレートから自分が利用したい環境を作ることができますが、以前の記事でpyenvで3.11.2のpythonを利用するようにしていたので、dev containerの作成時も3.11.2を利用するように、テンプレートを少し修正して利用させてもらいます。

コマンドパレットからのdev container作成
コマンドパレットからのdev container作成

poetryのdev container
poetryの環境がたまたまあった

自分のバージョンが選択できない

オプションとして3.11.2までの指定ができない

ここから、.devcontainer/を一式ダウンロードさせていただき、

下記のDockerfile中のPYTHON_VERSIONを使いたいバージョンに変更します

Dockerfile
FROM mcr.microsoft.com/devcontainers/base:${templateOption:imageVariant}
# FROM mcr.microsoft.com/devcontainers/base:jammy

ARG DEBIAN_FRONTEND=noninteractive
ARG USER=vscode
.
.
# Python and poetry installation
USER $USER
ARG HOME="/home/$USER"
- ARG PYTHON_VERSION=${templateOption:pythonVersion}
+ ARG PYTHON_VERSION=3.11.2
# ARG PYTHON_VERSION=3.10
.
.

この状態でvs codeのコマンドパレットからRebuild and Reopen in Containerを実行すればdev containerのビルドが始まり、プロジェクトがdev containerで開かれます。しかし、dev container上でdockerを扱いたい場合は、devcontainer.jsonに機能追加する形で実現できます。

dev containerでdockerを使えるようにする

docker in dockerやdocker outside of dockerの方法がありますが、これらについての詳細は割愛して使えるようになることを目標に簡単に説明すると、これもdevcontainer.jsonの機能追加という形で簡単に使えるようになるようです。(Use Docker or Kubernetes from a container)

中身としては、dev containerで機能が使えるようになるためのinstall.shが実行される感じっぽいですが、ユーザー側からすれば下記設定を追加するだけで良いのでめちゃ便利です。

今回は前回のプロジェクトを応用するというところで、mkdocsのビルドをdoodでやるのでdoodのfeatureを追加します。

devcontainer.json
  "customizations": {
    "vscode": {
      "extensions": ["ms-python.python", "njpwerner.autodocstring"]
    }
  },
  + "features": {
  +   "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
  + }

実はdev containerをコマンドパレットから作るときにもfeatureを追加できたりするので、色々と自分好みの機能を追加していきましょう。
dood-command-palette

また、ここにさまざまな機能があるのでぜひウォッチしていきましょう。

doodの機能をdev containerで使う際に、ここでは前回使ったhostに存在するmkdocsとかplantumlのコンテナをdev container上で実行させるために、それらのコンテナからワークスペース内のファイルを参照する必要があるのですが、doodのfeaturesのドキュメントには二通りのやり方があるようです。

今回はこちらの方法で実現しました。

この設定を追加することでdoodを使って今回のワークスペースのドキュメントについてビルドしたり内容を確認できるようになります。

ここまでで以前の記事の構成は実現できるようになっているはずですが、今回はテンプレートを作ってみるのでより発展させていきます。

pre-commitを簡単に設定しておく

pre-commitを使うことでgitのワークフローをhookしてさまざまな処理をさせることができます。

詳細はドキュメントや他の紹介されている記事などを参考頂いて、まずはpre-commitの設定ファイルを書いていきます。

今回はこのサンプルを拝借させていただこうと思います。

pytestblackも使えるようになると嬉しいので、サンプルでblackと競合するdouble-quote-string-fixerを消して設定に追加してみました。

yaml
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: debug-statements
-     -   id: double-quote-string-fixer
    .
    .
+ -   repo: https://github.com/psf/black
+     rev: 23.3.0
+     hooks:
+     -   id: black
+   - repo: local
+     hooks:
+       - id: pytest-check
+         name: pytest-check
+         entry: pytest
+         stages:
+             - "push"
+         language: system
+         pass_filenames: false
+         always_run: true

続いて、dev containerのテンプレートプロジェクトを使う人がpre-commitをdev container起動時に使えるようにしたいので、poetryで作った仮想環境を自動で認識してあげるようにdev containerとvs codeを設定します。

dev containerの設定でコンテナ起動時やコンテナ作成時にコマンドを実行させることができるので、今回はコンテナ作成時にpoetryプロジェクトの依存関係とかインストールして、pre-commitの内容を使えるように初期installもします。タイムゾーンとかも設定しちゃいます。

devcontainer.json
  "workspaceFolder": "${localWorkspaceFolder}",
  "workspaceMount": "source=${localWorkspaceFolder},target=${localWorkspaceFolder},type=bind",
+   "postCreateCommand": "poetry install; poetry run pre-commit install;"
+   "containerEnv": { "TZ": "Asia/Tokyo" }

続いて、vs codeでプロジェクトのterminalを開いたときに自動的にpoetryの仮想環境がactivateされるように下記設定をしておきます。

json
{
  "python.terminal.activateEnvInCurrentTerminal": true,
  "python.defaultInterpreterPath": "./.venv/bin/python3"
}

まとめ

これでいい感じにvs codeで実行するpythonプロジェクト環境が完成できました。

サンプルとしてGitHubで作ったプロジェクトテンプレートではドキュメントをビルドするスクリプトとか置いてあるので、

開発 -> テスト -> ドキュメント生成 -> poetry build -> ライセンスチェック

みたいな感じの流れがある程度楽にできると思います。(GitHub Actionsとか入れてないのがちょっとびみょいですが)

vs codeのdev containerは便利だなと改めて感じたので、面倒でなければなるべく使うようにしたいです。

disk performanceについても色々と改善したいので、テンプレートについてはこれからもちょくちょく便利にしていきたいですね。。。

Discussion