要件
- ホスト機は Windows 10 Home Edition 1809+
- コンテナ動作機は VirtualBox 6.0.10 に入れた Ubuntu 18.04 日本語 Remix
- vscode の Visual Studio Code Remote - Containers 拡張機能を使う
- この拡張機能を使うことで、ホスト機(Win)に Language Server やデバッグなどで必要な node.js や PHP などの実行環境をインストールする必要がなくなる!
- ファイルの直接マウントは出来ないので、 sftp 拡張機能を経由する
- docker 19.03
- 本質にかかわらない細かい部分は省略しつつ手順を書いていきます
ホスト機(Win)の準備
OpenSSH をインストール
Windows の OpenSSH のインストール | Microsoft Docs
今は Windows 公式に OpenSSH を入れられるようになったのでありがたい世の中ですね。
> Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
Name : OpenSSH.Client~~~~0.0.1.0
State : NotPresent
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
> Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
Path :
Online : True
RestartNeeded : False
> Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
Name : OpenSSH.Client~~~~0.0.1.0
State : Installed
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
> ssh -V
OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
これで PowerShell, cmd.exe で ssh
コマンドをたたけるようになりました。
docker cli 各種をインストール
Windows 10 Pro+ であれば Hyper-V を用いた Docker for Windows を利用することが出来ますが、 Windows 10 Home Edition では出来ないので、今回は VirtualBox に用意した Ubuntu に docker をインストールし、そこにリモートで接続することで実現してみようと思います。
cli の用意が面倒なので、 Scoop を使ってインストールします。
> scoop install docker docker-compose docker-machine
> docker version
Client:
Version: 19.03.1
API version: 1.40
Go version: go1.12.7
Git commit: 74b1e89e8a
Built: Wed Jul 31 15:18:18 2019
OS/Arch: windows/amd64
Experimental: false
error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.40/version: open //./pipe/docker_engine: The system cannot find the file specified. In the default daemon configuration on Windows, the docker client must be run elevated to connect. This error may also indicate that the docker daemon is not running.
> docker-compose version
docker-compose version 1.24.1, build 4667896b
docker-py version: 3.7.3
CPython version: 3.6.8
OpenSSL version: OpenSSL 1.0.2q 20 Nov 2018
> docker-machine version
docker-machine.exe version 0.16.1, build cce350d7
これで PowerShell, cmd.exe で docker
docker-compose
docker-machine
コマンドをたたけるようになりました。しかしローカル環境には docker engine(実体)がないのでエラーが出ていますね。ここではひとまず無視します。
ゲスト機(Ubuntu)の準備
docker-machine
コマンドを用いて VirtualBox をワンコマンドで立ち上げることも可能ですが、今回は手で Ubuntu Desktop イメージから作ることにします。
- Ubuntu 18.04 日本語 Remix の iso ファイルをダウンロード
- VirtualBox で新規追加で適当に値を埋める
- ディスクサイズは 40 GB くらいあった方が嬉しい(20GB 以下だとたくさん Docker レイヤーが増えると死ぬ)
- iso を設定して起動して、 Ubuntu をインストール
- インストールが終わったら再起動して普通に起動してデスクトップに入る
パッケージ更新
$ sudo apt update \
&& sudo apt full-upgrade -y \
&& sudo apt install openssh-server -y \
&& sudo systemctl start sshd \
&& sudo apt autoremove -y
あたりでパッケージを更新して SSH サーバを用意して再起動。
VirtualBox GuestAddition 用意
GuestAddition を入れてさらに再起動
docker 用意
ここを見ながら docker をインストール
$ docker run --rm hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:6540fc08ee6e6b7b63468dc3317e3303aae178cb8a45ed3123180328bcc1d20f
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
これでゲスト機で docker
コマンドをたたけるようになりました。
リモートからこの docker デーモンを操作出来るように、デフォルトではローカルしか受け付けていない所を上書きして、 TCP 2375 番で受け付けれるようにします。
このあたり(Configuring remote access with systemd unit file)
$ sudo systemctl edit docker.service
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2375 --containerd=/run/containerd/containerd.sock
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker.service
これで任意の外部から tcp://このゲスト機のIP:2375
経由で docker
を操作出来るようになりました (もちろん外部から自由に叩けるということでセキュリティには注意!) 。
ホストからゲストに対して docker
コマンドをたたいてみる
ホスト機から叩けるか確認してみます。
> docker -H tcp://ゲスト機のIP:2375 run --rm hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
...
が出れば Windows 上から docker
コマンドをちゃんと叩けるようになりました。環境変数からホスト名を指定することも出来ます。
> $env:DOCKER_HOST="tcp://ゲスト機のIP:2375"
> docker version
...
vscode の準備
ようやく vscode が出てきました。
Remote - Containers 拡張機能をインストールします。
docker.host
設定に tcp://ゲスト機のIP:2375
を設定します。
左のアクティビティバーの Docker アイコンをクリックして、 Successfully connected, but no items found.
と出れば vscode での docker 接続成功です。やったぜ。
dev container - node を試してみる
Quick start: Try a dev container
こちらを試してみます。今回は node.js の開発用コンテナを用意してみます。
> git clone https://github.com/Microsoft/vscode-remote-try-node
> code vscode-remote-try-node
Docker for Windows や Docker for Mac であればこのままリモートコンテナにローカルのファイルをバインド出来るのですが、 Windows 10 Home さんではそれがかないません。
そこで面倒ですが一個中継を設けます。
sftp でファイル転送
sftp 拡張機能をインストールします。
コマンドパレットで sftp: config
とすると設定出来るようになるので、これを使って SFTP プロトコルでファイルをゲスト機に転送します。
{
"name": "ubuntu1804",
"host": "ゲスト機のIP",
"protocol": "sftp",
"port": 22,
"username": "m-yamagishi",
"remotePath": "/home/m-yamagishi/repos/vscode-remote-try-node",
"ignore": [
".git",
"node_modules"
]
}
設定は各々調整するようにしてください。個人設定が入るので、 .git/hooks/exclude
に .vscode/sftp.json
を追加して git から除外しておくのも大事です。
設定を正しく行ってコマンドから sftp: sync local -> remote
を実行すれば、リモートにファイルが転送されます。
ではリモートのコンテナマウントを、今転送した上記の remotePath
の所に変えましょう。 .devcontainer/devcontainer.json
を修正します。
{
"name": "Node.js Sample",
"dockerFile": "Dockerfile",
"appPort": 3000,
"extensions": [
"dbaeumer.vscode-eslint"
],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"postCreateCommand": "yarn install",
// Comment out the next line to run as root instead. Linux users, update
// Dockerfile with your user's UID/GID if not 1000.
"runArgs": [ "-u", "node" ],
// この二行を追加する
"workspaceFolder": "/workspace",
"workspaceMount": "src=/home/m-yamagishi/repos/vscode-remote-try-node,dst=/workspace,type=bind,consistency=cached"
}
変更したら左下の >< を押します。
Remote-Containers: Open Folder in Container
をコマンドパレットから選択すると、リモートで今のフォルダを開くように動きだします。最初はイメージのビルドが走るので遅いです。
リモートコンテナの展開に成功すると、普通にファイル一覧が出てきます。このファイル一覧は「ローカルにあるもの」を「リモートに sftp でコピーしたもの」を「docker mount したもの」です(難しい)。
この状態で F5 を押すとデバッグが開始されます。ブレイクポイントなども正常に動いているようですね。やったぜ。
このサンプルでは eslint しか extension を入れていませんが、 .devcontainer/devcontainer.json
に書き加えて、 Dockerfile
もそのエクステンションが動くように変更していけば他の extension も動くはずです。
また、 php など他の実行環境も同様の作業で完全リモートランタイムで動作させることが出来るようになるでしょう。凄い。これでローカルには vscode さえインストールしてしまえば OK! という世界になります。
Docker for Windows や Docker for Mac, Linux などであれば sftp などを使わなくても良いのでもっと簡単にこの環境が実現可能です。皆さんも是非やってみてください。