概要
WSL2で作ったDockerfileやdocker-compose.ymlをベースに、コンテナ内にアタッチした状態(コンテナに入ってターミナルを開いた状態)で開発を行える仕組み。厳密にはDocker標準の機能ではなく、VSCodeの拡張機能「Remote Development」によって実現されています。
項目 | 内容 |
---|---|
取り扱う内容 | • VS Code Remote Developmentの基本的な仕組みと設定方法 • Remote-Developmentを利用するメリット • docker-compose.yml、devcontainer.jsonの代表的な設定項目 • トラブルシューティング |
想定読者 | • WSL2環境でDockerを使用している開発者 • VS Codeでコンテナ開発を始めようとしている人 • Remote Developmentに絡んでエラーが出て困っている人 |
Remote-Developmentを利用するメリット
通常のDocker環境では、コンテナ内のリソースを利用するために、まずコンテナにアタッチする必要があります。VS CodeのRemote Developmentを使用すると、任意のコンテナにアタッチした状態で開発を開始できるため、以下の機能が直接利用可能になります。
- コンテナ内でのみ利用可能なパッケージやライブラリへの参照
Remote Developmentは、コンテナにアタッチした状態でVSCodeを開きます。これにより、VSCodeの実行環境がホストではなくコンテナ内に移動されます。その結果、コンテナ内にインストールされたパッケージやライブラリを、VSCode上で直接参照・利用することが可能になります。具体的には、コマンド実行やコード入力時の補完、定義ジャンプといった機能を利用する際に、パッケージやライブラリを利用しながら最大限活用できます。 - コンテナ内で実行するサービスのデバッグ
Remote Developmentを使用すると、VSCodeのデバッガーをコンテナ内で実行されているプロセスに直接アタッチできます。これにより、ブレークポイントの設定、変数の監視、ステップ実行などのデバッグ機能を、あたかもローカル環境で開発しているかのように利用できます。
導入手順
VSCodeの拡張機能Remote Development
をインストールします。
VSCodeでコマンドパレットからReopen in Container
すします。初めて実行する場合など、いずれの設定ファイルに基づいてコンテナを起動するか問われる場合があります。docker-compose.yml
が既にある場合、`From docker-compose.yml'を選びます。
追加機能をインストールする画面が出た場合、いずれにもチェックを入れずに「OK」をクリックします。
WSL2側で開いていたプロジェクトのルートディレクトリに.devcontainer
ディレクトリが自動作成されます。中身はdocker-compose.yml
とdevcontainer.json
の2ファイル。既にファイルがある場合は、既存ファイルの内容にしたがってコンテナ起動されます。
この時点でのWSL2側ディレクトリ構成は、以下例のようになっています。
your-project/
├── .devcontainer/ (Remote-Developmentの設定ファイル Reopen in Container時に自動生成)
│ ├── devcontainer.json
│ └── docker-compose.yml
├── frontend/
│ ├── Dockerfile
│ ├── src/
│ ├── package.json
│ └── ... (その他のフロントエンド関連ファイル)
├── backend/
│ ├── Dockerfile
│ ├── src/
│ ├── package.json
│ └── ... (その他のバックエンド関連ファイル)
├── db/
│ └── data/ (データベース関連ファイル、ボリュームマウント用)
├── docker-compose.yml
└── README.md
この構成では、コンテナを起動する方法によって、適用される設定が以下の通りに変わります。
- 通常のdocker-composeコマンドでコンテナを起動する場合
- プロジェクトルート、つまり
your-project/
でdocker-compose up
した場合を指す - プロジェクトルートの
docker-compose.yml
にしたがってコンテナが起動される
- プロジェクトルート、つまり
- VSCodeの
Reopen in Container
を使用する場合
以下すべてを適用してコンテナが起動されます。-
.devcontainer/devcontainer.json
から、VSCode固有の設定(使用する拡張機能、コンテナ起動後のコマンドなど)が適用される。 - プロジェクトルートの
docker-compose.yml
が基本設定として読み込まれる -
.devcontainer/docker-compose.yml
の設定が、上書きまたは追加される
-
設定項目
特に重要だと感じた項目について記載します。
.devcontainer.json
VSCodeがコンテナ内でどのように動作するかを定義する設定ファイル。
- service
コンテナ起動時にアタッチするサービスを指定します。docker-compose.yml
のservices
に記載した名前を指定します。すべてのコンテナを起動した上で、VSCodeのウィンドウおよびターミナルが、ここで指定したコンテナ内で開きます。"service": "frontend",
ここで指定しなかったサービスも、コンテナ自体は起動していますので、そちらの開発や操作を行う場合は、後述の「別のコンテナにアタッチする」を行って別コンテナへアタッチしてください。
docker-compose.yml
ルートディレクトリのdocker-compose.yml
に対して、追加または上書きする設定を保持します。開発環境でだけ適用したい設定があれば、ここに記載するとよいです。ルートディレクトリのdocker-compose.yml
に記載済の設定は引き継がれるので、ここには追加・上書きが必要な設定だけ記載すればよいです。
-
volumes
# ルートディレクトリをコンテナ内の`/workspace`にマウントする。`:cached`はパフォーマンス向上のために使用される - ..:/workspaces:cached
-
command
コンテナ起動時に実行されるコマンド。自動生成された.devcontainer/docker-compose.yml
では以下のコマンドが自動で書き込まれているはず。# コンテナ内でsleepコマンドを走らせて、コンテナがすぐに終了するのを防ぐ command: /bin/sh -c "while sleep 1000; do :; done"
この設定は、 Dockerfileの
CMD
やdocker-compose.ymlのcommand
よりも優先されるので注意しましょう。(例: DockerfileのCMD
にnpm run start
を記載してサービスが自動起動するようにしていても、上記sleepコマンドが優先で実行されて、Dockerfile側のnpm run start
は実行されない。この場合、yaml側のcommandをコメントアウトするなどして対応します)
操作Tips
別のコンテナにアタッチする
VSCodeのコマンドパレットからAttach to Running Container
を実行し、表示されるリストからアタッチしたいコンテナを選択すると、別コンテナのターミナルを別ウィンドウで開くことができます。
使用シーン:
- アタッチ中のコンテナ以外のコンテナでコマンドを実行する必要がある場合
- 複数のコンテナを同時に操作したい場合
- デバッグや監視のために別コンテナの状態を確認したい場合
トラブルシューティング
Dockerfileに加えた変更が反映されない
コンテナの起動時、VSCodeのコマンドパレットからReopen in Container
ではなくRebuild and Reopen in Container Without Cache
してみましょう。コンテナの再ビルドが走るので、変更後のDockerfileに基づいてコンテナが実行されます。
Resolver error: Error: Server returned 404エラー
コンテナ起動時、上記エラーが発生したことがあります。VSCodeのバージョンが古かったのでアップデートしたら解消しました。
VSCodeバージョン:1.87.2 → 1.91.1 にアップデート。
Remote Development拡張機能バージョン:0.25.0
コンテナ内でGitが利用できない
Reopen in Container
をやり直す
端末や環境によるのかもしれないですが、Reopen in Container
したままPCをスリープ→復帰すると、その後のgit操作が以下エラーによって通らなくなることがありました。再度Reopen in Container
すると解消します。コンテナの再ビルドまでは不要で、入り直しさえすればOK。
# 上記該当時のエラー
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
GitHub SSH関連の設定が完了しているか確認する
【Git】WSL2環境でGitを使う場合のGitHub SSHキー設定に記載のSSH Agent設定を行っていない場合、実施します。
WSL2のgitconfig
や.ssh
をマウントしているなら、無効化する
.devcontainer/docker-compose.yml
などDocker関連の設定ファイルで、SSH関連のファイルをコンテナへマウントしている場合、これを解除します。
# 例:volumesの箇所
# ルートディレクトリをコンテナ内の`/workspace`にマウントする。`:cached`はパフォーマンス向上のために使用される
- ..:/workspaces:cached
# 以下はコメントアウトする
# ~/.gitconfig:/home/node/gitconfig
# ~/.ssh:/home/node/.ssh
そもそも、ホスト側のSSH関連ファイルをコンテナ内に持ち込むのは以下の観点から非推奨と思っています。
- ホストとコンテナでユーザーが異なる場合に、マウントされたファイルやディレクトリのアクセス権が書き変わったり、アクセス不可になったりする。コンテナ内で無理やり権限を書き換えて、他のコンテナでそのファイルが読めない事態に陥りがち。
- セキュリティ上、秘密鍵情報がコンテナ内にファイルとして存在している状態は、機密漏洩のリスクにつながる。keychainはメモリ経由で情報が渡るので、鍵の情報が洩れる心配が少ない。
ただし、アサインされたプロジェクトで上記マウントによる方法を採用していたら、チームの方針に従ってください。
Manage Unsafe Repositories ボタンが表示される
Remote Developmentで「Manage Unsafe Repositories」が表示されるを参照して
CMD
やcommand
が無効になる
設定項目に記載のとおり、.devcontainer/docker-compose.yml
のcommand
が有効になっている場合、DockerfileのCMD
やdocker-compose.ymlのcommand
が上書きされて無効化されてしまいます。.devcontainer/docker-compose.yml
のcommand
をコメントアウトして、再度コンテナを起動すると解消します。
特定のコマンドが実行できない
特定のコマンドを実行しようとした際に、command not found
などといってコマンドが実行できない場合、以下を確認してください。
例:
- This command is not available when running the Angular CLI outside a workspace.(Angular関連のコマンド)
対象のパッケージがインストールされているか確認する
コンテナのビルド後など、プロジェクトにおいてnpm install
やpip install
といったパッケージ/ライブラリ追加プロセスが自動化されていない場合、コンテナ起動時点ではまだパッケージがインストールされていない可能性があります。
コンテナ起動時点でパッケージインストールが完了しているか確認し、自動インストール処理があればそちらの復旧を行います。自動でインストールする仕組みが無ければ、手動でインストールを行います。
実行したコマンドがアタッチしていない別コンテナのものでないか確認する
ルートディレクトリ以下すべてのソースコードをマウントしている場合などに混乱しがちだが、Reopen in Container
した際に開いているVSCodeウィンドウやターミナルは、.devcontainer.json
で指定したコンテナ内で開いています。
したがって、仮にフロントエンドのコンテナにアタッチしている場合、バックエンドやデータベースといった別コンテナで動作する前提のコマンドは、アタッチ中のコンテナでは通りません。別のコンテナにアタッチするを参照して、正しいコンテナのウィンドウを開いて実行してください。