Goal
- dockerコンテナをssh付きで起動する
- dockerコンテナにsshできるようにする
- まずは開発環境で上記を実現する(この記事の鍵設定のまま公開サーバでセットアップすると超危険です)
はじめに
dockerは1コンテナ1プロセスが基本だが、supervisorなどのプロセスコントロールシステムを使えば複数プロセス起動させることもできる. 以下の記事では、1コンテナ1プロセスの制約は規模の小さいシステムではけっこう厳しいことを指摘している. かわりにロールベースでコンテナ起動させることを提案している.
http://postd.cc/docker-misconceptions/
- 誤解その2:Dockerコンテナごとに1つのプロセスだけを持たせる
- ロールに基づいたDockerイメージを使用する
phusion社はロールベースのコンテナ管理に適したベースイメージを提供している.
ubuntuベースにはなくてphusion/baseimageにあるものは以下リンクに一覧されている.
https://github.com/phusion/baseimage-docker#whats_inside_overview
ssh, cronなどが積まれていて、プロセスコントロールとしてrunitが導入されている.
phusion/baseimageでsshできるまでの手順
- phusion/baseimageを落としてくる
- デフォルトではsshdはインストールされているが、起動されない
- baseimageを元にsshd有効の新規イメージを作成する
- ローカルPCにsshログイン用の秘密鍵を配置する
- sshd有効新規イメージを指定してdocker containerを起動する
- 起動コマンドで先ほど配置した秘密鍵と対になるrootユーザの公開鍵を配置する
- (Windows/Macでdocker起動している場合?)docker machineとdocker containerのポートフォワードを指定する
- 秘密鍵を指定してsshログイン
(1) phusion/baseimageを落としてくる
##
## docker runコマンドでコンテナ起動する
## localにないイメージはdocker hubからdownloadしてきて起動する
##
docker run phusion/baseimage hostname
# Unable to find image 'phusion/baseimage:latest' locally
# latest: Pulling from phusion/baseimage
# Status: Downloaded newer image for phusion/baseimage:latest
# 4028824b96c3
##
## localにもってるimageの一覧を確認
## phusion/baseimageが仲間になった
##
docker images
# phusion/baseimage latest e9f50c1887ea 3 months ago 237.7 MB
(2) baseimageを元にsshd有効の新規イメージを作成する
前述の通り、デフォルトでbaseimageはsshがインストールされているが起動しないようになっている.
有効にするためにオリジナルのDockerfileを作成し、sshd有効バージョンのイメージを作成する.
Dockerfileの参考は以下.
https://github.com/phusion/baseimage-docker#enabling_ssh
##
## 適当なdir作成して直下にDockerfileを配置する
##
mkdir docker-trial
cd docker-trial
vi Dockerfile
FROM phusion/baseimage:latest
RUN rm -f /etc/service/sshd/down
# Regenerate SSH host keys. baseimage-docker does not contain any, so you
# have to do that yourself. You may also comment out this instruction; the
# init system will auto-generate one during boot.
RUN /etc/my_init.d/00_regen_ssh_host_keys.sh
##
## docker buildコマンドで新規イメージ名とビルドするディレクトリパスを指定
## baseimage_sshという名前で、カレントディレクトリをビルドする
## baseimage_sshがdocker image仲間になる
##
docker build -t baseimage_ssh .
# baseimage_ssh latest ba085bb0e0c0 About an hour ago 240.5 MB
docker images
# REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
# baseimage_with_ssh latest ba085bb0e0c0 19 hours ago 240.5 MB
# phusion/baseimage latest e9f50c1887ea 3 months ago 237.7 MB
(3) ローカルPCにsshログイン用の秘密鍵を配置する
https://github.com/phusion/baseimage-docker
にデフォルトの秘密鍵がコミットされているのでそれを探してdownloadしてくる.
2015.11現在は以下手順のcurlで取得できる.
もちろんこのセットを公開サーバで使うと第三者がログインし放題になるので注意.
cd docker-trial
curl -o insecure_key -fSL https://github.com/phusion/baseimage-docker/raw/master/image/services/sshd/keys/insecure_key
chmod 600 insecure_key
(4) sshd有効新規イメージを指定してdocker containerを起動する
先ほどビルドしたイメージbaseimage_sshを起動する.
鍵を有効にして起動
sshdは起動するようになったが、/sbin/my_init --enable-insecure-key
を実行しないと"鍵"が有効にならない.
docker run baseimage_ssh /sbin/my_init --enable-insecure-key
↑のコマンドは処理戻ってこないが、docker run
に-d
を指定するとデーモン起動できる.
/sbin/my_init --enable-insecure-key
を実行すると、root@(docker container)の~/.ssh/authorized_keys
に公開鍵が配置される.
これが前述curlでdownloadしておいた秘密鍵と対になる.
port forwardを有効にして起動
Windows/Macにdockerコンテナを直接起動できないので、docker-machineが各コンテナへのプロキシ用vmとしてホストになる. Windows/Macはあくまでsshクライアントで、docker-machineがサーバとなりその中にdocker containerが起動すると考えるとよさそう(mac/docker-machine/docker containerの関係は一番上の図を参考).
(boot2dockerというコマンドは非推奨らしく、2015.11現在はdocker-machineコマンドを使う. https://docs.docker.com/installation/mac/)
自分の環境ではvirtualbox環境でdocker-machineが起動されている.
docker-machine ls
# default * virtualbox Running tcp://192.168.99.100:2376
dockerコンテナはこのdocker-machine上に起動されるのでsshさせるためにはport forwardが必要.
(要確認:port forwardはdocker-machineが存在するときのみ必要なのか?複数コンテナ起動させることを考えるとlinux上で動かすときもsshさせるためにはport forward必須な気もする.)
docker run -p 2222:22 baseimage_with_ssh /sbin/my_init --enable-insecure-key
docker run
の-p
オプションでcontainer:22をhost:2222にbindする.
(5) 秘密鍵を指定してsshログイン
一番上図に記載したように、Windows/Mac環境ではdocker-machineがdocker containerのホストとなる.
docker containerのip addressはdocker inspect (コンテナID)
で確認できるが、このipはdocker machineからしかアクセスできないためこのipを使ってsshログインすることはできない(要確認:たぶんlinux環境ではできる).
前述の手順でport forward設定つきでコンテナ起動しているので、フォワード元のアドレス:ポートへ向かってsshリクエストする.
##
## 現在起動しているコンテナを一覧する
##
docker ps
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
# fbdf5a494392 baseimage_ssh "/sbin/my_init --enab" 4 hours ago Up 4 hours 0.0.0.0:2222->22/tcp sick_stallman
##
## docker ps結果で確認できるcontainer idを使って、
## baseimage_sshの22番にセットされているport mappingを確認する
##
docker port fbdf5a494392 22
# 2222
##
## 再度docker-machineのアドレスを確認
##
docker-machine ls
# NAME ACTIVE DRIVER STATE URL SWARM
# default * virtualbox Running tcp://192.168.99.100:2376
cd docker-trial
ssh -i insecure_key root@192.168.99.100 -p 2222
-i
に前述の手順でdownloadした秘密鍵のパスを指定する.
Debug
docker run baseimage_ssh --debug
--debug
オプションでデバッグを出力できる. docker run
の結果がいつまで経っても終わらない場合などどこで失敗してるかかなり参考になる.
ssh root@(docker container) -i insecure_key -vvv
sshクライアントで-vvv
付きで実行すると、デバッグ情報を出力できる.
そもそもtcpリクエストがコンテナ:22に到達していないのか、鍵が間違っているのか、などを切り分けることができる.
docker run baseimage_ssh netstat -an | grep "LISTEN "
baseimage_sshを起動して、22番ポートがlistenされているかなどを確認できる.
docker run -t -i baseimage_ssh bash -l
# -i: 標準入力
# -t: 擬似ターミナル
# Ctrl + P + Qでデタッチする(bg起動状態になる)
# exitで終了
# または
docker exec (container id) bash -l
らちがあかないときは、terminalに直接入って調査したほうが速い.
docker-machine ssh default
docker-machine ls
の結果でわかるdocker-machine名(default)を指定するとdocker-machineにログインできる.
docker-machineからdocker containerがどう見えているか確認することで調査の役に立つかも
docker ps
docker inspect (container id)
現在起動しているdocker container一覧.
container idを指定してコンテナの詳細情報を表示する.