Dev Container をカスタマイズする

前回までで、Dev Containerによる開発環境構築、shell環境を整えることが可能になりました。
今回はさらに一歩進んで、開発環境をカスタマイズする方法を紹介します。

設定ファイルを編集する

Dev Containerの設定ファイルは、.devcontainer/devcontainer.jsonにあります。
このファイルを編集することで、開発環境をカスタマイズできます。
設定の詳細は、Dev Container metadata referenceにあります。
ここでは、よく使う設定を紹介します。

name

Dev Containerの名前を指定します。これを設定すると、接続時にDev Containerの名前が表示されます。

remoteEnv

Dev Containerに渡す環境変数を指定します。
変数記法と組み合わせることで、ローカルの環境変数を引き継ぐこともできます。

{
  "remoteEnv": {
    "ENV1": "value1",
    "ENV2": "${localEnv:ENV2}"
  }
}

上の例では、ENV1という環境変数にvalue1という値を設定しています。
また、ENV2という環境変数に、ローカルの環境変数ENV2の値を設定しています。

remoteUser

デフォルトではDev Containerに接続するユーザーはDockerイメージのユーザーと同じになります。
例えば、mcr.microsoft.com/devcontainers/javascript-node:1-20-bullseyeイメージの場合は、nodeユーザーです。
remoteUserを指定すると、接続するユーザーを変更できます。

{
  "remoteUser": "root"
}
features

Dev Containerに追加の機能を設定します。
例えば、最新版のGitをインストールするghcr.io/devcontainers/features/git や、Docker in Dockerを実現するghcr.io/devcontainers/features/docker-in-dockerなどがあります。

{
  "features": {
    "ghcr.io/devcontainers/features/git:1": {
      "ppa": false
    },
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  }
}

上の例では、gitdocker-in-dockerの2つのFeaturesを利用しています。
また、gitには"ppa": falseというオプションを指定しています。
オプションの詳細や、利用可能なFeaturesについては、Available Dev Container Featuresから確認できます。

customizations

Dev Containerに対してエディター設定などを行えます。
この記事ではVisual Studio Codeを使用していますので、Visual Studio Codeの設定方法を紹介します。

{
  "customizations": {
    "vscode": {
      "settings": {
        "terminal.integrated.defaultProfile.linux": "zsh"
      },
      "extensions": ["esbenp.prettier-vscode"]
    }
  }
}

上の例では、settings"terminal.integrated.defaultProfile.linux": "zsh"を設定することで既定のターミナルをzshに変更しています。
また、extensionsesbenp.prettier-vscodeを設定することで、Prettierの拡張機能をインストールしています。

ここからは、ライフサイクルスクリプトです。コンテナの作維持や起動時に実行するコマンドを設定できます。

initializeCommand

Dev Containerの初期化時に実行するコマンドを指定します。Dev Containerへの接続を開始する時に、ローカルマシンで実行されます。

{
  "initializeCommand": "echo 'Initializing'"
}
onCreateCommand, updateContentCommand, postCreateCommand

これらのコマンドはDev Containerが作成された時にだけ、Dev Container内で実行されます。それぞれの実行タイミングは以下のとおりで、上から順に実行されます。

コマンド実行タイミング
onCreateCommandDev Containerが初めて起動した直後
updateContentCommand作成中にソースツリーで新しいコンテンツが利用可能になった時
postCreateCommandDev Containerが初めてユーザーに割り当てられたとき
{
  "onCreateCommand": "echo 'onCreate'",
  "updateContentCommand": "echo 'updateContent'",
  "postCreateCommand": "echo 'postCreate'"
}
postStartCommand, postAttachCommand

これらのコマンドはDev Containerが起動した時に毎回、Dev Container内で実行されます。
それぞれの実行タイミングは以下のとおりで、上から順に実行されます。

コマンド実行タイミング
postStartCommandDev Containerが起動した直後
postAttachCommandDev Containerに接続した直後
{
  "postStartCommand": "echo 'postStart'",
  "postAttachCommand": "echo 'postAttach'"
}

Docker Composeを使用する

Dev ContainerはDockerイメージをベースに作成され、devcontainer.jsonに設定を追加することで、ビルド時のオプション設定などが行えます。
また、Docker Composeを使用することで、複数のコンテナを同時に起動できます。
通常の開発では、複数のコンテナを同時に起動することが多いため、Docker Composeを使用することをおすすめします。
Docker Composeの設定はdocker-compose.ymlに記述しますので、devcontainer.jsonの設定項目は少なくなります。

.devcontainer/docker-compose.ymlを作成し、以下のように記述します。

services:
  app:
    image: mcr.microsoft.com/devcontainers/javascript-node:1-20-bullseye
    volumes:
      - ..:/workspace:cached
    command: sleep infinity

そして、devcontainer.jsonに以下のように記述します。

{
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace"
}

この状態で、Dev Containerを起動すると、appサービスに接続した状態でVisual Studio Codeが再起動します。

設定ファイル再掲

最終的に、devcontainer.jsondocker-compose.ymlは以下のようになりました。

devcontainer.json
{
  "name": "Asagi",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "customizations": {
    "vscode": {
      "settings": { "terminal.integrated.defaultProfile.linux": "zsh" },
      "extensions": [
        "christian-kohler.npm-intellisense",
        "christian-kohler.path-intellisense",
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "github.copilot",
        "visualStudioExptTeam.vscodeintellicode"
      ]
    }
  }
}

拡張機能はいくつか追加しています。

docker-compose.yml
services:
  app:
    image: mcr.microsoft.com/devcontainers/javascript-node:1-20-bullseye
    volumes:
      - ..:/workspace:cached
    command: sleep infinity

まとめ

Dev Containerをカスタマイズする方法を紹介しました。
カスタマイズすることで、用途に合わせたDev Container環境を構築することが可能です。定期的に設定を見直すことで、さらに開発効率を上げることができます。
自分のニーズに合わせてカスタマイズしてみてください。

外部リンク