そんな今日この頃の技術ネタ

本家側に書くほどでもない小ネタ用

Docker Machine/Swarm/Compose とりあえず触ってみたメモ

Dockerを使ってみたい案件があり、デプロイ方法について色々検討している今日この頃。

新しいツールということもあって、 軽くググってみただけでもKubernetesとかMesosとかあるいはもっと別な方法が色々と出てくるし、 逆にいえば「これが決定版!」とはまだどれも言えそうにはない雰囲気。

サードパーティ製のツールはどれもそれなりに利点はありそうだけど、 一方で学習コストが高くついて辛い感じもあり、 また個人的にはDocker Compose使って作業してたんでそれを流用できないというのも気が進まないポイントであった。

実際のとこそこまで機能はいらないし、いっそConsulのイベント機能で無理やり…とか考えたりもした。


そんな感じで正直なところ迷走していたのだが、 公式ツールであるところのSwarmが去年末の段階で1.0.0をリリースしていたらしいということに今更になって気づく。

(なんでか見逃してましたね。)

公式ツールという安心感もあるし、何より使い慣れたComposeも使える!

というわけでひとまず使い方を勉強してみた。


導入

Docker Engine

いわばDocker動かす本体。

Machineと連携させるには素で入る方じゃなくてEngineがついた方を入れる必要があるらしい。

ということで、公式ドキュメントに従ってインストールを進める。

Docker Engine> Install

長くなるので省略するが、OSごとの子細なやり方が書いてあるので迷うことはないだろう。

yumなりaptなりで簡単に入れられる。

Docker Compose

ymlファイルからコンテナを起動するためのツール。毎回長ったらしいコマンドを記述しないで済む。

Docker Compose> Install

以前本家の方で書いた記事があったのでそっちでも。

blue1st.hateblo.jp

Docker Machine

他のホストにDockerの動作環境を用意し、あたかもローカル環境であるかのようにコントロールできるツール。

Docker Machine> Install

Docker Swarm

クラスタを制御するためのもの。Machineの方を入れれば使える。


VMで動かしてみる

大雑把な流れとしては

  1. クラスタ操作のためのトークンを作成
  2. Machineへ操作のためのマスタを追加
  3. Machineへ実際にデプロイするノードを追加
  4. マスタをコントロールできるように環境変数を設定
  5. 各種Docker操作

といった感じな模様。

ひとまずVirtualBoxを使ったサンプルをこなしてみる。

1. クラスタ操作のためのトークンを作成

操作端末(じゃなくても良いけど)でswarmイメージを使ってトークンを生成する。

docker run --rm swarm create

以降の操作で用いるのでコピペ保管しておくこと。

どうやらトークンではなくてConsulを使って連携させることもできるみたいだけど、 今回は時間なかったので今度試す。

blue1st.hateblo.jp

なんかConsul依存度が高まってくなぁ。


追記: consulのKVを使う場合

この手順を飛ばし、以降の操作におけるtoken://<TOKEN>の部分をconsul://<consulのURL>/<必要ならキーを入力>という感じで使える。

2. Machineへ操作のためのマスタを追加

ドライバとしてvirtualbox、オプションとしてswarmswarm-master、そしてトークンを指定してVMを作成する。

docker-machine create -d virtualbox --swarm --swarm-master --swarm-discovery token://<TOKEN> master

ちなみにVMじゃなくて実機を使う場合は、ドライバとしてgenericを指定し、 generic-ssh-user generic-ssh-key generic-ip-addressあたりのオプションを記述してやればいける、はず。

これは自宅環境だと試せなかったのでそのうち。

3. Machineへ実際にデプロイするノードを追加

マスタの時のからswarm-masterオプションを抜いた感じ。

docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> node1
docker-machine create -d virtualbox --swarm --swarm-discovery token://<TOKEN> node2

ひとまず2つほど。

4. マスタをコントロールできるように環境変数を設定

docker-machine envコマンドで必要なことは出力してくれるので、evalに食わせればOK。

よく使いそうなので実用上はエリアスに入れとくと良いかも。

eval "$(docker-machine env --shell bash --swarm master)"

これで端末でdockerコマンドを打つと、先ほど作成したmasterのDockerを操作できる。(docker infoとかでクラスタの状況も確認できる。)


ちなみに下記のコマンドで元に戻せる。

eval "$(docker-machine env -u)"

5. 各種Docker操作

色々と細かいことを書いても長くなってしまうので肝心なとこだけ。

とりあえず雑多にdocker-compose.ymlを用意してみる。

nginx:
  image: nginx:latest
  environment:
    - "constraint:node==node*"

nginx:latestnodeと名のついたノードにだけデプロイする、の意味。


とりあえずupしてみる。

docker-compose up -d
node2: Pulling nginx:latest... : downloaded
master: Pulling nginx:latest... : downloaded
node1: Pulling nginx:latest... : downloaded
docker ps
CONTAINER ID        IMAGE       COMMAND          CREATED         STATUS      PORTS           NAMES
8fa0a4a3a719        nginx       "nginx -g 'daemon off"    46 seconds ago      Up 45 seconds     80/tcp, 443/tcp     node1/swarm_nginx_1

クラスタ全体でイメージはダウンロードするようだが、 起動は一個だけ。

次に起動するコンテナを増やしてみる。

docker-compose scale nginx=3
Creating and starting swarm_nginx_2 ... done
Creating and starting swarm_nginx_3 ... done
docker ps
CONTAINER ID        IMAGE        COMMAND          CREATED         STATUS         PORTS             NAMES
f521e8b48602        nginx        "nginx -g 'daemon off"     20 seconds ago      Up 19 seconds     80/tcp, 443/tcp     node1/swarm_nginx_3
109dfb5794fe        nginx        "nginx -g 'daemon off"     20 seconds ago      Up 19 seconds     80/tcp, 443/tcp     node2/swarm_nginx_2
8fa0a4a3a719        nginx        "nginx -g 'daemon off"     3 minutes ago         Up 3 minutes     80/tcp, 443/tcp     node1/swarm_nginx_1

masterを避けて指定個数が散らばって起動されることが確認できる。


ちなみに普通にdocker-compose killでそれぞれ殺せる。

ノード自体が要らなくなった場合はdocker-machine lsで確認してstop&rmで。


実際上はローカルのプライベートリポジトリに登録したイメージを配布する目論見。

最初のイメージのダウンロードがどの程度時間かかるのかが気になるところ。

blue1st.hateblo.jp


明示的にホストのポートを指定して起動するような場合、バッティングすると当然起動時にエラーとなってしまうのだが、 これをいかに避けるかが目下のところ悩みどころ。

せっかくswarmで運用するならば具体的な番号を避けてコンテナ間のlinkを使うべきだというのは分かっちゃいるが、 現状そこまで完全にDockerまかせで運用する覚悟があるわけでもないので…