目的
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
手順
- nsenterでPID 1の名前空間に入るコンテナのDockerfileを作成する
- DockerfileをBuildする
- ビルドしたイメージを特権付きでHostのプロセス名前空間で起動する
1.nsenterでPID 1に入るコンテナのDockerfileを作成する
任意の場所に以下のDockerfileを作成します。
util-linuxをインストールし、ENTRYPOINTでnsenterを使って、PID 1(コンテナ自身のinitプロセス)の名前空間に入ります。
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をビルドします。
PS C:\Users\xxx>docker build . -t hostenter
3.ビルドしたイメージを特権付きでHostのプロセス名前空間で起動する
インタラクティブモードでdocker run
してシェルを起動します。
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上の全てのデバイスにアクセスできるため、上記の方法でコンテナからホストの名前空間のプロセスとしてシェルを実行しています。