docker-machineのgenericプロバイダを使う


#docker-machine
docker-machineはdockerホストの管理ツールです。
rbenvやndenvのdocker版みたいな感じです。
dockerコマンドは環境変数を適切に設定すればコンテナの操作をローカルから実施できるようになるのですが、そういうことも管理してくれるのでリモートに対するdocker操作が捗るようになります。


#dockerホスト
既存のdockerホストをdocker-machineの管理下に入れます。
これによりローカルのdockerコマンドの向き先をdocker-machineに管理させることができ、今までdockerホストに直接sshしてdockerる事がなくなります。

#docker-machine create
docker-machineの管理下に置かれるdockerホストを作成するには`docker-machine create`を実行します。しかし、このコマンドはあくまでもホスト自体を作成するコマンドであって、その内容は設定先のサーバーにdockerをインストールしてゴニョゴニョするといったものです。既にdockerがインストールされてるホストに対してはあまり好ましくありません。
それに`/etc/os-release`ファイルがない場合、スクリプトがコケるという問題があったりもします。

そんなとき、プロバイダにgenericを指定するとゴニョゴニョせずに設定だけを管理下に置けるようになります。

#dockerをtlsで動かす
下準備としてまずはリモートのdockerのtls接続を有効にしなくてはいけません。
そのためにCAを作ってサーバー証明書（ついでにクライアント証明書）を作成します。
まずは適当なディレクトリ（`/etc/docker/tls`など）で以下のスクリプトを実行します。途中鍵のパスフレーズを聞かれるので何か入力します。

```sh:CA作る.sh
export HOST=your.domain
export IP=1.2.3.4

# CAの鍵と証明書作成
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem

# サーバー鍵と証明書要求書
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr

# サーバー証明書に署名
echo "subjectAltName = IP:10.10.10.20,IP:127.0.0.1,DNS:${HOST},IP:${IP}" > server.cnf
openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
 -CAcreateserial -out server.pem -extfile server.cnf

# クライアント証明書と署名要求書
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr

# クライアント証明書に署名
echo extendedKeyUsage = clientAuth > client.cnf
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
 -CAcreateserial -out cert.pem -extfile client.cnf
```

#docker の起動オプション
起動オプションを変更してtlsモードを有効化します。
オプションの変更はRedHat系なら`/etc/sysconfig/docker`、Debian系なら`/etc/default/docker`に設定します。
どっちもない場合は、`/etc/init.d/docker`から辿ってください。

DOCKER_OPTSを設定してる部分があるので、そこで先に作成した証明書関連を指定するようにします。

```sh:docker
前略

# Use DOCKER_OPTS to modify the daemon startup options.
#DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4"
TLS_DIR=/etc/docker/tls
DOCKER_OPTS="--tlsverify --tlscacert=${TLS_DIR}/ca.pem --tlscert=${TLS_DIR}/server.pem --tlskey=${TLS_DIR}/server-key.pem -H=0.0.0.0:2376"

後略
```

設定が終わったら`service docker restart`でデーモンを起動させてください。無事デーモンが起動したらホストでの作業は終わりです。

#docker-machineのインストール
クライアントに戻って、docker-machineの設定をします。
docker-machineは[dockertoolbox](https://www.docker.com/docker-toolbox)ってのに入っています。各環境用のインストーラーがあるのでインスコしてください。
macなら`brew cask install dokcertoolbox`でインスコできます。

#docker-machine createする
インストールが終わったら先ほど設定したdockerホストをdocker-machine管理下に入れます。
まずは
`docker-machine create -url tcp://xxx.xxx.xxx.xxx:2376 hoge`
とコマンドを実行します。
urlオプションにはホストのIPとポートを設定します。hogeは任意の名前を指定して下さい。
コマンドが成功すると`docker-machine ls`で確認できます。

```sh:docker-machine_ls
% docker-machine ls
NAME      ACTIVE   DRIVER       STATE   URL                         SWARM
hoge      *        none                 tcp://xxx.xxx.xxx.xxx:2376
```

これでdocker-machineの管理下には置けました。
次にdockerコマンドの向き先を変更するための環境変数を出力します。
`docker-machiee env hoge`
exportすべき変数が出力されるはずですが、pemが無いと怒られます。

# pem達を設定
サーバーサイドで作成した証明書一式をクライアントに設定します。
場所は`~/.docker/machine/machines/hoge/`です。config.jsonという設定ファイルがあるはずです。
ここにサーバーで作成したpem達一式をDLしておきます。設定が終わると再度`docker-machine env hoge`を実行してみます。

```sh:
% docker-machien env hoge
Error getting SSH command: exit status 255
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://XXX.XXX.XXX.XXX:2376"
export DOCKER_CERT_PATH="/Users/foo/.docker/machine/machines/hoge"
export DOCKER_MACHINE_NAME="hoge"
# Run this command to configure your shell:
# eval "$(docker-machine env hoge)"
```

こんな感じで出力されるはずです。そしたらば最後に出力されているようにこれをevalで評価させます。
`eval "$(docker-machine env hoge 2> /dev/null)"`
ssh設定ができてないと１行目にSTDERRが出力されるので/dev/nullに捨てます。
これでdockerコマンドの向き先がホストに変更されましたので、ローカルから思う存分dockerる事ができます。

# dockerのバージョン
dockerはサーバーとクライアントでバージョンが合って無いと動かないようなので、ホストとクライアントでバージョンを揃える必要があります。