こんにちは、全力開発部の @konoka-iori です。

2024年に入ってからDockerとDev Containerを使った開発環境のコンテナー化に興味を持ち、実際に開発中のプロジェクトに導入してみたので、その過程で得た知見等をまとめていきたいと思います。

きっかけ

私は主にPythonで開発を行っており、Pythonではpipenvを使って仮想環境を構築し、プロジェクトごとに依存関係を管理していました。

しかし、PCごとにインストールされているPythonのバージョンが異なっており、さらに別の言語やフレームワークを使ったプロジェクトもあるため、開発環境の構築に手間がかかるようになっていました。

そこで、開発環境丸ごとコンテナー化できないものかと考えるようになり、DockerとDev Containerを使った開発環境のコンテナー化を試してみることにしました。

Dev Containerとは

Dev Containerは、VS Codeの拡張機能で、開発環境をコンテナー化して開発するためのツールです。 以下のリンクからインストールできます。

Dev Containers - Visual Studio Marketplace -

Extension for Visual Studio Code - Open any folder or repository inside a Docker container and take advantage of Visual Studio Code's full feature set.

Dev Containerの使い方や設定方法については、以下の公式ドキュメントを参照してください。

Developing inside a Container using Visual Studio Code Remote Development -

Developing inside a Container using Visual Studio Code Remote Development

また、以下のZennの記事もわかりやすくて参考になります。

Dev Containerを使ってみよう - Zenn

Dev Containerのよいところ

普通に Dockerfiledocker-compose.yml を使って環境構築してもよいのですが、Dev ContainerのよいところはVS Codeでの開発に特化しているところです。

たとえば、Dev Containerを通じてVS Codeの拡張機能をインストールしたり、設定を記述したりできます。

プロジェクトごとに異なる拡張機能や設定を使いたい場合に便利ですし、チーム開発においては開発環境の統一と同期がしやすくなります。 .vscode/settings.json.vscode/extensions.json に設定を記述することでも同じようなことができますが、 devcontainer.json に記述しておくことで、コンテナー構築時に設定を自動で適用することができるので手間が省けます。

このようにVS Codeとの連携が強く、開発環境に関してはDev Containerを使ったほうが簡単で便利だと感じました。

また、DockerやDocker Composeを使ったことがなくても、Dev Containerは比較的簡単に開発環境をコンテナー化することができるので、入門として良い選択肢だと思います。

慣れてきたら devcontainer.jsonimage に自分で作った Dockerfile を指定することもできますので、柔軟に開発環境を構築できます。

コンテナー化の手順

私の場合は、すでにローカル環境で開発が進んでいたので、リポジトリにそのまま .devcontainer/devcontainer.json を作成しました。

devcontainer.json には、コンテナーの設定や拡張機能のインストールなどを記述します。

たとえば、私が開発している konoka-iori/gemini-discord-botdevcontainer.json は以下のようになっています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
	"name": "gemini-discord-bot",
	"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
	"features": {
		"ghcr.io/devcontainers-contrib/features/pipenv:2": {}
	},
	"customizations": {
		"vscode": {
			"settings": {
				"editor.defaultFormatter": "ms-python.autopep8",
				"python.defaultInterpreterPath": ".venv/bin/python3.11",
				"[markdown]": {
					"editor.defaultFormatter": "yzhang.markdown-all-in-one"
				},
				"markdownlint.config": {
					"MD013": false,
					"MD025": false,
					"MD033": false,
					"MD024": false
				}
			},
			"extensions": [
				"njpwerner.autodocstring",
				"GitHub.vscode-pull-request-github",
				"yzhang.markdown-all-in-one",
				"shd101wyy.markdown-preview-enhanced",
				"DavidAnson.vscode-markdownlint",
				"ms-python.mypy-type-checker",
				"ms-python.vscode-pylance",
				"ms-python.python",
				"ms-python.debugpy",
				"ms-python.autopep8",
				"ms-python.isort",
				"Gruntfuggly.todo-tree"
			]
		}
	},
	"containerEnv": {
		"PIPENV_VENV_IN_PROJECT": "1"
	},
	"runArgs": [
		"--name", "gemini-discord-bot",
		"-e", "TZ=Asia/Tokyo"
	],
	"postCreateCommand": "pipenv sync --dev"
}
これはGitHubから自動で取得したコードです。最新のコードはリンク先をご確認ください。最終同期日時: 2024-10-27

この時点でローカルに変更がある場合は、すべてcommitしておきます。

devcontainer.json の設定が終わったらcommitして、pushします。

次に、VS Codeでリポジトリを開いて、コマンドパレットから「Clone Repository in Container Volume(コンテナーボリュームにリポジトリを複製)」を選択してリポジトリを選び、コンテナーを起動します。

Tip
「Clone Repository in Container Volume」を使うことで、ローカルの環境を汚さずにコンテナー内で開発を行うことができます。 また、「Clone Repository in Container Volume」を使うとnamed volumeにリポジトリが複製されるため、Bind Mountするファイルがなくなります。 これにより、I/Oパフォーマンスが改善されて快適な開発ができます。

最後に、ローカルリポジトリを削除して、完了です。これで開発環境がコンテナー化されました。

コンテナー化してよかったこと

コンテナー化してよかったことをいくつか挙げてみます。

環境構築の楽さ

環境構築はもっとも面倒かつ時間のかかる作業であり、ハードルが高いと感じていたので、それが解消されたことは大きなメリットだと思います。

環境構築が楽になったことで、開発に対するモチベーションも上がりました。

開発環境の統一と同期がしやすい

開発環境をコンテナー化したことで、複数のPCで開発環境が統一・同期され、どこでも同じ環境で開発ができるようになりました。

これまでプロジェクトごとに異なっていた拡張機能やVS Codeの設定を devcontainer.json を使って管理できるようになり、混沌としていたVS Codeの拡張機能や設定が整理されて、設定ミスを防げるようになりました。

チーム開発においては、開発環境の統一が行われ、メンバーの環境依存による混乱や問題が解消されて、開発効率が劇的に向上しました。開発環境が同じであるため、コードレビューやデバッグもスムーズに行える上、作業の引き継ぎもしやすくなりました。

devcontainer.json によって拡張機能や設定が統一されるようになったことで、(Pythonを使う場合は)Pylanceやautopep8、mypyなどのチェックを自動で行えるので、コードの品質管理がしやすくなりました。私はレビュアーを担当することが多いのでこれはとてもありがたいです。

ローカル環境の汚染を避けられる

また、私はローカル環境の汚染を避けたいと強く感じていたので、コンテナー化することでローカル環境にはDockerとVS Codeがインストールされていればよいという状態になってとても晴れやかな気分です。

これでローカル環境からPythonやJavaなどを削除し、きれいな状態を保つことができるようになりました。

Dev Containerの課題

Dev Containerを使ってみて、いくつか課題があることも感じました。

まず、イメージサイズです。 Dockerfile を作らず、Dev Containerを使ってコンテナーを構築する場合、 Dockerfile で作成したイメージよりもサイズが大きくなりがちです。また、それに伴ってコンテナーの起動時間が遅いと感じることがあります。 スリムで軽量なイメージを作りたいときは、 Dockerfile を使ってイメージを作成することをおすすめします。

次に、プロジェクトにコントリビュートする際、コンテナーをどのようにビルドすれば良いかわからないという声がチーム内からありました。 コンテナーのビルド方法として「Reopen in Container(コンテナーで開く)」と「Clone Repository in Container Volume(コンテナーボリュームにリポジトリを複製)」などがあり、どれを使えばよいかわかりにくいという声がありました。

Note
弊チームでは CONTRIBUTING.md に「Clone Repository in Container Volume」を使ってビルドするように記述し、コントリビューターにビルド方法を共有しています。

まとめ

DockerとDev Containerを使った開発環境のコンテナー化について紹介しました。

Dev Containerを使うことで、開発環境の統一や同期が容易になり、ローカル環境の汚染を避けることができます。 また、環境構築が楽になり、開発効率が向上しました。

しかし、イメージサイズやコンテナーのビルド方法に関する課題もあります。 これらの課題を解決するためには、 Dockerfile を使ってスリムなイメージを作成することや、チーム内でのビルド方法の共有が重要だと感じました。