一連の流れのある【中編】になります。
ここまできてようやくチュートリアルのPart3が進められるような状況になりました。今回からはOSをChromeOS
からUbuntu 18.02 LTS
に変更して行っていきます。
【参考】
以前のエントリの内容と重複はありますが、チュートリアルを進めていきます。 ここまで飛ばしていいという部分には【ここまで読み飛ばしていいです】という目印をつけておこうと思います。
Get Started, Part 3: Services
ここではService
に関して学ぶことになります。
事前準備
事前準備としてはDockerのインストールは当然のことながらPart1とPart2を行ってきた環境(コンテナ)があることが必要です。
加えてDocker Compose
のインストールが必要になります。Mac用のDockerデスクトップとWindows用のDockerデスクトップにはプレインストールされていますが、Linux系は別途インストールする必要があります。以下のサイトを参考にインストールを行います。
$ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose
また、Part2で作成したfriendlyhelloイメージをレジストリにpushして公開することが必須になります。(ここではその共有イメージを使います。)
以下のようにDockerのイメージを実行し、http://localhost:8080/
という感じでアクセスできることは確認しておいてください
※原文は4000ポートを使用していますがChromeOSではアクセスがNGなので8080に変更してありますので注意です。
【一般形】
$ docker run -p 8080:80 username/repo:tag
【前回の例で以下のように動作していました(ここでいうhoge
は各自のユーザ名に変更してください)】
$ docker run -p 8080:80 hoge/get-started:part2
サービスとは?
このPartではアプリケーションを拡張し負荷分散を行います。そのために分散アプリケーションの階層を1レベル上に上げ、サービスという概念が必要になります。
階層的にはこんな感じ
- Stack
- Services (←いまここ)
- Container (part2(前回)でやった部分)
分散アプリケーションはサービスという概念で構成されていて、例えばビデオ共有サイトでは、データベースサービス、ビデオをトランスコーディングするサービス、フロントエンド用のサービスから構成されているようなイメージになります。
サービスはコンテナから構成されます。その設定でイメージの実行方法、使用するポート、コンテナのレプリカをいくつ実行する必要があるかなどの体系化を行う必要があります。これらの設定を行う場合にはdocker-compose.yml
を記述することでこれらの定義、実行、拡張することが可能になります。
docker-compose.yml
を書いてみる
docker-compose.yml
でコンテナの動作を設定してみます。
以下に記載してymlファイルdocker-compose.yml
として作成します。
このとき、Part2で作成したイメージをレジストリにpushしていることを確認して、自分の作成した
username/repo:tag
をイメージの詳細に置き換えてこの.yml
を更新します。
以下の例ではhoge/get-started:part2
として設定しています。またポートも4000から8080へ変更しています。
【変更前(原文のまま)】
version: "3" services: web: # replace username/repo:tag with your name and image details image: username/repo:tag deploy: replicas: 5 resources: limits: cpus: "0.1" memory: 50M restart_policy: condition: on-failure ports: - "4000:80" networks: - webnet networks: webnet:
【今回の変更後】
version: "3" services: web: # replace username/repo:tag with your name and image details image: hoge/get-started:part2 deploy: replicas: 5 resources: limits: cpus: "0.1" memory: 50M restart_policy: condition: on-failure ports: - "8080:80" networks: - webnet networks: webnet:
このdocker-compose.yml
では次のような動きを記述しています。
- Part2で作成したイメージをリポジトリから取得。
- 取得したイメージから5つのインスタンスを生成して、webと呼ばれるサービスとして名づけます。それぞれに対してCPU資源は10%、50MBのRAMを割当て。
- コンテナでエラーがあった場合には再起動。
- webサービスの各インスタンスの80ポートはローカルホストからは8080ポート経由からアクセス可能。(オリジナルの記述は4000ポート)
- webnetと呼ばれる負荷分散ネットワークを生成し、ポート80を共有するようにwebのコンテナに指示します。 (内部的にはコンテナ自体が一時ポートでwebのポート80に発行)
- webnetネットワークをデフォルト設定(負荷分散オーバーレイネットワーク)で定義。
【ここまで読み飛ばしていいです】
負荷分散ネットワークアプリの起動
まずは以下のコマンドを起動します。コマンドの意味はPart4で説明がありますが、これを実行しないとエラーが発生します。
$ docker swarm init
【ログ】
$ docker swarm init Swarm initialized: current node (nc03uv6m1z1dxgwxdilvh29rj) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-1dukwcs4w07qt835cw6o5w0aju191e93be2jtctejrndzj5jyd-25d5b683d7jx4hceptehbtrz9 192.168.0.7:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
つづいて以下のように実行します。この実行ではアプリはgetstartedlab
と設定しています。
$ docker stack deploy -c docker-compose.yml getstartedlab
【ログ】
$ docker stack deploy -c docker-compose.yml getstartedlab
Creating network getstartedlab_webnet
Creating service getstartedlab_web
これで動作の確認になります。ここからはChromeOSではうまく動作しなかった部分になりますが… 以下のコマンドで確認します。
$ docker service ls
【ログ】
$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS p1dyl3harlzm getstartedlab_web replicated 0/5 hoge/get-started:part2 *:8080->80/tcp
お!あれ?だめなのか?
念の為、コンテナの動作状況を以下のコマンドで確認してみます。
$ docker service ps getstartedlab_web
【ログ】
$ docker service ps getstartedlab_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS lgz0af823dtz getstartedlab_web.1 hoge/get-started:part2 ubuntu Running Running 50 seconds ago n2bgt0wx11kg getstartedlab_web.2 hoge/get-started:part2 ubuntu Running Running 22 seconds ago 0b1v6d8jy5lu getstartedlab_web.3 hoge/get-started:part2 ubuntu Running Running 50 seconds ago sm21dfefpfgw getstartedlab_web.4 hoge/get-started:part2 ubuntu Running Running 32 seconds ago isx43duompwd getstartedlab_web.5 hoge/get-started:part2 ubuntu Running Running 11 seconds ago
ステータスはRunningになっています!動作しているようです。念の為もう一度Serviceの動作状況の確認を調べてみると…
$ docker service ls ID NAME MODE REPLICAS IMAGE PORTS p1dyl3harlzm getstartedlab_web replicated 5/5 hoge/get-started:part2 *:8080->80/tcp
無事に起動しているようです。ちょっとホッとしました。
今回の動作環境ではDockerでaufsを使用していないため、パフォーマンスが劇的に低くなっているため各コンテナの起動に時間がかかってしまったのではないかと考えます。(他の例でも、起動に関するパフォーマンスは明らかに落ちているのはわかります。)
ではブラウザでこの負荷分散サービスへアクセスしていきます。
アクセス先は同様にhttp://localhost:8080/
になります。このURLにアクセスするとロードバランスを図ってくれるのでアクセスする度(リロードする度)に
表示されるHostIDが変化していくことを確認してください。
$ docker swarm init Swarm initialized: current node (nc03uv6m1z1dxgwxdilvh29rj) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-1dukwcs4w07qt835cw6o5w0aju191e93be2jtctejrndzj5jyd-25d5b683d7jx4hceptehbtrz9 192.168.0.7:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions. $ docker stack deploy -c docker-compose.yml getstartedlab Creating network getstartedlab_webnet Creating service getstartedlab_web $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS p1dyl3harlzm getstartedlab_web replicated 0/5 hoge/get-started:part2 *:8080->80/tcp $ docker service ps getstartedlab_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS lgz0af823dtz getstartedlab_web.1 hoge/get-started:part2 ubuntu Running Running 50 seconds ago n2bgt0wx11kg getstartedlab_web.2 hoge/get-started:part2 ubuntu Running Running 22 seconds ago 0b1v6d8jy5lu getstartedlab_web.3 hoge/get-started:part2 ubuntu Running Running 50 seconds ago sm21dfefpfgw getstartedlab_web.4 hoge/get-started:part2 ubuntu Running Running 32 seconds ago isx43duompwd getstartedlab_web.5 hoge/get-started:part2 ubuntu Running Running 11 seconds ago $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS p1dyl3harlzm getstartedlab_web replicated 5/5 hoge/get-started:part2 *:8080->80/tcp
アプリケーションのスケールをしてみる
スケールをするのは簡単です。
docker-compose.yml
のレプリカの数を変更して保存し、再度docker stack deploy
コマンドを再実行するだけでアプリを拡張できます。
以下の例ではレプリカ数を5から3へ変更しています。非常にシームレスにスケールするのがわかります。
$ vim docker-compose.yml $ docker stack deploy -c docker-compose.yml getstartedlab Updating service getstartedlab_web (id: p1dyl3harlzm5ghawpj04noay) $ docker service ls ID NAME MODE REPLICAS IMAGE PORTS p1dyl3harlzm getstartedlab_web replicated 3/3 hoge/get-started:part2 *:8080->80/tcp $ docker service ps getstartedlab_web ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 7qeqrcn6etna getstartedlab_web.1 hoge/get-started:part2 ubuntu Running Running 20 seconds ago lgz0af823dtz \_ getstartedlab_web.1 hoge/get-started:part2 ubuntu Shutdown Shutdown 24 seconds ago y52g099pbi4f getstartedlab_web.2 hoge/get-started:part2 ubuntu Running Starting 2 seconds ago n2bgt0wx11kg \_ getstartedlab_web.2 hoge/get-started:part2 ubuntu Shutdown Shutdown 2 seconds ago 0b1v6d8jy5lu getstartedlab_web.3 hoge/get-started:part2 ubuntu Running Running 10 minutes ago
負荷分散させるアプリケーションがdocker-comporse.yml
の変更を行ってコマンド一発でスケールできるのは非常に便利です!
後片付け
Serviceの終了を指せる場合には以下のコマンドを使用します。
$ docker stack rm getstartedlab $ docker swarm leave --force
これで今回の環境は完全に終了します。
【ログ】
$ docker stack rm getstartedlab Removing service getstartedlab_web Removing network getstartedlab_webnet $ docker swarm leave --force Node left the swarm.
これでPart3は終了です。
Get Started, Part 4: Swarms
ここからはPart4でSwarmに関する部分になります。(Part3でもやってましたけど) Part4では、Swarmとはどういうものか、Swarm内のノードがマネージャまたはワーカーになる方法、Swarmを作成、その上にアプリをデプロイを行っていきます。 また、その環境下でPart3同様に異なるマシンで構成でDockerの基本機能、ネットワーク機能、負荷分散やスケールできることを実験してみます。
前提としてはPart3までが完了していればOKということになるのですが、新たにdocker-machine
コマンドが必要になります。
WindowsやOSXであればDocker環境をインストールするとすでに入るのですが、Linuxの場合には別途インストールが必要になります。
以下のサイトを見ながら作業となります。
抜粋すると以下のコマンドになります。(versionは0.16.0の場合)
$ base=https://github.com/docker/machine/releases/download/v0.16.0 && curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine && sudo install /tmp/docker-machine /usr/local/bin/docker-machine
インストール後の動作チェックは以下で大丈夫です。
$ docker-machine version docker-machine version 0.16.0, build 702c267f
クラスタの作成
ドキュメントを読んでいくと…
You need a hypervisor that can create virtual machines (VMs), so install Oracle VirtualBox for your machine’s OS.
なんとvirtualboxをインストールしてVMを起動しろと言われます。(ChromeOSではここまで来ると本末転用のような状況…OS環境を変えて正解だったのかも)
仕方ないので、以下のリンクからUbuntu用のUbuntu 18.04 (Bionic) / Ubuntu 18.10 (Cosmic) / Debian Unstable
パッケージをダウンロードします。
Ubuntuの場合、ブラウザ(Firefox)でダウンロードすると.deb
ファイルを認識してパッケージのインストールを行ってくれますので、
そのままインストールしてしまいましょう。
インストールが完了したら、以下のように2台のVMを起動します。--driver
で指定したVM環境が使用されVMが作成されます。
$ docker-machine create --driver virtualbox myvm1 $ docker-machine create --driver virtualbox myvm2
起動したVMはmyvm1
とmyvm2
という名前で起動しています。このVMのIPアドレスは以下のコマンドで調べることができます。
$ docker-machine ls
ubuntu@ubuntu:~$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS myvm1 - virtualbox Running tcp://192.168.99.101:2376 v18.09.3 myvm2 - virtualbox Running tcp://192.168.99.102:2376 v18.09.3
VMのIPアドレスがわかったら、2つともIPアドレスを控えておきます。そのうちの1台(今回はmyvm1
側)をSwarmのマネージャホストにします。
該当するホストでdocker-machine ssh
経由でdocker swarm init
コマンドを実行します。実行時に表示されるtokenはメモしておきます。というかコマンドそのものをコピーしておいたほうがいいかもしれません。(docker swarm join ほげほげの部分)
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>" Swarm initialized: current node <node ID> is now a manager. To add a worker to this swarm, run the following command: docker swarm join \ --token <token> \ <myvm ip>:<port> To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
【ログ】
$ docker-machine ssh myvm1 "docker swarm init --advertise-addr 192.168.99.101" Swarm initialized: current node (76irf1ec7b14xfns1oym7638x) is now a manager. To add a worker to this swarm, run the following command: docker swarm join --token SWMTKN-1-0hdt9lh014fow8y0yrzw6sruqdzb275sw2ohwhiolzfy0ev05z-42bhd4wxtwd9hu7ndx9prrzzd 192.168.99.101:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
念の為、Swarmを使用する場合にはポート2377とポート2376を使用する可能性があるので、使用しないように注意が必要です。
また、上記のdocker-machine ssh
でコマンドを送信できない場合にはホストにネイティブにインストールされているsshコマンドを使用する事もできます
その場合には--native-ssh ssh
オプションを追加設定します。具体的には以下のようになります。
$ docker-machine --native-ssh ssh myvm1 "docker swarm init --advertise-addr <myvm1 ip>"
続いて2台目のVM(今回はmyvm2
)をワーカーとして登録します。その際は先程実行したdocker swarm init
の戻りでtokenが表示されているので
それをオプション指定してdocker swarm join
をホストに送信します。例の
$ docker-machine ssh myvm2 "docker swarm join --token <token> <ip>:2377"
$ docker-machine ssh myvm2 "docker swarm join --token SWMTKN-1-0hdt9lh014fow8y0yrzw6sruqdzb275sw2ohwhiolzfy0ev05z-42bhd4wxtwd9hu7ndx9prrzzd 192.168.99.101:2377" This node joined a swarm as a worker.
これでSwarmが生成できました。以下のコマンドで生成されたノードを表示してみます。
$ docker-machine ssh myvm1 "docker node ls"
ここでもし最初からやり直す場合にはdocker swarm leave
を実行するとSwarmが終了し元に戻ります。
アプリのデプロイを行う
Swarmができあがったので、アプリをデプロイしていきます。
これまではdocker-machine ssh
で実行していましたが、これではいちいちコマンドを実行していく必要があるので結構手間です。そこでdocker-machine env
で得られる情報を元にローカルのdocker-compose.yml
ファイルを使用してデプロイする方法もあります。今回はそれを使用してみます。
環境変数の設定はdocker-machine env
で取得できるので
$ docker-machine env myvm1 export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.99.101:2376" export DOCKER_CERT_PATH="/home/ubuntu/.docker/machine/machines/myvm1" export DOCKER_MACHINE_NAME="myvm1" # Run this command to configure your shell: # eval $(docker-machine env myvm1)
この情報をeval
で取り込んで有効化します。
$ eval $(docker-machine env myvm1)
すると、今回作成したmyvm1
がアクティブ状態になります。
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS myvm1 * virtualbox Running tcp://192.168.99.101:2376 v18.09.3 myvm2 - virtualbox Running tcp://192.168.99.102:2376 v18.09.3
Part3と同様にアプリのデプロイして、動作を確認してみます。
【注意】デプロイを行う前にdocker-compose.yml
ファイルのあるパスに移動しておいてください。
myvm1
のホスト上で以下のコマンドを実行すると
$ cd ./friendlyhello/ $ docker stack deploy -c docker-compose.yml getstartedlab
【ログ】
$ docker stack deploy -c docker-compose.yml getstartedlab Creating network getstartedlab_webnet Creating service getstartedlab_web
myvm1
とmyvm2
にアプリが分散配置されて起動されます。以下のコマンドで分散の状況を確認することができます。
$ docker stack ps getstartedlab
$ docker stack ps getstartedlab ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS 886onhvdec3j getstartedlab_web.1 ueponx/get-started:part2 myvm2 Running Running 3 minutes ago ukvh7zbk85e8 getstartedlab_web.2 ueponx/get-started:part2 myvm1 Running Running 3 minutes ago tgvo877hsaox getstartedlab_web.3 ueponx/get-started:part2 myvm2 Running Running 3 minutes ago ffzmzokyv6v7 getstartedlab_web.4 ueponx/get-started:part2 myvm1 Running Running 3 seconds ago jq5q4ukq9w6b getstartedlab_web.5 ueponx/get-started:part2 myvm1 Running Running 3 seconds ago
ここまできたらブラウザなどを使ってmyvm1
またはmyvm2
のIPアドレスにアクセスを行います。
【myvm1へのアクセス】
【myvm2へのアクセス】
この環境でスケールさせる場合にはdocker-compose.yml
を修正し、docker stack deploy
を実行することでスケールが用意にできます。またノードの追加に関しても今回のmyvm2
と同様に追加することでホスト単位のスケールも用意にできるようになります。
stackの終了方法
stackの終了方法は今回の場合は以下のようになります。
$ docker stack rm getstartedlab
環境変数のクリア
docker-machine env
で設定した設定は以下のように行うとクリアできます。
$ eval $(docker-machine env -u)
ローカルホストを終了させればdockerのマシンも終了します。状態を確認する場合には以下のコマンドとなります。
$ docker-machine ls
停止したノードを再起動させる場合にはホスト名を指定して以下のように再起動ができます。
$ docker-machine start <machine-name>
おわりに
OSを変更することでようやくPart3とPart4がおわらせられました。しかし、このチュートリアルかなり事前準備の要求が高いですね。あともう少し頑張ってみます。
【参考エントリー】