🐈‍⬛

Dev ContainerテンプレートでPython+GPU環境を爆速立ち上げ

テラーノベルで機械学習を担当している川尻です。

私たちの機械学習プロジェクトでは、VSCodeのDevelopment Containers (以下、dev container)を使用しています。dev containerでは、開発に必要なツールを事前にイメージに格納し、開発はコンテナ内で行います。一度設定を完了すれば、チーム全体で環境を共有でき、大変便利です。VSCodeだけでなく、Jetbrains系のIDEやクラウド上でのリモート開発もサポートされています[1]

dev container
Developing inside a Container より引用

しかし、設定項目が増えてくると、新規プロジェクトを立ち上げるたびに、毎回同様の設定をコピーしなければならず、めんどくさいです。そんなときdev containerには、カスタムでテンプレートを作成して簡単に公開する方法が用意されています。この記事では具体的な手順と使用方法を紹介します。例として、GPUをすぐに使えるPython環境をベースにして、よく使うdev containerのFeatureやVSCode Extensionが最初から含まれているテンプレートを作成します。今回作成したテンプレートのコード全体は、以下のリポジトリで公開しています。

https://github.com/rkawajiri/devcontainer-templates

テンプレートを作成

簡単にテンプレートを作成できるようにサンプルのリポジトリが用意されているので、こちらをベースに修正していきます。
https://github.com/devcontainers/template-starter

このサンプルには、基本的なテストや公開のためのGithub Actionsも用意されています。もとのリポジトリは以下のように一つのリポジトリで複数のテンプレートを管理するようになっています。hellocolorという簡単なサンプルのテンプレートが用意されています。hellocolorは削除して、pythonという名前のテンプレートを作っていきます。

├── src
│   ├── color
│   │   ├── devcontainer-template.json
│   │   └──| .devcontainer
│   │      └── devcontainer.json
│   ├── hello
│   │   ├── devcontainer-template.json
│   │   └──| .devcontainer
│   │      ├── devcontainer.json
│   │      └── Dockerfile
|   ├── ...
│   │   ├── devcontainer-template.json
│   │   └──| .devcontainer
│   │      └── devcontainer.json
├── test
│   ├── color
│   │   └── test.sh
│   ├── hello
│   │   └── test.sh
│   └──test-utils
│      └── test-utils.sh
...

このリポジトリ自体がdev containerで開発できるようになっているので、dev containerで開きましょう。テンプレートのビルドに最低限必要なファイルは、src/python/devcontainer-template.jsonsrc/python/.devcontainer/devcontainer.json の2つです。その他、必要に応じて通常のdev containerと同様にsrc/python.devcontainer/以下に、Dockerfiledocker-composer.yamlなどを追加していきます。

最小限のdevcontainer-template.jsonを書くと以下のようになります。ここでは"id"src/以下のフォルダ名が一致するようにしてください。Github Actionsで実行するスクリプトがこれを前提としています。その他のプロパティについてはドキュメントを参照してください[2]

src/python/devcontainer-template.json
{
    "id": "python",
    "version": "0.1.0",
    "name": "Python with GPU",
    "description": "Python with GPU",
    "platforms": [
        "Python"
    ]
}

あとは、普段開発で使っているdevcontainer.jsonの設定を書いていくだけです。共通で使うVSCode Extensionやdev container Featureを追加しておくとよいでしょう。便利なdev container Featureは以下のページで検索できるようになっています。

https://containers.dev/features

GPUを使う設定はdocker-compose.yamlで書けますが、GPUがない環境では起動できないため、CI環境などではテストが通りません。そこで、GPUを使うためのComposeの設定は別ファイル docker-compose.gpu.yaml に分けておいて、使うときにだけ読み込むようにします。

src/python/.devcontainer/devcontainer.json
{
    "name": "Python with GPU",
    "dockerComposeFile": [
        "docker-compose.yml",
        // "docker-compose.gpu.yml" // Comment out
    ],
    ...

テストのコードは以下のように書いていきます。DockerfileやFeatureなどでインストールしたコマンドが存在しているかのチェックが基本になるかと思います。

test/python/test.sh
#!/bin/bash
cd $(dirname "$0")
source test-utils.sh

# Template specific tests
check "python" python --version
check "poetry" poetry --version
check "gcloud" gcloud --version
check "gcloud-config" ls ~/.config/gcloud
check "git-lfs" git lfs --version

# Report result
reportResults

テストの実行は以下のようにします。

$ ./.github/actions/smoke-test/build.sh python
$ ./.github/actions/smoke-test/test.sh python

失敗した場合は、エラーを確認して修正してください。その際の注意点として、用意されているスクリプトの不具合(仕様?)で、テストまで正常に動作しないと一時フォルダが削除されず、もう一度ビルドするときに失敗することがあります。そのためビルドを再度実行したい場合は、一度一時フォルダを手で消してください。

$ rm -r /tmp/python

テストまで通ったら、テストがGithub Actionsで実行されるように、設定を修正して起きます。

.github/workflows/test-pr.yaml
...
jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      templates: ${{ steps.filter.outputs.changes }}
    steps:
      - uses: dorny/paths-filter@v2
        id: filter
        with:
          filters: |
-            color: ./**/color/**
-            hello: ./**/hello/**
+            python: ./**/python/**
...

テンプレートを公開

Github ActionsからGithub Pakcagesにテンプレートをアップロードすることで公開します。リリース用のWorkflowの中では、Github Pakcageへのアップロード以外に、各テンプレートのREADME.mdを自動で生成してPRを作成します。

まずは、WorkflowからPRが作成できるようする権限設定として、このリポジトリの Settings > Actions > General > Workflow permissions から 「Allow GitHub Actions to create and approve pull requests」 にチェックが入っていることを確認してください。

続いてリリースのタスクを実行するために Actions > Workflows から 「Release Dev Container Templates & Generate Documentation」 を開きます。右上の 「Run workflow」 からブランチを選択して、Workflowを実行します。完了を待つとPackagesに作成したテンプレートが追加されているはずです。

作成されたテンプレートはデフォルトではプライベートになっていますが、現状はパブリックにしないと使えません。Packages からテンプレートを選択して、 Package settings > Change Visibility を選んで設定を変更してください。

テンプレートを使う

いよいよテンプレートを使って、Dev Containerを立ち上げます。まずは、Dev Container CLIをインストールします。VSCodeのコマンドパレットからインストールする方法か、npmでインストールする方法が簡単です[3]。あとは、プロジェクトディレクトリの中で、先程公開したイメージを指定してコマンドを実行するだけです。

$ mkdir test-proj
$ cd test-proj
$ devcontainer templates apply --template-id=ghcr.io/rkawajiri/devcontainer-templates/python:latest
[2 ms] @devcontainers/cli 0.58.0. Node.js v18.16.0. linux 5.15.146.1-microsoft-standard-WSL2 x64.
{"files":["./.devcontainer/Dockerfile","./.devcontainer/devcontainer.json","./.devcontainer/docker-compose.gpu.yml","./.devcontainer/docker-compose.yml"]}

GPUを使えるようにするには、以下のように修正します。

.devcontainer/devcontainer.json
    "dockerComposeFile": [
        "docker-compose.yml",
-        // "docker-compose.gpu.yml" // Comment out
+        "docker-compose.gpu.yml"
    ],
    "service": "app", 

あとはお好きなIDEでこのフォルダを開けばdevcontainerで開発ができます。VSCodeのcodeコマンドをインストールしてあれば以下のコマンドでも開けます。

code .

まとめ

テンプレートのサンプルリポジトリには、テンプレートを検索してもらえるように公開インデックス[4]に登録する方法なども説明されているため、ぜひ見てみてください。公開インデックスに追加すると、VSCode内から直接テンプレートを使ってプロジェクトを作ることもできるようです。

みなさんもテンプレートを作って公開してみてはどうでしょうか?

脚注
  1. dev containerのサポートツール: https://containers.dev/supporting ↩︎

  2. devcontainer-template.jsonのプロパティ: https://containers.dev/implementors/templates/#devcontainer-template-properties ↩︎

  3. Dev Container CLI Installation: https://code.visualstudio.com/docs/devcontainers/devcontainer-cli#_installation ↩︎

  4. Dev Contaienr Tempalteの公開インデックス: https://containers.dev/templates ↩︎

テラーノベル テックブログ

Discussion