VSCode Remote Containers を使うなら dotfiles repository で幸せになろう

## VSCode Remote Containers とは

Docker コンテナを開発環境として使用するための VSCode 拡張機能です。

https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers

コンテナ内に開発環境を構築することで、PC の環境を汚さずにプロジェクトごとに言語やツールを使い分けることができます。
また、Dockerfile で開発環境を定義できるためチーム内で開発環境を共有することが容易になります。

Qiita 等に紹介記事がたくさんあるため詳しい説明や使い方については割愛します。

## DevContainer と dotfiles

※ この記事では VSCode Remote Container で接続している開発用のコンテナのことを DevContainer と呼称します

DevContainer で開発するということは当然 DevContainer の shell 環境を使用することになります。
デフォルトの状態の shell は使いにくいので、必然的に `.bashrc` (`.zshrc`) などの設定ファイルを用意して自分好みにカスタマイズしたくなることでしょう。

しかしこういった設定ファイルを DevContainer 内で作成してしまうと DevContainer がステートフルになってしまうのであまり良くありません。
となるとホスト側にある設定ファイルを bind mount するという方法もありますが、`devcontainer.json` をリポジトリで管理して共有しているプロジェクトなどでは使えません。

そこで登場するのが (Linux 使いにとってはおなじみの) dotfiles repository です。
これは `.bashrc` などの shell の設定ファイルやコマンドラインツールなどの設定ファイル (いわゆる `dotfiles`) を Git で管理して、あらゆる Linux 環境で共有できるようにしようというアイディアです。
次の記事でとても分かりやすく解説されているため、dotfiles についてよく知らない人は一読することをおすすめします。

https://qiita.com/yutkat/items/c6c7584d9795799ee164

VSCode Remote Container には [dotfiles repository のサポート](https://code.visualstudio.com/docs/remote/containers#_personalizing-with-dotfile-repositories)が組み込まれており、次のような User 設定を行うことで DevContainer 起動時に dotfiles をインストールしてくれるようになります。

```json:settings.json
{
  "dotfiles.repository": "https://github.com/frozenbonito/dotfiles.git",
  "dotfiles.targetPath": "~/dotfiles",
  "dotfiles.installCommand": "install.sh"
}
```

- `dotfiles.repository`
  - DevContainer に適用させたい dotfiles を管理しているリポジトリを clone するための URL を指定します
  - GitHub で管理している場合は `frozenbonito/dotfiles` のように `owner/repo` 形式で記述することもできます
- `dotfiles.targetPath`
  - dotfiles を clone する DevContainer 内のディレクトリのパスを指定します
  - デフォルトは `~/dotfiles` です
- `dotfiles.installCommand`
  - dotfiles をインストールするために実行するコマンドのパス (リポジトリルートからの相対パス) を指定します
    - dotfiles repository の clone 後に実行されます

dotfiles をインストールするためのコマンドは自分で用意して repository 内に含めておく必要があります。
dotfiles のインストールや同期を行ってくれるツールは色々とありますが、`dotfiles.installCommand` に設定するコマンドはどんな DevContainer でも動かせるように shell script で書いておくのが無難です。
前述した [dotfiles の解説記事で紹介されているインストーラ](https://qiita.com/yutkat/items/c6c7584d9795799ee164#%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AAdotfiles%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%A9%E3%83%BC%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)が参考になると思います。

インストーラは実行権限を付与した状態で commit する必要があることに注意してください。

```console
$ git update-index --add --chmod=+x install.sh
```

## Tips

### dotfiles を SSH で取得する

なんらかの理由で HTTPS を使って clone することができない場合は、次のように SSH 形式で `dotfiles.repository` を設定してあげれば SSH で clone することも可能です(`owner/repo` 形式で設定した場合は GitHub から HTTPS で clone されます)。

```json:settings.json
{
  "dotfiles.repository": "git@github.com:frozenbonito/dotfiles.git"
}
```

この場合、Git の SSH key を DevContainer で使えるようにしておく必要があります。
公式ドキュメントの次の部分を参考にしてください(ホスト側で SSH Agent を動かしてあげる感じです)。

https://code.visualstudio.com/docs/remote/containers#_using-ssh-keys

ホストが WSL2 の場合は次の記事も参考になるかと思います。

https://qiita.com/frozenbonito/items/5bb6f30f1e8df8e02317

### dotfiles で DevContainer かどうかを判定する

DevContainer 以外の環境でも使用している dotfiles の場合、DevContainer 環境でのみ有効にしたい設定(あるいは有効にしたくない設定)が出てくるかもしれません。
DevContainer では環境変数 `REMOTE_CONTAINERS=true` が設定されるので、こちらを参照して判定すると良いでしょう。

https://github.com/microsoft/vscode-remote-release/issues/3517