Trying out the Dev Containers feature.
- Dev Containersを使うと,Docker Container内でVS Codeを開くことができ,コンテナ内のソースコードを直接編集できる
- Dev Containers起動時に設定ファイルに記載のあるVS CodeのExtensions等も一括でインストールできる --> チームで開発環境を統一しやすい
- Dockerfileやcompose.yamlを汚さずにツールのインストールや設定変更ができる
- GitHub Codespacesを使用する際にDev Containeersを選択することで,環境構築を自動化できる。
- React with Vite
- nginx
- install Docker, VS Code
- clone this repository
- install Dev Containers VS Code Extensions
code ~/devcontainer-testIn VS Code, from the command palette, select Reopen in Container
Note
To rebuild Dev Container,use Rebuild and Reopen in Container or Rebuild without cache and Reopen in Container.
Warning
When an error occurs during Dev Containers build, clearing the cache and rebuilding may solve the problem.
docker rm $(docker ps -a -q)
docker rmi $(docker images -q)
docker builder prunedeploy react app with nginx.
docker compose upgo to http://localhost:80
Dev Containerを使うにあたってのtips等をまとめる。
基本的にコンテナにデプロイ時に不必要なものは含めたくないので,Multi Stage buildを使ってDev Containers用の環境を作ることが推奨される。
-
compose.yamlを使わず,Dockerfile使う場合にはdevcontainer.jsonでtargetの指定ができる。
FROM mcr.microsoft.com/devcontainers/typescript-node:22-bookworm AS devcontainer # target名を指定する -
.devcontainer/devcontainer.jsonでtargetを指定する
A string that specifies a Docker image build target that should be passed when building a Dockerfile. Defaults to not set. For example: "build": { "target": "development" } 1
{ "name": "dev-container-test", "build": { "dockerfile": "Dockerfile", "target": "devcontainer" }, }
compose.yamlを使う場合にはtargetをcompose.yaml側で指定するためにDev Containers用に.devcontainer/compose.yamlを作成する必要がある。2,3
# compose.yaml
services:
react-app:
build:
target: devcontainer // targetを指定
context: ./
dockerfile: Dockerfile
image: react-img-devcontainer:latest
container_name: react-container-devcontainerFROM mcr.microsoft.com/devcontainers/typescript-node:22-bookworm AS devcontainer # target名を指定するNote
compose.yamlのservices名をdevcontainer.jsonのserviceに指定する。
{
"name": "dev-container-test", // 任意の名前
"dockerComposeFile": [
"../compose.yaml",
"compose.yaml"
],
"service": "react-app", // compose.yamlのサービス名
}Dev Containers公式イメージがいくつかの言語ではサポートされている。
Note
例えば,base-debianはbuilderpack-depsをベースにして作成されている。 builderpack-depsとは,ビルド時に必要なパッケージをまとめたイメージ。
A collection of common build dependencies used for installing various modules, e.g., gems.4
Note
dotfilesは設定ファイルやスクリプト等をまとめたリポジトリのこと。 e.g. .bashrc, .gitconfig, .vimrc, etc.
VSCodeの個人用のsettings.jsonに以下を参考に記載することでdotfilesをDev Containersに持ち込むことができる。5
[!NOTE]: .gitconfigは何もしなくてもDev ContainersのHOMEディレクトリにコピーされる。
// Dev Containersでdotfilesを使う。
"dotfiles.repository": "https://github.com/RyosukeDTomita/dotfiles.git", // fixme
"dotfiles.targetPath": "~/dotfiles", // fixme
"dotfiles.installCommand": "install.sh", // fixme ~/dotfilesのrepository topからみたスクリプトのパスを指定する。Note
dotfiles.installCommandには~/dotfilesのrepository topから見たスクリプトのパスを指定する。
そのため,dotfilesのGitHub Repositoryにinstall.shは配置が必要。自分のdotfilesのinstall.sh
Note
dotfiles.installCommandを指定しない場合にはデフォルトのファイル名として以下が存在すればdotfilesのinstallが実行されるとVS Codeの設定画面に記載がある。
Dev Containerの環境では,REMOTE_CONTAINERS=trueが環境変数に定義されており,これを使ってDev Containerかどうかを判別できるためローカル用とDev Containers用で処理を分けることができる。dotfilesのinstall scriptでREMOTE_CONTAINERS=trueで分岐する例
- devcontainer.jsonと.vscode/settings.json両方に記載ができる。
- 基本は.vscode/settings.json配下に設定を記載するで良いと思っている。
Extension IDを.devcontainer/devcontainer.jsonに記載することで追加できる。

"extensions": [
"formulahendry.auto-rename-tag",
],:::note info Add to devcontainer.jsonを選択できるのでこれを使うと楽 :::
- 個人用のsettings.jsonに記載することで,リポジトリの設定を変更せずにExtensionsを追加できる。
// Dev containersに個人的に使うExtensionsを入れる。
"dev.containers.defaultExtensions": [
"vscodevim.vim"
],devcontainer.jsonでportを開放する方法は3つある。
addPortは非推奨。forwardPortsを使う方が良い。In most cases, we recommend using the new forwardPorts property. 6
forwardPortsを使うことで,コンテナのポートをローカルにフォワードすることができる。portAttributesを使うことで,portに関連する追加属性を設定することができる。
Note
2025年3月に動作検証したところ,ローカルのVS CodeではportAttributeのみでportフォワーディングが可能だった。
しかし,GitHub Codespacesを使う場合にはportAttributesのみではportフォワーディングがされなかった。
portAttributesのみ
forwardPortsも追加すると自動的にportフォワーディングされる
実際に公式ドキュメントにはforwardPortsのみしか記載がなく7,forwardPortsとportAttributesを併用することが推奨される。
{
"name": "dev-container-test", // 任意の値
"dockerComposeFile": [
"../compose.yaml",
"compose.yaml"
],
"service": "react-app", // compose.yamlのサービス名
"workspaceFolder": "/app",
"forwardPorts" : [5173, 5173],
"portsAttributes": {
"5173:5173": {
"label": "Vite application",
"protocol": "http",
"onAutoForward": "notify"
}
},
"postStartCommand": "cd react-app/ && yarn dev --host 0.0.0.0",
}Dev Containersを起動しつづけるために永続コマンドが必要であるが,このサービスの再起動が必要になった場合には,コンテナの再ビルドが必要である。
CMD ["nginx", "-g", "daemon off;"]しかし,これは非効率的なので,Dev Containersにはコンテナのイベントをトリガーしてコマンドを実行する機能8を使い,サービスの再起動を可能にすることができる。
OverrideCommandをtrueに設定することで,コンテナを永続化することができる1。postStartCommandでサービスを起動することで,コンテナの永続化にサービスが使われなくなり,再起動が可能になる。
{
"name": "dev-container-test",
"dockerComposeFile": [
"../compose.yaml",
"compose.yaml"
],
"service": "react-app",
"workspaceFolder": "/app",
"overrideCommand": true,
"forwardPorts" : [80, 80],
"postStartCommand": "nginx"
}- ファイル単体でのマウントは現状できない。
- 設定ファイルは前述のdotfilesを使って共有するのが良い。
- クレデンシャルを含む情報などはGitHubにアップロードできないため,dotfiles経由ではなく,マウント機能を使ってDev Containersに持ち込むのが良い。
{
"name": "dev-container-test",
"dockerComposeFile": [
"../compose.yaml",
"compose.yaml"
],
"service": "react-app",
"workspaceFolder": "/app",
"overrideCommand": true,
"mounts": [
"source=~/.aws,target=/home/root/.aws,type=bind" // ~/.awsをマウントできる
],features一覧から使用可能なツールを探すことができる。
devcontainer.jsonにfeaturesを記載することで,ツールをインストールすることができる。
"features": {
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/guiyomh/features/vim:0": {},
"ghcr.io/dhoeric/features/hadolint:1": {}
},必要そうなパッケージをまとめたshell scriptを作成し,これをpostCreateCommandで実行することでツールをインストールすることができる。
"postCreateCommand": "install-pkg.sh",Footnotes
-
https://containers.dev/implementors/json_reference/#general-properties ↩ ↩2
-
https://github.com/microsoft/vscode-remote-release/issues/7810 ↩
-
https://stackoverflow.com/questions/78421879/devcontainer-docker-compose-best-practice ↩
-
https://code.visualstudio.com/docs/devcontainers/containers#_personalizing-with-dotfile-repositories ↩
-
https://containers.dev/implementors/json_reference/#image-specific ↩
-
https://docs.github.com/en/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace#automatically-forwarding-a-port ↩
-
https://containers.dev/implementors/json_reference/#lifecycle-scripts ↩


