Devcontainer.jsonの基本的な書き方と設計について
はじめに
前回の記事では、Dev Containersが解決できる課題と基本的な概念について説明しました。今回は実際にdevcontainer.json
を利用して、Dev Container環境を構築する方法について詳しく解説していきます。書き方については公式のDocumentや他の記事、AI利用等で問題なく情報を得ることができるため、本記事ではdevcontainer.json
の基本的な構文と主要な設定項目、その仕組みについて焦点を当てることにします。
devcontainer.jsonとは
devcontainer.json
は、Dev Container環境の設定を定義するJSONファイルです。このファイルにより、開発環境に必要なツール、VSCode拡張機能、環境変数などを宣言的に定義することができます。以前の記事で記載した通り、このファイルを作成することで開発環境の再現性が向上し、チーム全体で統一された開発環境を簡単に構築することができるようになります。
ファイルの配置場所
devcontainer.json
は以下のいずれかの場所に配置します。
.devcontainer/devcontainer.json
または
.devcontainer.json
推奨は.devcontainer/
ディレクトリ内への配置です。これにより、Dockerfileやその他の関連ファイルを同じディレクトリにまとめることができるようになります。
imageの選択
最もシンプルなdevcontainer.json
の例としては以下のような記述になります。
{
"name": "My Dev Container",
"image": "mcr.microsoft.com/devcontainers/python:1-3.13-bullseye"
}
この例では、Microsoftが提供するPythonイメージを使用して、基本的なDev Container環境を構築しています。
利用できるイメージの一覧については以下のリンクから確認することができます。
これらのイメージを利用しないで独自のDockerfileを使用することも可能です。その場合は以下のように記述することになります。
{
"name": "My Dev Container",
"dockerfile": "Dockerfile",
"context": ".."
}
一般的な開発においては、公式のDev Containerイメージを使用することで、必要なツールやライブラリが事前にインストールされた状態で環境を構築することができます。ただし、不要なツール等もインストールされている可能性があるため、軽量なコンテナを求める場合は、独自のDockerfileを使用して必要なツールのみをインストールすることが推奨されます。一方で、必要なツールを追加する場合は後述のfeatures
セクションを利用することで、簡単に追加することができます。
Features
例えばPythonのImageにGitHub CLIをインストールした開発環境を構築する場合、以下のようにfeatures
セクションを使用するだけでツールのインストールが可能になります。
{
"name": "Node.js & Python Environment",
"image": "mcr.microsoft.com/devcontainers/python:1-3.13-bullseye",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {}
}
}
これにより、Dev Container内でGitHub CLIが自動的にインストールされることになります。Featuresは、Dev Container内で必要なツールやライブラリを簡単にインストールできる仕組みです。
利用できるFeaturesの一覧については以下のリンクから確認することができます。
Featuresの仕組み
Featuresは、OCI(Open Container Initiative)に準拠したコンテナイメージの一部として提供されるコンポーネントです。Baseのイメージの拡張パーツのような形で利用され、Dev Containerの機能を拡張します。
Featuresはメタデータであるdevcontainer-feature.jsonと設定用のScriptのinstall.shで構成されています。
参考:https://github.com/devcontainers/features/tree/main/src/aws-cli
そのため、自作のFeaturesを作成することも可能ですが、Dockerfileを使用してカスタムイメージを作る方が簡単で柔軟性があるため、外部に広くあまねく公開したい機能でない限りは自作Featuresを作るケースは少ないと思います。
Dev Containersの環境においてPython pyenv相当の仮想環境は必要か
一般的な開発環境では、Pyenvなどの仮想環境管理ツールが必須とされていますが、Dev Containers環境では状況が異なります。Dev Container自体がコンテナによって隔離された環境として機能するため、追加して仮想環境を構築する必要がありません。
Pythonのバージョン管理についても、Pyenvを使用する代わりに、Dev Containerのベースイメージを変更することで簡単に切り替えることができます。例えば、Python 3.11からPython 3.13に変更したい場合は、devcontainer.json
のimageプロパティを以下のように変更するだけです。
{
"name": "Python 3.13 Development",
"image": "mcr.microsoft.com/devcontainers/python:1-3.13-bullseye"
}
Poetryの様なパッケージ管理ツールについてはチームの方針や好みによって必要になってくるので、必要に応じてfeaturesを利用してインストールしましょう。
Extensions
Extensionsセクションでは、Dev Container内で自動的にインストールされるVSCode拡張機能を指定することができます。チームの中でExtensionを統一したい場合、この機能はとても効果的です。また、開発環境を移行する場合にもどのExtensionを利用していたかなどを意識する必要がないため、非常に便利です。
{
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-python.pylint",
"ms-python.black-formatter",
"ms-vscode.vscode-typescript-next",
"esbenp.prettier-vscode",
"bradlc.vscode-tailwindcss"
]
}
}
}
Extensionをdevcontainer.json
に追加するときは、VSCodeのExtentionの設定からAdd to devcontainer.json
を選択することで、簡単に追加することができます。追加されている名前はExtensionのIDで、VSCodeのExtension Marketplaceで確認することができます。
VSCodeの設定カスタマイズ
拡張機能だけでなく、VSCodeの設定も統一できます。利用する言語はFrameworkではPathを通す必要があったりするため、この機能を利用することで開発環境のセットアップの手間を大幅に削減することができます。
{
"customizations": {
"vscode": {
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"files.exclude": {
"**/__pycache__": true,
"**/.pytest_cache": true
}
}
}
}
}
Lifecycle scripts
devcontainer.json
では、コンテナのライフサイクルに応じて特定のコマンドを実行するためのフックを設定できます。これにより、環境構築やサービスの起動などを自動化できます。
このあたりは公式のドキュメントが最も情報量が多いのでそちらを参照してください。
pip install -r requirements.txt
やnpm install
などのコマンドを自動で実行するのが一般的な使い方になると思います。実施したいコマンドによって呼び出すLifecycleは異なると思いますが、初期設定としては基本的にはpostCreateCommandで呼び出しておけば問題はないと思います。
{
"postCreateCommand": "pip install -r requirements.txt"
}
複数のコマンドを実行したい場合は、&&でコマンドを配列で実行する形式で実行可能です。Listでの実行はエラーとなります。
※8/20 修正。うらがみ様ご指摘ありがとうございました。
{
"postCreateCommand":"pip install -r requirements.txt && pre-commit install"
}
初期セットアップのコマンドの数が多くなる場合は、スクリプトファイルを作成してそれを呼び出す形を検討ことも選択肢に入ります。
{
"postCreateCommand": "./scripts/setup.sh"
}
但し、この場合はスクリプトファイルを修正した場合にDev Containerが構成ファイルの変更を検知することができないため、devcontainer.json
に列挙して記載することが良いかもしれません。
ネットワーク自動化開発におけるdevcontainer.jsonの例
筆者はネットワーク自動化のプロジェクトに携わることが多いため、ネットワーク自動化におけるdevcontainer.json
の例を示します。ネットワーク自動化開発においては基本的にはPythonを利用することになるため、BaseのImageはPythonにしておくのが無難です。featuresに関してはGitHub CLIやgo-taskを利用することが多いと思います。また、重要な要素として自動化開発の途中で装置にpingを打つことは多いと思いますが、pingコマンドはデフォルトではインストールされていないことが多いので、必要に応じてpostCreateCommand
で追加する必要があります。
PythonのLibraryに関してはiPythonやnetmiko等が必要になると思いますが、それらはrequirements.txt
に記載しておくことで、postCreateCommandで自動的にインストールされるようにしておくのが無難です。
※8/27 修正。Hiroshi Koyama様ご指摘ありがとうございました。
{
"name": "Network Automation Environment",
"image": "mcr.microsoft.com/devcontainers/python:1-3.13-bullseye",
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/go-task:1": {}
},
"postCreateCommand":"apt-get update && apt-get install -y iputils-ping && pip install -r requirements.txt"
}
Team内での共通のdevcontainer.json
を作成して、GitHubのTemplate Repositoryとして公開しています。これによって、devcontainer.json
を1から作ったことが無いメンバーでも恩恵を受けつつ、修正をしながら習熟していける様な運用をしています。
まとめ
この記事では、devcontainer.json
の基本的な書き方と主要な設定項目について説明しました
- Features: 開発ツールの簡単インストール
- Extensions: VSCode拡張機能の統一
- Lifecycle Script: 環境構築の自動化
Featuresで対応できない複雑な環境構築が必要な場合は、Dockerfileを使用したカスタムイメージの作成が必要になりますが、基本的にはimageとfeaturesを組み合わせることで、ほとんどの開発環境を簡単に構築することができます。
Dockerfileを書けないとDev Containerを使えないということはなく、devcontainer.json
を適切に設定することで、ほとんどの開発環境を簡単に構築することが可能ですし、そこから受けられる恩恵は非常に大きいため積極的に利用することをお勧めします。
Discussion
以下のように書かれていますが、この例はうまく動作しないのではないでしょうか?
単一の文字列の場合は
/bin/sh
で実行され、配列の場合はシェルを使用せず直接コマンドが実行されます。DockerfileにおけるCMD
やENTRYPOINT
と同様ですね。記事中にリンクされている公式ドキュメントにもその仕様が書かれています。
以上のことから、記事中で例示されている
postCreateCommand
はうまく動作しないと思いますが、いかがでしょうか。ご連絡ありがとうございます。ご指摘の通りですね。。
間違った情報を公開してしまい、申し訳ございませんでした。
指摘頂いた内容について修正させていただきました。ご指摘、ありがとうございました。
お名前記載させて頂いておりますが、不都合ありましたら削除しますのでお申し付けください。
ご対応ありがとうございます!
名前の記載は何も問題ありません。ご配慮ありがとうございます。
最後の例の下記について
こちらも次のように
&&
で連結する必要はないでしょうか。ご指摘の通りですね。。ありがとうございます。
指摘頂いた内容について修正させていただきました。ご指摘、ありがとうございました。
お名前記載させて頂いておりますが、不都合ありましたら削除しますのでお申し付けください。