起動中のDockerコンテナにnsenterで接続する

起動中のDockerコンテナに接続する方法として、よくsshdを立ち上げておく方法が紹介されていますが、本来の目的と異なるプロセスを立ち上げるのは好ましくありませんし、準備も面倒です。 (参考: If you run SSHD in your Docker containers, you’re doing it wrong!)

util-linuxに含まれているnsenterを使うことで、起動中のDockerコンテナに簡単に接続することができます。

しかも、jpetazzo/nsenterのDockerイメージを使うことでインストールも簡単にできます。

nsenterのインストール

jpetazzo/nsenterイメージを用いて、次のように-vオプションを付けてコンテナを起動します。

$ docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter

このコンテナは/usr/local/binnsenterdocker-enterの2つのコマンドをインストールして終了します。

たったこれだけでインストールは完了です。

nsenterとdocker-enterコマンドの使い方

nsenterコマンド

nsenterコマンドを使ってコンテナに接続するには、次のようにたくさんのオプションを付ける必要があります。 ここではsample_containerという名前のコンテナに接続するものとします。

$ sudo nsenter --target $(docker inspect --format '{{.State.Pid}}' sample_container) --mount --uts --ipc --net --pid

実行にはsudoが必要です。一般ユーザー権限で実行すると、次のように権限のエラーとなります。

nsenter: cannot open /proc/7195/ns/ipc: Permission denied

また、実行するコマンドを渡すことができます。

$ sudo nsenter --target $(docker inspect --format '{{.State.Pid}}' sample_container) --mount --uts --ipc --net --pid -- ls -l

しかし、こんな大量の引数はとても覚えられません。

docker-enterコマンド

jpetazzo/nsenterイメージにはnsenterのラッパーである、docker-enterコマンドが追加されています。

これを使えばコンテナ名を指定するだけで接続することができます。

$ sudo docker-enter sample_container

もちろんコマンドも渡せます。こちらの方が断然いいですね。

$ sudo docker-enter sample_container ls -l

boot2docker環境へのインストール

boot2docker環境にもインストールすることができます。

$ docker run --rm -v /var/lib/boot2docker:/target jpetazzo/nsenter

そして、次の関数をOS X側のシェルに設定しておきます。

docker-enter() {
    boot2docker ssh '[ -f /var/lib/boot2docker/nsenter ] || docker run --rm -v /var/lib/boot2docker/:/target jpetazzo/nsenter'
    boot2docker ssh -t sudo /var/lib/boot2docker/docker-enter "$@"
}

READMEには書かれていないのですが、boot2docker sshに、-tオプションを付けて擬似端末を割り当てないとsudoが実行できずに固まってしまいます。

しかし、どうやらこれはboot2dockerを再起動すると直るようです。

ダメなときは次のメッセージが表示されたあとに固まります。

stdin: is not a tty

備考

Ubuntu Server 14.04 LTSと、OS X 10.9.4でインストールできることを確認しました。