CygwinへのDocker Machine導入

By | 2016年3月29日

こんにちは。船田です。
すこし前から社内でWorkSpacesを本格的に導入しはじめており、仕事で使えるように環境構築をしています。
今回は、CygwinでDocker Machineを導入する手順を紹介します。

作業の流れ

CygwinにDocker Machineを導入し、Docker EngineはEC2上にセットアップします。
基本的には公式サイト(https://docs.docker.com/machine/install-machine/)あたりの手順どおりですが、Cygwinで引っかかるところなどを追加しています。

また、CygwinでIAMユーザにひもづいたcredentialが設定済みである必要があります。手順はCygwinへのaws-cli導入に記載しています。

Docker Machineのインストール

Docker Machineのインストールはとても簡単です。直接Githubからexeを落としてパスの通ったディレクトリに配置するだけです。

$ if [[ ! -d "$HOME/bin" ]]; then mkdir -p "$HOME/bin"; fi && \
curl -L https://github.com/docker/machine/releases/download/v0.6.0/docker-machine-Windows-x86_64.exe > "$HOME/bin/docker-machine.exe" && \
chmod +x "$HOME/bin/docker-machine.exe"

公式では$HOME/binに配置していましたが、Cygwinのデフォルトだとパスも通っていないようでしたし、/usr/local/binなどでもOKです。
 
また、docker-machine用のサブコマンドをタブ補完してくれるスクリプトをインストールしますが、Cygwinでは事前にbash-completionパッケージを導入しておく必要があります。

$ apt-cyg install bash-completion

apt-cygでインストールします。

 
続いて補完スクリプトをインストールします。補完スクリプトは
https://github.com/docker/machine/tree/master/contrib/completion/bash
にあります。スクリプトは3つあり、それぞれ以下の様な機能を持っています。

スクリプト名 用途
docker-machine.bash docker-machineのサブコマンドの補完ができるようになります
docker-machine-prompt.bash activeなDocker Machineがプロンプトに表示されるようになります
docker-machine-wrapper.bash 複数のDocker Machineを使っている場合、docker-machine use で利用可能なDocker Machineを表示し、変更することができます

これらを/etc/bash_completion.d/に入れて、minttyを再起動すればすぐに利用可能になります。

$ docker-machine <TAB>
active            env               ip                regenerate-certs  scp               status            url
config            help              kill              restart           ssh               stop              use
create            inspect           ls                rm                start             upgrade           version

docker-machineコマンドに続けてタブキーでサブコマンドの候補が表示されています。
 
 

EC2をDocker Engineとしてセットアップ

Docker Machineはドライバを変更することで、AWSやDitigal Ocean、ローカルで動くVirtualboxなど様々なプラットフォーム上で動くDocker Engineと連携できます。
今回はEC2上のDocker Engineと連携します。
 
docker-machineコマンドからのEC2上へのDocker Engineのセットアップは

$ docker-machine create --driver amazonec2 【オプション】

のようにします。
 
細かいオプションは
https://docs.docker.com/machine/drivers/aws/)
にあるとおりです。今回は以下のように実行しました。

$ docker-machine create --driver amazonec2 \ 
                        --amazonec2-region xxxxxxxx \
                        --amazonec2-vpc-id vpc-xxxxxxxx \
                        --amazonec2-subnet-id subnet-xxxxxxxx \
                        --amazonec2-security-group xxxxxxxxxxxx \
                        --amazonec2-tags xxxxxxxxxxx \
                        --amazonec2-instance-type t2.small \
                        --amazonec2-root-size 20 \
                        --amazonec2-iam-instance-profile xxxxxxxxxx \
                        【Docker Machine名】
Running pre-create checks...
Creating machine...
(【Docker Machine名】) Launching instance...
(【Docker Machine名】) Tags are not key value in pairs. 1 elements found
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: D:\cygwin64\home\xxxxxxxx\bin\docker-machine.exe env 【Docker Machine名】

しばらくするとEC2インスタンスが起動してDocker Engineがセットアップされます。
 
 

dockerコマンドのインストール

Docker Machineはセットアップできましたが、このままではCygwinにDockerコンテナの作成や削除をするためのdockerコマンドが入っていないので何もできません。
 
そのため、
http://docs.docker.jp/engine/installation/binaries.html
からdockerコマンドのexeを拾ってきます。

$ curl -L https://get.docker.com/builds/Windows/x86_64/docker-latest.exe > "$HOME/bin/docker.exe" && \
chmod +x "$HOME/bin/docker.exe"

これでdockerコマンドも実行できるようになります。

環境変数の設定

dockerコマンドからDocker Machine経由でDocker Engineを使用するためには、いくつかの環境変数を適用する必要があります。

$ docker-machine env 【Docker Machine名】

を実行すると、

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://XX.XX.XX.XX:2376"
export DOCKER_CERT_PATH="D:\Users\USERNAME\.docker\machine\machines\Docker Machine名"
export DOCKER_MACHINE_NAME="Docker Machine名"
# Run this command to configure your shell:
# eval $("D:\cygwin64\home\USERNAME\bin\docker-machine.exe" env Docker Machine名)

のように表示されます。適用する必要がある環境変数と、適用するならコマンドの実行結果をevalすればいいよ、とのことが示されています。

ただ、dockerコマンドを実行するたびにevalを実行するのは面倒です。ひとつしかDocker Machineを使わないのであれば、

eval $(docker-machine env Docker Machine名)

と.bashrcに書いてしまえば、今後は環境変数の設定を意識することなくdockerコマンドが実行できます。

これで普通のWindowsならdockerが使えるようになると思います。しかしCygwinでdockerコマンドを実行すると、

$ docker run -it --hostname test-machine centos:6 /bin/bash
cannot enable tty mode on non tty input

のように表示されてしまいます。Cygwinではttyの扱いが特殊のようで、dockerコマンドがうまく実行できません。

winptyの導入

解決のためには、winpty(https://github.com/rprichard/winpty)を入れる必要があります。

$ apt-cyg install gcc-g++
$ apt-cyg install mingw64-x86_64-gcc-g++
$ git clone https://github.com/rprichard/winpty.git
$ cd ./winpty
$ ./configure
$ make
$ make install

$ vim ~/.bashrc
###
alias docker='/usr/local/bin/console.exe docker'
###上記を追記

$ source ~/.bashrc

で完了です。あらためてdockerコマンドを実行すると

$ docker run -it --hostname test-machine centos:6 /bin/bash
[root@test-machine /]#

のように、正常に動作するようになったことがわかります。

しかしまだ問題があり、

$ docker rm $(docker ps -aq)
output is not a tty
Container name cannot be empty

のように、dockerコマンドの出力結果をそのまま別のサブコマンドに渡すことができません。。
この問題については、

$ docker rm $(\docker ps -aq)
1q2w3e4r5t6y
azsxdcfvgbhn
...

のようにdockerコマンドの先頭に「\」をつけて一時的にaliasを無効にすることで回避できます。
 
 

まとめ

ちょっとした検証や開発用途でDockerを利用する場合は、Docker Toolboxを使用してローカルのVirtualboxを使用するパターンがお手軽ですが、WorkSpacesのような仮想環境上にはVirtualBoxを導入できません。
この場合は、EC2上でDocker Engineを動かすことでDockerが利用可能になります。
また、EC2をDocker Engineとした場合、AmazonLinuxのコンテナも動かせるので、AmazonLinux用のchefレシピをテストするときなど、いちいち新規のEC2インスタンスを起動する必要がなく便利に使えるようになります。