以前の記事で仮想環境上のWindows10 HomeにDocker Desktop for Windows WSL2 Backendを導入しましたが、そのDockerをホスト側のWindows10 で使えないか試してみました。
簡単なまとめ
- 素直な構成にするのが一番です。
- 今回のケースの場合は仮想環境上でWSL2とDocker Desktop for Windows WSL2 Backendを使いましょう。(後述のホスト側のバインドも正常に動作します)
- 公式が提供するツールを使いましょう。(Docker Desktop for WindowsやDocker Toolboxなど)
- Visual Studio Code(VS Code)のRemote Containers 機能拡張が使えるようになります。
- 今回試した手順では、 ホスト側のディレクトリをDockerで正常にバインドできません でした。
検証環境
ホスト側
- Windows10 Pro バージョン1909 64bit
- PowerShell上でOpenSSHクライアントが利用可能
ゲスト側
- 仮想化ソフトウェア:VMware Workstation Player 15.5.1
- Windows10 Home バージョン1909 64bit(Insider Previewを使用)
- PowerShell上でOpenSSHクライアントが利用可能
- WSL2が有効
- Docker Desktop for Windows Edge 2.2.3.0
- WSL2 Backend機能が有効
- デフォルトのWSL2ディストリビューション:Ubuntu 無印版 (18.04.4)
導入の流れ
ホスト側の対応
ホスト側でdockerおよびdocker-composeコマンドを利用できるようにするため、Windows版のdocker-cliとdocker-composeをインストールします。
Windows用のパッケージ管理ツール「Chocolatey」を使うと、単体で導入できます。
※Chocolateyの導入方法については、以下の参考サイト様をご参照ください。
# インストール時には管理者権限でコマンドプロンプトを起動する必要があります。
# またはChocolatey GUIでの導入も可能です。
C:\WINDOWS\system32>choco search docker
...省略...
docker-cli 19.03.3 [Approved]
docker-compose 1.25.4 [Approved]
...省略...
C:\WINDOWS\system32>choco install docker-cli docker-compose
ゲスト側のWindows10 Homeの対応
次に、ゲスト側のWindows10 HomeにてOpenSSHサーバーを導入および起動し、ファイアウォール設定を行ってSSHを送受信可能にします。
コマンドで実行する場合は、Microsoft公式の手順を実行します。
※以下に記載の手順は、参考サイト様の内容をほぼ引用しています。
# 管理者権限でPowerShellを起動します。
# OpenSSHサーバーはデフォルトではオプション扱いで無効になっているため、有効化します。
# はじめに、OpenSSH関連の機能の状態を確認します。
PS C:\WINDOWS\system32>Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
Name : OpenSSH.Client~~~~0.0.1.0
State : Installed
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
# OpenSSHサーバーをインストールします。
# インストール時に "OpenSSH-Server-TCP" という名前のファイアウォール規則が作成され、有効になります。
# これにより、ポート22でのSSH受信トラフィックが許可されます。
PS C:\WINDOWS\system32>Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
# OpenSSHサーバーを起動します。
PS C:\WINDOWS\system32>Start-Service sshd
# 以下の設定を行うと、Windowsの起動時にOpenSSH serverが自動起動するようになります。
PS C:\WINDOWS\system32>Set-Service -Name sshd -StartupType 'Automatic'
# ファイアウォールの規則が存在するかチェックします。
PS C:\WINDOWS\system32>Get-NetFirewallRule -Name *ssh*
# "OpenSSH-Server-In-TCP"という名前のファイアウォール規則が存在し、起動していれば
# (※Enabledの項目がTrueになっていれば)この後の作業は不要です。
# ファイアウォール規則が存在しない場合は作成します。
PS C:\WINDOWS\system32>New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
WSL2を起動します。ここではデフォルトのディストリビューションで設定しているUbuntuを起動します。
2020/04/10時点のWSL2ではサービスの自動開始ができないようなので、Ubuntu側のOpenSSHサーバーを手動で開始します。
※systemctlコマンドが使えないため、serviceコマンドで起動します。
$ sudo service ssh start
* Starting OpenBSD Secure Shell server sshd [ OK ]
ゲスト側のWSL2上のDocker Engineをホスト側に引き込む
ここまでで、ゲスト側のWSL2上のDocker Engineをホスト側に引き込む準備ができました。
SSHの多段接続とUnixソケットのローカルポートフォワード設定をホスト側で行います。
ホスト側のOpenSSHクライアント用の設定ファイルを作成します。
ここでは自宅内環境のため割り切って公開鍵認証を行わず、ゲスト側のWindows10 HomeおよびWSL2にパスワード認証にて接続するようにしています。
# %UserProfile%\.ssh\config を編集します。
# ゲスト側のWindows10 Homeへの接続情報です。
# HostNameでIPアドレスを指定する場合は、Windows10 HomeのIPアドレスを指定します。
# userはWindows10 Homeのユーザーを指定します。
Host vm-win10home
HostName XXX.XXX.XXX.XXX
User bar
# ゲスト側のWSL2の設定です。
# Windows10 HomeからWSL2へTCP/IPでアクセスする際、ビルド18945以降は
# アドレスにlocalhostで指定できるようになったので、HostNameではlocalhostを指定しています。
# userはWSL2のユーザーを指定します。
# 特定のUnixソケット(Docker Engineの本体)をポート23750にローカルポートフォワードします。
# ProxyCommandのsshは、Windows10 Home側のssh.exeを絶対パスで指定します。
Host wsl2
HostName localhost
User baz
LocalForward localhost:23750 /var/run/docker.sock
ProxyCommand C:\Windows\System32\OpenSSH\ssh.exe -W %h:%p vm-win10home
ホスト側のPowerShellにて、OpenSSHクライアントを使ってSSHの多段接続を行います。
# WSL2への接続を行います。
# -Nオプションで、リモートでコマンドを実行しないようにします。
# Windows10 Home側、WSL2側でパスワード認証が発生します。
PS C:\Users\foo>ssh -N wsl2
bar@XXX.XXX.XXX.XXX's password:
baz@localhost's password:
動作確認
ホスト側のコマンドプロンプトまたはPowerShellにて以下のDockerコマンドを実行し、ゲスト側のDocker Engineが認識できているか確認します。
# コマンド実行時には、管理者権限は不要です。
PS C:\Users\foo>docker -H localhost:23750 version
実行結果の例
Client:
Version: 19.03.3
API version: 1.40
Go version: go1.12.10
Git commit: 2355349d-
Built: 10/14/2019 16:41:26
OS/Arch: windows/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 19.03.8
API version: 1.40 (minimum version 1.12)
Go version: go1.12.17
Git commit: afacb8b
Built: Wed Mar 11 01:29:16 2020
OS/Arch: linux/amd64
Experimental: true
containerd:
Version: v1.2.13
GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429
runc:
Version: 1.0.0-rc10
GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd
docker-init:
Version: 0.18.0
GitCommit: fec3683
補足:docker context について
以下の設定を行っておくと、ホスト側でのdockerコマンドの入力時に-H オプションの指定が不要になり、少し手間が省けます。
# docker コンテキストの一覧を表示します。
PS C:\Users\foo>docker context ls
NAME DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default * Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm
# docker コンテキストを新規に作成します。「my-context」部分は自由に名前をつけることができます。
PS C:\Users\foo>docker context create my-context --docker host=tcp://localhost:23750
my-context
Successfully created context "my-context"
# 作成したdocker コンテキストをメインで使用するようにします。
PS C:\Users\foo>docker context use my-context
# docker コンテキストの一覧を再度表示した場合、作成したコンテキストに「*」がついているのを確認します。
PS C:\Users\foo>docker context ls
NAME DESCRIPTION DOCKER ENDPOINT KUBERNETES ENDPOINT ORCHESTRATOR
default Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm
my-context * tcp://localhost:23750
VS CodeのRemote Containers 機能拡張について
最後に、VS CodeのRemote Containers 機能拡張が動作するように設定します。
ホスト側のVS Codeの機能拡張サイドバーより「Remote」で検索して「Remote Development」機能拡張をインストールします。
※「Remote Containers」機能拡張のみを個別にインストールしてもOKです。
併せて「Docker」機能拡張もインストールします。
Docker機能拡張をインストールすると、設定画面にてdockerのホスト指定が行えるようになります。
設定画面を開き、以下の設定を行います。
以下の設定はVS Codeの再起動は不要で、即座に反映されます。
- 検索欄に「docker.host」と入力します。
- 「Docker: Host」の設定欄にSSHでローカルポートフォワーディングしているDockerを指定します。
- ここでは「tcp://localhost:23750」と入力します。
VS Codeのアクティビティバーより「リモート エクスプローラー」(※Remote Development機能拡張インストール後に選択可能)または「Docker」(※Docker機能拡張インストール後に選択可能)をクリックします。
サイドバーにてWSL2上のdockerコンテナやイメージなどが見えること、およびコンテナの起動や起動中のコンテナへVS Codeから接続できることを確認します。
ハマった点など
- Dockerfileまたはdocker-compose.ymlにてホスト側のディレクトリをコンテナにバインドしようとすると、エラーになったり正常にバインドできなかったりとうまくいきません。
今回の構成ではホスト側はゲスト側のDocker Desktop for Windowsの対象範囲外のため、どうしようもないと思われます。 - 多段SSHを行う際に、「WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!」という警告が出て接続できなくなるときがあります。これは仮想環境やWSL2のVMのIPアドレスが変更になったり、構成に変化があると発生するようです。
今回は自宅内開発のため、警告が出た場合はknown_hostsから対象の環境の定義を削除することで対応します。
その後、再度多段SSHを行うとうまくいきます。
# PowerShellにて実行します。
PS C:\Users\foo> ssh-keygen -R XXX.XXX.XXX.XXX
PS C:\Users\foo> ssh-keygen -R localhost
最後に
Dockerの公式ツールを使えば、上記の手順は全く不要です。ハマリポイントも解消されます。
参考サイト様
- Chocolateyを使った環境構築の時のメモ
- Windows Server 2019 および Windows 10 用 OpenSSH のインストール
- Windows 10にオンデマンド機能のOpenSSHサーバをインストールする方法
- Windows Subsystem for Linux のリリース ノート - ビルド 18945
- Linuxがほぼそのまま動くようになった「WSL2」のネットワーク機能
- sshのUNIXドメインソケット転送を利用してリモートのDockerホストに接続する
- Windwos10でssh ProxyCommandの多段SSHの設定
- ssh接続先のdockerコンテナにVSCodeのRemote Developmentで繋ぐ
- docker context
- Using an SSH tunnel to connect to a remote Docker host
- SSH接続で WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! って言われて接続を拒否られるとき
- SSH接続エラー回避方法:.ssh/known_hostsから特定のホストを削除する/削除しないで対処する3つの方法