23
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

株式会社日立システムズAdvent Calendar 2020

Day 8

VSCode+WSL2+Dockerによるリモート開発環境の構築 (devcontainer.json概訳付き)

Last updated at Posted at 2020-12-07

はじめに

複数プロジェクトを同時に開発していたりすると依存するライブラリ等がコンフリクトしたり、別の開発者に展開する際に環境構築手順を作らないといけなかったりと地味に時間がかかっています。
またデプロイする際もコンテナで実施することも徐々に増えてきているので、初めからコンテナ上で開発した方がいいよねっていうことでVSCodeの拡張機能「Remote - Containers」を利用したリモート開発環境を構築したので、それについて紹介いたします。

今回実施した内容は以下の通りとなっています。

  1. 環境構築 (SSH/Docker Context)
  2. リモート上でのWebアプリ開発・デバッグ
  3. 設定ではまったこと
  4. (参考)devcontainerイメージ一覧
  5. (参考)devcontainer.json設定一覧

構築した環境

構築した環境は以下の通り。WSL2のUbuntu上にDockerをインストールし、そこに接続する形をとっています。
別サーバー上にDockerをインストールしてリモート開発する場合も、ほぼ手順は同じかと思います。
※透過プロキシが入っているのはプロキシ設定を省略するのが目的です。もし必要があれば別記事についても参照ください。
環境概要

1. 環境構築

標準の手順では、VSCodeのsetting.jsonにDockerの接続先を設定していますが、ここでは接続先を切り替えることを考慮してDocker Contextによる接続先の設定、およびDocker拡張機能によるコンテキストの設定方法を説明します。

1.1. SSH認証キーの作成と設定

Docker Contextによる接続では、パスワードによる認証に対応していないため、SSH認証キーを作成しそれぞれ設定します。
ここでは、Windows 10に付属しているOpenSSHを利用します。
OpenSSHをインストールされていない場合は「設定→アプリ→オプション機能→機能の追加」よりOpenSSH サーバー、およびOpenSSH クライアントをインストールしてください。

Local(PowerShell)
> ssh-keygen -t ecdsa -f keyfile

作成された公開鍵id_ecdsa.pubをリモート上に転送し、~/.ssh/authorized_keysに登録します。

Remote(WSL2)
$ cat keyfile.pub >> /home/<user>/.ssh/authorized_keys
$ chmod 600 /home/<user>//.ssh/authorized_keys

もしWSL2を利用されている場合は、dockerと同様に下記の通りSSHのサービスを起動し必要があればWindowsのポートフォワードもしてください。

Remote(WSL2)
$ sudo service ssh start

1.2. Docker Contextの作成

作成した認証キーの登録し、Docker Contextの作成を行います。最後のdockerコマンドで作成したContextを指定し、リモート上の実行中のコンテナ一覧が表示されれば正常に作成されています。

Local(PowerShell)
> sc config ssh-agent start=auto
> net start ssh-agent
> ssh-add ./keyfile

> docker context create remote1 --docker "host=ssh://<user>@<remote hostname>:<port>"
> docker --context=remote1 ps

※ssh-addでエラーが発生した場合、OpenSSH サーバーがインストールされているか確認してください(参考記事4)。

1.3. VSCode拡張機能のインストール

VSCodeには以下の2つの拡張機能をインストールしてください。

  • Docker
  • Remote - Containers

Docker拡張機能をインストールすると新たにタブが追加されるので、そのタブを開きCONTEXTSを開くとDocker Contextの一覧が表示されます。
ここで先ほど作成したContextを利用するように設定(右クリック→USE)します。Context横に接続マークが表示されていれば設定完了です。

Docker Contextの選択

2. リモートでのWebアプリ開発・デバッグ

ここではASP.net coreを例に、リモート上でWebアプリの開発、およびデバッグするまでの手順を記載いたします。
リモート上になりますので、ローカルファイルシステムのマウントは出来ず、図に記載した通りリモート上のファイルシステムをマウントするように設定します。

2.1. コンテナ開発設定の初期化

  • Ctrl+Shift+Pを押下しコマンドパレット表示後、Remote-Containers: Add Development Container Configuration Filesを選択します。
    コンテナ開発設定の追加

  • 追加する設定テンプレート一覧が表示されます。ここではShow All Definitions...をクリックし、言語別のテンプレートを表示させます。
    テンプレート一覧(初期)

  • C# を選択すると、.net coreのバージョンやオプションについて聞かれますが、デフォルトのままでOKボタンを押下します。
    テンプレート一覧(言語別)

  • 選択したテンプレートにてdevcontainer.jsonDockerfile等が作成されれば初期化は完了です。
    リモートコンテナプロジェクト設定完了

2.2. プロジェクトの設定変更

リモート上へのマウント設定の追加

データを保持するために、リモート上にプロジェクト用のフォルダを作成します。
ここでは仮にログインユーザのホームディレクトリにworkspacesフォルダを作成し、また、その下に項2.1で初期化したフォルダと同名のフォルダを作成します。
これはデフォルトの設定では、コンテナ起動後のVSCode接続時にワークスペースフォルダ中にあるプロジェクトフォルダを開きにいくためです。

Remote
$ mkdir -p  /home/<user>/workspaces/<Project Folder Name>

devcontainer.jsonworkspaceMountの項目を追加し、上記のworkspacesフォルダとのマッピングを追加します。
target=の設定については、Dockerfileで利用したベースイメージの仕様になります。

devcontainer.json
{
    // ---  ----
    "workspaceMount": "source=/home/<user>/workspaces,target=/workspaces,type=bind,consistency=cached",
    // ---  ----
}

ユーザ設定の変更

次にリモート上のユーザと、コンテナ上で実行されるユーザの整合性を取るようにします。
ここの設定を間違えると、読み書きが出来なかったり、リモート上でファイルを開けなかったりするので注意してください。
はじめにリモートホスト上にログインしたユーザのuidgidを確認します。
※下はユーザremoteでログインした場合一例になります。

Remote
$ id
uid=1001(remote) gid=1001(remote) groups=1001(remote),999(docker)

確認した上記のuidgidでコンテナ上にユーザを作成します。その他のオプションについてはMSガイドを参照してください。
ここでは試しにdevconというユーザ名で作成しています。

Dockerfile
ARG USERNAME=devcon
ARG USER_UID=1001
ARG USER_GID=$USER_UID

# Create the user
RUN groupadd --gid $USER_GID $USERNAME \
    && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
    && apt-get update \
    && apt-get install -y sudo \
    && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
    && chmod 0440 /etc/sudoers.d/$USERNAME

USER $USERNAME

またdevcontainer.jsonにユーザ名を設定します。

devcontainer.json
{
    // ---  ----
    "remoteUser": "devcon"
}

以上で設定の変更は完了です。
後は左下の><アイコンをクリックして出てきたメニューよりRemote-Containers: Reopen in Containerをクリックすると、Dockerイメージがビルドされコンテナの起動とリモート接続が開始されます。

2.3. コンテナでの開発

ここまでくると通常のローカルでの開発とほぼ同じです。
起動したVSCodeからターミナルを開き、dotnetコマンドでプロジェクトを初期化し、F5キーを押下すればデバッグが開始され、ブラウザからの参照やブレークポイントによる変数内容の確認等も可能になってます。

  • プロジェクト初期化
Container
$ dotnet new react
  • Webアプリの参照
    Web画面

  • デバッグ・ブレークポイント
    デバッグ・ブレークポイント確認

上記の通り、VSCodeがデバッグ時にコンテナ上のポートを転送してくれるようになっています。
デバッグを開始した際、左下に「使用可能なポートがX個あります」と表示されていれば転送設定がされており、もしされていない場合はメッセージ部分をクリックすると下記のようなポート転送設定画面が開かれるので、ここに手動で追加してください。

実行時のポート検出

2.4. データのアップロード・ダウンロード

コンテナ上へのデータのアップロード・ダウンロードのVSCodeから行えます。
アップロードする場合は、VSCodeのエクスプローラーにファイルをドラッグ&ドロップするとアップロードでき、ダウンロードする場合は右クリックすると下記の通りダウンロードメニューがあるので、そこから実施できます。

エクスプローラー

3. 設定ではまったこと

ネットワーク環境が異なる場合の注意点 (主にプロキシ設定)

リモート開発時はローカルとネットワーク環境等が異なると思いますが、標準だとVSCode/gitについて設定が引き継がれるようになっています。
このためローカルでプロキシの設定をしていたりすると、一部プラグインがその設定により正常に動作しなかったりするので、その設定を外す必要があります。
これらの設定を外す場合はdevcontainer.jsonを修正し、settingsでVSCodeの設定を、'postStartCommand'でgitの設定を変更するようにします。

devcontainer.jsonを修正後は、設定を反映させるためにVSCodeのウィンドウの再読み込みを行ってください。
これまでの設定を実施したdevcontainer.jsonは以下の通りとなります。

devcontainer.json
{
	"name": "csharp_container",
	"build": {
		"dockerfile": "Dockerfile",
		"args": { 
			"VARIANT": "3.1",
			"INSTALL_NODE": "true",
			"NODE_VERSION": "lts/*",
			"INSTALL_AZURE_CLI": "false"
		}
	},
	"settings": {
		"terminal.integrated.shell.linux": "/bin/bash",
		"http.proxySupport": "off"
	},
	"postStartCommand": "git config --global --unset http.proxy && git config --global --unset https.proxy",
	"extensions": [
		"ms-dotnettools.csharp"
	],
	"workspaceMount": "source=/home/remote/workspaces,target=/workspaces,type=bind,consistency=cached",
	"remoteUser": "devcon"
}

設定失敗時のコンテナイメージのリビルド

Docerfiledevcontainer.jsonの設定について失敗した場合、メニューのRebuild Containerが正常に動作しないことがあります。
この場合はvsc-<Project Folder Name>という名称でイメージが作成されているので、それを手動で削除します。
VSCodeのDockerタブのCONTAINERSより、該当する名称のものを探しRemove...で削除してください。

複数PCからの接続時の注意点

Remote Containers拡張機能では、コンテナイメージの識別に、プロジェクトフォルダのパスを利用している模様です(※20/11/20時点)。
このため注意点として、複数PC(ユーザ)から同一のリモートホスト(Docker)に接続する場合、プロジェクトのパスを変更しなければならない点が挙げられます。
プロジェクトフォルダのパスが同一だった場合でもVSCodeは立ち上がりますが、同一コンテナ上に接続しに行っているためデバッグ時にポートの競合が起きる等の問題が発生してしまいます。

remoteUser指定時の挙動について

devcontainer.jsonの設定説明を見てみると、uid, gidが自動的にマッピングしてくれるとの記載がありますが、そのような挙動は見られませんでした。
利用方法が悪いのかバグなのかは調べきれていませんが、可能な限りDocker上で実行するユーザの設定をしたほうが現時点では無難な感じです。

(参考)devcontainerイメージ一覧

参考までにリモート開発用コンテナ一覧について転記します。
最新のイメージ一覧はこちらから参照してください。

  • mcr.microsoft.com/vscode/devcontainers/base
    • alpine, alpine-3.10, alpine-3.11, alpine-3.12
    • debian, buster, debian-10, stretch, debian-9
    • ubuntu, focal, ubuntu-20.04, bionic, ubuntu-18.04
  • mcr.microsoft.com/vscode/devcontainers/cpp - buster, debian-10, stretch, debian-9
  • mcr.microsoft.com/vscode/devcontainers/dotnetcore - 3.1, 2.1
  • mcr.microsoft.com/vscode/devcontainers/go - 1, 1.15, 1.14
  • mcr.microsoft.com/vscode/devcontainers/java - 8, 11, 14
  • mcr.microsoft.com/vscode/devcontainers/javascript-node - 14, 12, 10
  • mcr.microsoft.com/vscode/devcontainers/php - 7, 7.4, 7.3
  • mcr.microsoft.com/vscode/devcontainers/python - 3, 3.8, 3.7, 3.6
  • mcr.microsoft.com/vscode/devcontainers/anaconda - 3
  • mcr.microsoft.com/vscode/devcontainers/miniconda - 3
  • mcr.microsoft.com/vscode/devcontainers/ruby - 2, 2.7, 2.6, 2.6
  • mcr.microsoft.com/vscode/devcontainers/rust
  • mcr.microsoft.com/vscode/devcontainers/typescript-node - 14, 12, 10
  • mcr.microsoft.com/vscode/devcontainers/universal

(参考)devcontainer.json設定一覧

参考までにdevcontainer.jsonで設定可能な項目の一覧について記載します。
最新の設定はこちらを参照してください。

  • 一般設定項目
設定項目 詳細
name string リモート接続時の表示名を設定します。
extensions array コンテナの作成時にコンテナ内にインストールする必要がある拡張機能を指定する拡張機能IDの配列を設定します。
settings object settings.jsonに設定する内容。コンテナ/マシン固有のデフォルト値を追加。
forwardPorts array コンテナ内からローカルマシンに転送する必要のあるポートの配列を設定します。
postCreateCommand string, array コンテナ作成後にコンテナ内で実行するコマンド文字列またはコマンド引数のリストを設定します。workspaceFolderがカレントディレクトリとなっており、ソースフォルダがマウントされた後に実行されるため、フォルダ内のシェルスクリプト等を実行することも可能です。。
postStartCommand string, array コンテナの開始時に実行するコマンド文字列またはコマンド引数のリストを設定します。その他仕様はpostCreateCommandと同様です。。
postAttachCommand string, array VSCodeが実行中のコンテナにアタッチされた後に実行するコマンド文字列またはコマンド引数のリストを設定します。その他仕様はpostCreateCommandと同様です。
initializeCommand string, array コンテナイメージ構築前、およびコンテナが作成または開始された際にローカル上で実行するコマンド文字列またはコマンド引数のリスト。コマンドはworkspaceFolderにて実行されます。
userEnvProbe enum タスクのデバッグや実行の際に利用するユーザ環境変数について取得するための方法を指定します。
none(デフォルト), interactiveShell. loginShell. loginInteractiveShellが設定可能で、interactiveShellでは/etc/bash.bashrc,.bashrcに設定された内容が、loginShellでは「rc」ファイル、および/etc/profile, .profileに設定された内容が含まれています。
デフォルト値のnone以外のモードでは起動が遅くなる可能性があります。
devPort integer VS CodeServerがコンテナで使用する特ポートを設定します。デフォルトではランダムに設定されます。
  • 共通項目(Dockerイメージ、Dockerfile、Docker Compose)
設定項目 詳細
remoteEnv object VSCode(またはターミナル等のサブプロセス)の環境変数を設定または上書きする名前と値のペアのセット。環境変数と事前定義された変数についても参照可能。[ターミナル]> [統合:環境の継承]が設定でチェックされていることを確認してください。
例:"remoteEnv": { "PATH": "${containerEnv:PATH}:/some/other/path", "MY_VARIABLE": "${localEnv:MY_VARIABLE}" }
remoteUser string コンテナ内で実行されるVSCodeのユーザを設定します(ターミナル、タスク、デバッグ等のサブプロセス含む)。VSCodeが再起動されたとき(またはウィンドウがリロードされたとき)に更新が適用されます。
[コンテナ]
デフォルトはcontainerUserが設定されます。Linuxでは、指定されたコンテナユーザのUID / GIDは、ローカルユーザのUID / GIDと一致するように更新され、バインドマウントでのアクセス許可の問題を回避します。UID / GIDの更新を適用するには、コンテナを再作成する必要があります。
[Compose]
デフォルトではDocker Composeファイルで設定された実行ユーザになります。
workspaceFolder string コンテナに接続時にVSCodeが開くデフォルトのパスを設定します。
[コンテナ] 通常workspaceMountと組み合わせて使用​​します。ソースコードのマウントしたパスです。
[Compose] コンテナ内でソースコードフォルダをマウントしたパスを設定します。デフォルトは"/"
shutdownAction enum ウィンドウが閉じられた(シャットダウンされた)際にコンテナを停止するかどうか。
none, stopContainer(コンテナ時デフォルト), stopCompose(Compose時デフォルト)
  • Dockerイメージ、Dockerfileのみ
設定項目 詳細
image string Dockerイメージを利用する場合必須。
VSCodeがコンテナを作成する際のコンテナレジストリ内のイメージの名前を指定します。
build.dockerfile string Dockerfileを使用する場合に必須。
コンテナの内容を定義するDockerfileの場所。パスはdevcontainer.jsonファイルからの相対パスを記載します。
build.context string docker buildを実行するdevcontainer.jsonからの相対パスを設定します。
build.args object Dockerfileをビルドするときに渡されるDockerイメージビルド引数を含む名前と値のペアのセット。環境変数と事前定義された変数についても参照可能。
例:"build": { "args": { "MYARG": "MYVALUE", "MYARGFROMENVVAR": "${localEnv:VARIABLE_NAME}" } }
build.target string Dockerfileビルドするときに渡されるターゲット文字列を指定します。
例:"build": { "target": "development" }
appPorts integer, string, array 通常はforwardPortsプロパティを使用すること推奨。
このプロパティでは、コンテナのポートフォワード設定についても実施します。
containerEnv object コンテナの環境変数を設定または上書きする名前と値のペアのセット。環境変数と事前定義された変数についても参照可能。
例:"containerEnv": { "MY_VARIABLE": "${localEnv:MY_VARIABLE}" }
containerUser string コンテナで実行される命令について指定したユーザに設定します。デフォルトは、rootまたはDockerfileUSERで指定したユーザになります。
Linuxでは、指定されたコンテナユーザのUID / GIDは、ローカルユーザのUID / GIDと一致するように更新され、バインドマウントでのアクセス許可の問題を回避します
updateRemoteUserUID boolean Linuxでは、containerUserまたはremoteUserが指定されている場合、バインドマウントでのアクセス許可の問題を回避するために、コンテナユーザのUID / GIDがローカルユーザのUID / GIDと一致するように更新されます。デフォルトはtrue
mounts array 作成時にコンテナに追加する追加のマウントポイントの配列。DockerCLIのmountフラグと同じ値をサポートします。環境変数や事前定義された変数についても参照可能です。
例:"mounts": ["source=${localWorkspaceFolder}/app-scripts,target=/usr/local/share/app-scripts,type=bind,consistency=cached"]
workspaceMount string コンテナの作成時に、ワークスペースのデフォルトのローカルマウントポイントを上書きします。DockerCLIのmountフラグと同じ値をサポートします。主に、リモートコンテナの構成やディスクパフォ​​ーマンスを向上させる際に変更します。環境変数や事前定義された変数についても参照可能です。
runArgs array コンテナの実行時に使用するDockerCLI引数の配列。デフォルトは[]。
overrideCommand boolean コンテナのデフォルトコマンドを上書きするか設定します。
デフォルトではtrueに設定されており、/bin/sh -c "while sleep 1000; do :; done"が実行されます。
  • Docker Composeのみ
設定項目 詳細
dockerComposeFile string, array Compose時必須。DockerComposeファイルへのパスまたはパス配列を指定します。パスはdevcontainer.jsonからの相対パスになります。配列で定義した場合、後で定義された内容で上書きされます。
.envファイルはデフォルトではプロジェクトのルートから取得されますが、DockerComposeファイルにて別のパスの指定も可能です。
service string Compose時必須。実行後に接続するサービス名。
runServices array 開始するDocker Compose設定内のサービス名配列。shutdownActionnoneに設定しない限り、VSCode終了時に、これらも停止されます。デフォルトではすべてのサービスが対象です。

最後に

Docker関係の知識は多少必要かもしれませんが、思っていた以上に簡単に、また特段の制限なくWebアプリ等の開発環境が構築可能なことに驚きました。
また外注等の開発者の入れ替わりが激しい場合も容易に開発環境を複製することが出来ますので、かなりメリットが大きいと感じています。
今回記載した記事が、何かしら皆さまのお役に立てれば幸いです。

関連記事

参考記事

  1. VSCodeでリモートホスト上のDocker上で開発する - Qiita
  2. Visual Studio Code Remote Development
  3. Developing inside a Container using Visual Studio Code Remote Development
  4. Can't acess ssh-agent · Issue #1491 · PowerShell/Win32-OpenSSH
  5. VS Code Remote Development Container Images - Docker Hub

商標

  • Microsoft、Windows、Visual Studioは,米国Microsoft Corporationの米国およびその他の国における登録商標または商標です。
  • Ubuntuは,Canonical Ltd.の商標または登録商標です。
  • DockerおよびDockerのロゴはDocker,Inc.の米国およびその他の国における商標または登録商標です。
  • その他記載の会社名、製品名、サービス名等はそれぞれの会社の商標または登録商標です。
23
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?