WSLから名前付きパイプ経由でDocker for Windowsに接続する方法


概要

MSの公式ブログWindows Command Line Tools For Developersで紹介されている。
[Cross Post] WSL Interoperability with Docker – Windows Command Line Tools For Developers

この方法を使えば、Docker for Windowsでtcpのポート2375を晒さなくても利用できる。

WSLから直接接続するのではなく、Windowsの名前付きパイプ(Named pipe)に通信するNpiperelay.exeとWSLのソケット通信ツールのsocatを使って、Docker CLIからのUnix socketへの接続を変換する仕組み。


(上記ブログより)

ざっくり手順

  1. go, socat, Docker CEをインストール
  2. goでNpiperelay.exeをビルドし、Windowsディレクトリに配置(WSL側にシンボリックリンクを作成)
  3. socatでDockerのソケット通信をキャプチャしてNpiperelay.exeへ渡すためのスクリプトを作成
  4. 3.のスクリプトをバックグラウンドプロセスとして実行してDockerを利用する
$ #
$ # 1. go, socat, Docker CEをインストール
$ #
$ sudo apt update
$ wget -O - https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz | sudo tar -C /usr/local -xzf -
$ export PATH=$PATH:/usr/local/go/bin
$ sudo apt install socat docker.io -y
$ sudo adduser ${USER} docker
$ #
$ # 2. goでNpiperelay.exeをビルドし、Windowsディレクトリに配置(WSL側にシンボリックリンクを作成)
$ #
$ go get -d github.com/jstarks/npiperelay 
$ # パスは任意。ここではc:\hoge\ にnpiperelay.exeを作成
$ GOOS=windows go build -o /mnt/c/hoge/npiperelay.exe github.com/jstarks/npiperelay
$ sudo ln -s /mnt/c/hoge/npiperelay.exe /usr/local/bin/npiperelay.exe
$ #
$ # 3. socatでDockerのソケット通信をキャプチャしてNpiperelay.exeへ渡すためのスクリプトを作成
$ #
$ cat << EOS > ~/docker-relay
#!/bin/sh
exec socat UNIX-LISTEN:/var/run/docker.sock,fork,group=docker,umask=007 EXEC:"npiperelay.exe -ep -s //./pipe/docker_engine",nofork
EOS
$ chmod +x ~/docker-relay

ここで一度WSLを開き直して

$ #
$ # 4. 3.のスクリプトをバックグラウンドプロセスとして実行してDockerを利用する
$ #
$ sudo ~/docker-relay &
$ docker info

でホストが見えてればOK。

問題点

  • クリーンな環境で何度か試したが、上記手順どおりやって全然動かない時が多々ある。
  • 一度コマンドが通ったら比較的安定する。
  • socatとNpiperelay.exeの間で何か起きてそう。
  • 再現性が突き止められてないが、WSLを開き直したり何度か試してるうちに使えるようになったり…。
  • docker.ioだとCLIのバージョンが古いが、ブログでは1709ではバグってるぽいと言及。
  • docker-ceの17.09.1を入れて試したが、一応動いてはいる。
  • docker.ioをapt remove docker.ioで削除しようとするとエラーになる罠がある。

追記(2017-12-20)

Unix SocketがWSLでサポートされるみたいなので、WSL側でDockerデーモンを動かせるようになる日が来るかも?

AF_UNIX comes to Windows – Windows Command Line Tools For Developers