Docker for WindowsのMobyLinuxVMに接続する方法


目的

Docker for Windows(Linux)でDocker HostのMobyLinuxVMの中に入って設定を確認したり一時的に変更したい場合、Hyper-Vマネージャーの仮想マシン接続を試みても、接続することはできません。

そこで、接続する方法を調べてみました。

手順としては、
DOCKER COMMUNITY FORUMS: How can I SSH into the Beta’s MobyLinuxVM
のコメントに書いてある方法ほぼそのままですが、Dockerの仕組みの勉強になったので、個人的なメモを兼ねて残しておきます。

注意

  • これが必要になるケースはかなり限られると思います。
  • 半分興味本位で調べた程度なので、誤りや補足等あればご指摘お願いします。

前提

  • OS: Windows 10 Pro Fall Creators Update
  • Docker for Windows: Version 17.09.0-ce-win33 (13620) stable

手順

  1. nsenterでPID 1の名前空間に入るコンテナのDockerfileを作成する
  2. DockerfileをBuildする
  3. ビルドしたイメージを特権付きでHostのプロセス名前空間で起動する

1.nsenterでPID 1に入るコンテナのDockerfileを作成する

任意の場所に以下のDockerfileを作成します。
util-linuxをインストールし、ENTRYPOINTでnsenterを使って、PID 1(コンテナ自身のinitプロセス)の名前空間に入ります。

Dockerfile
FROM alpine
MAINTAINER You <you@example.com>
RUN apk update && \
    apk add util-linux && \
    rm -rf /var/cache/apk/*
ENTRYPOINT ["nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid"]

2.DockerfileをBuildする

上記Dockerfileをビルドします。

PowerShell
PS C:\Users\xxx>docker build . -t hostenter

3.ビルドしたイメージを特権付きでHostのプロセス名前空間で起動する

インタラクティブモードでdocker runしてシェルを起動します。

PowerShell
PS C:\Users\xxx>docker run -it --privileged --pid=host hostenter /bin/sh
/ #

--privilegedオプションを付けて特権コンテナとして起動することで、Host上のデパイスにアクセス出来るようにしています。
--pid=hostでホストの名前空間で起動しています。

仕組み

Docker Host上でコンテナが起動されると、各コンテナはHostのdockerdからforkしたプロセスとして実行されます。
その際、それぞれのコンテナに異なる名前空間が割り当てられ、PID 1(initプロセス)を起点としてコンテナ上のプロセスが実行されます。
参考:RED HAT OREN EYE ONLINE: Dockerによるコンテナ化アプリケーションの運用設計ガイド(パート1)

nsenterは、任意の名前空間に入るツールで、通常はHost上にインストールして各コンテナにアタッチするために利用されます。(docker execコマンドが無かった時代に必須だったらしい)
参考:Qiita: nsenter・docker-enterでコンテナに入る方法

また、各コンテナプロセスの名前空間はdocker run--pidオプションで変更することができ、Hostの名前空間で実行する事もできます。
--priviligedオプションを付ければ、コンテナはHost上の全てのデバイスにアクセスできるため、上記の方法でコンテナからホストの名前空間のプロセスとしてシェルを実行しています。