GameWith Developer Blog

GameWith のエンジニア、デザイナーが技術について日々発信していきます。

Dev ContainerでVSCode拡張機能が動作しない時に試すこと

はじめに

こんにちは。サービス開発部の木村です。

アドベントカレンダー18日目の記事として、Dev ContainerでVSCode拡張機能を使う際のナレッジについて紹介します。

Dev ContainerではVSCodeの実行環境をコンテナ化している都合上、ローカルのVSCodeに拡張機能をインストールしているだけでは動作しない物も多くあります。動作しない時の原因特定に役立つように、基礎知識と見直す箇所の情報をまとめました。

Dev ContainerにおけるVSCode拡張機能の取り扱いに関してはVSCodeの公式ドキュメントに記載されていますが、情報が断片的だったり、設定パターンが複数あり正しく設定しないとDev Container上では拡張機能が動作しない場合もあるため、困った時の参考になれば幸いです。

https://code.visualstudio.com/docs/devcontainers/containers

この記事の内容はVSCodeのVersion 1.96.0で動作確認をしています。

また、Dev Container自体の簡単な説明や導入時のポイント等をまとめた記事を以前投稿しています。気になる方は是非合わせて読んでください。

tech.gamewith.co.jp

Dev ContainerにおけるVSCode拡張機能の基礎知識

VSCodeでデフォルトのローカル開発をする際にはただ拡張機能をインストールすれば問題なく動作しますが、Dev ContainerではVSCodeの実行環境がコンテナ化されているため、ローカルのVSCodeにインストールした拡張機能はコンテナ上では動作しないことが多いです。

基礎知識として、Dev Container上では通常時のVSCodeと違い、どこにインストールされた拡張機能をどこで実行するべきかを把握すると、動作しない時の状況把握がスムーズになります。

結論だけ気になる方はVSCode拡張機能が動作しない時に試すことまで飛ばして頂いて構いません。

拡張機能のインストール場所

Dev Containerを使う上でのVSCode拡張機能のインストール場所が2つあります。

  • ローカル
    • ローカルのVSCodeにインストールされたもの。
    • 普段Dev Containerに関係なくインストールした拡張機能はこちらに該当します。
  • コンテナ
    • Dev Containerで起動したDockerコンテナにインストールされたもの。

インストール場所による挙動の違いの一例として、バックグラウンドでワークスペース内のファイルを参照する拡張機能は、コンテナにインストールしないと動作しないものもあります。

Dev Container起動中のVSCodeのExtensionsタブで、次のキャプチャのようにそれぞれの拡張機能がどこにインストールされているのかを確認できます。

Extensionsタブの中でLocalとDev Containerで項目が分かれており、インストールされている場所毎に拡張機能がグルーピングされています。

LOCALでグレーアウトしてInstall in Dev Containerと表示されている拡張機能は、ローカルにインストールされていますが、コンテナ上で実行できない状態にあることを表しています。

コンテナに拡張機能をインストールして使用する方法

ローカルではなくコンテナに拡張機能をインストールするには、下記のような方法があります。

  1. devcontainer.jsoncustomizations.vscode.extensionsで拡張機能IDを指定する。
  2. User Settingsのdev.containers.defaultExtensionsで拡張機能ID指定する。
  3. VSCodeのExtensionsタブのInstall in Dev Containerボタンをクリックする。

1つ目のdevcontainer.jsonは通常リポジトリ内で管理されるため、リポジトリで使用されている技術スタックやチームの開発フロー上使用するものなど、チームで共通して使用したい拡張機能はこちらの方法を用いるのが望ましいです。

git関連などの個人的にインストールしたい拡張機能は、2つ目のUser Settingsを使用する方法を使うべきです。ただし、プロジェクト毎に管理ができず、異なるリポジトリのDev Containerにもインストールされてしまうので、その点は注意が必要です。

3つ目のGUIからインストールする方法は、Dockerコンテナを作り直した際に消えてしまうので、その手間を把握した上で利用を検討しましょう。

ローカルの拡張機能をコンテナで使用する方法

User Settingsのremote.extensionKindで拡張機能IDと後述する実行場所を指定することで、ローカルにインストールされた拡張機能をコンテナで強制的に実行することができます。

{
    "remote.extensionKind": {
        "alefragnani.Bookmarks": ["ui", "workspace"],
        "mechatroner.rainbow-csv": ["ui"]
    }
}

"ui""workspace"の両方を指定した場合は両方の実行場所で適用されるため一応どちらの領域もカバーできますが、開発環境のパフォーマンス低下の要因にも成り得るため、可能であれば必要最低限の設定にした方が良さそうです。

拡張機能の実行場所

Dev Container上でVSCode拡張機能が実行される場所が2つあり、拡張機能の実装によって実行場所が異なります。

  • "workspace"
    • ワークスペース内のファイルを編集する拡張機能(フォーマッターなど)
    • ワークスペース内のファイルをバックグラウンドで参照する拡張機能(git関連や静的解析ツールなど)
  • "ui"
    • VSCodeのUIや開いているファイルの見た目を変更する拡張機能(シンタックスハイライト系や全角文字可視化系など)
    • その他ファイルへのアクセスを必要としない拡張機能

拡張機能毎の実行場所は、拡張機能のリポジトリにあるpackage.jsonremote.extensionKindに定義されている物もあるため、必要に応じて確認すると良いでしょう。

全てコンテナにインストールすれば解決するのか

調査前は、ローカルから強制実行するのではなく全てコンテナにインストールする方が管理が楽なのではと思いましたがダメでした。

"ui"で実行される拡張機能の多くは、コンテナにインストールしても動作せず、remote.extensionKindで明示的に実行場所を指定しないと動作しませんでした。

そのため、インストール先と実行場所の使い分けからは避けられません。

VSCode拡張機能が動作しない時に試すこと

基礎知識を踏まえて、Dev Container上でVSCode拡張機能が動作しない時の、個人的な確認手順の紹介です。動作しない時は、基本的にインストール場所または実行場所が適切ではないことが多いです。

私は、拡張機能の分類ごとに次のような手順で試すようにしています。

バックグラウンドでファイルへの参照や編集を行う拡張機能の場合

バックグラウンドでファイルへの参照や編集を行う拡張機能の場合、コンテナにインストールされているか確認します。

もしインストールされていなければ、ユースケースごとの設定でコンテナにインストールします。

  1. リポジトリやチームに依存する場合はdevcontainer.jsoncustomizations.vscode.extensionsを使用する。
  2. 個人的にインストールしたい場合はUser Settingsのdev.containers.defaultExtensionsを使用する。
  3. 一時的な利用ではVSCodeのExtensionsタブのInstall in Dev Containerを使用する。

調査前はremote.extensionKind"workspace"を指定する方法でも良さそうと思っていたのですが、実際に試すとGitLensPHP Intelephenseのような開いているファイル以外にもアクセスするような拡張機能が動作しなかったため、バックグラウンドでファイルの参照を行う拡張機能はコンテナにインストールしてしまう方が確実だと感じています。

開いているファイルのみの参照や編集を行う拡張機能の場合

拡張機能の実装によっていくつかパターンがありますが、バックグラウンドでファイルへの参照や編集を行う拡張機能と同様にコンテナにインストールするか、基本的にUser Settingsのremote.extensionKindでローカルの拡張機能を強制実行することで動作するようになります。

ローカルの拡張機能を実行する場合は、下記のような手順で試すと良いです。

  1. 拡張機能のリポジトリにあるpackage.jsonremote.extensionKindが定義されている場合は、User Settingsのremote.extensionKindで同様の値を指定する。
  2. 開いているファイルに書き込みを行う場合はUser Settingsのremote.extensionKind"workspace"を指定する。
  3. 開いているファイルの参照だけを行う場合はUser Settingsのremote.extensionKind"ui"を指定する。
{
    "remote.extensionKind": {
        // `package.json`に`remote.extensionKind`が定義されている値を採用する例
        // https://github.com/alefragnani/vscode-numbered-bookmarks/blob/v8.5.0/package.json#L10-L13
        "alefragnani.Bookmarks": ["ui", "workspace"],

        // 開いているファイルの編集を行う拡張機能の例
        "EditorConfig.EditorConfig": ["workspace"],

        // 開いているファイルの参照だけを行う拡張機能の例
        "zh9528.file-size": ["workspace"]
    }
}

ファイルへのアクセスを行わない拡張機能の場合

基本的にローカルのインストールされた拡張機能がそのまま使えるか、User Settingsのremote.extensionKind"ui"を指定し、コンテナで強制実行することで動作します。

{
    "remote.extensionKind": {
        "tonybaloney.vscode-pets": ["ui"]
    }
}

さいごに

ローカル開発と比べて拡張機能の管理が複雑ですが、一度設定できてしまえば後はローカル開発と同じ感覚で開発できて快適です。

拡張機能が動作せずにDev Containerの導入を辞めたり開発環境を妥協するのは勿体無いので、この記事が参考になれば幸いです。


こんなGameWithではエンジニアを絶賛募集中です!

サーバーエンジニアやフロントエンジニアの方、AIに興味がある方や、Unityでの開発に興味がある方もお気軽にカジュアル面談をお申し込みください!

github.com