アプリケーションのデプロイ¶
Swarm クラスタを構築 しましたので、投票アプリケーションを構築・デプロイする準備が整いました。
ステップ1:イメージについて学ぶ¶
起動するアプリケーション用コンテナのいくつかは、 Docker Hub から既存のイメージを直接取得します。カスタム・イメージを必要とする他のコンテナは、自分で構築する必要があります。どのコンテナがカスタム・イメージを使えるどうか、あるいは構築する必要があるか確認します。
- ロードバランサ・コンテナ:作成済みイメージ(
ehazlett/interlock
) - Redis コンテナ:作成済みイメージ(公式
redis
イメージ) - Postgres ( PostgreSQL ) コンテナ:作成済みイメージ(公式
postgres
イメージ) - Web コンテナ:カスタム・イメージを構築
- Worker コンテナ:カスタム・イメージを構築
- Results コンテナ:カスタム・イメージを構築
カスタム・イメージの構築に必要な Dockerfile は、 アプリケーションの GitHub 公開リポジトリ から取得できます。
- Swarm``manager`` ノードに
ssh
で接続していなければ、接続します。
- アプリケーションの GitHub リポジトリ をクローンします。
$ git clone https://github.com/docker/swarm-microservice-demo-v1
sudo: unable to resolve host master
Cloning into 'swarm-microservice-demo-v1'...
remote: Counting objects: 304, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 304 (delta 5), reused 0 (delta 0), pack-reused 287
Receiving objects: 100% (304/304), 2.24 MiB | 2.88 MiB/s, done.
Resolving deltas: 100% (132/132), done.
Checking connectivity... done.
このコマンドは、現在のディレクトリ直下に新しいディレクトリ階層を作成します。新しいディレクトリには投票アプリケーション・イメージの構築に必要な全てのファイルとフォルダがあります。
AWS
ディレクトリにある cloudformation.json
ファイルは EC2 インスタンスのデプロイに使いました。 Vagrant
ディレクトリにあるファイルや命令は Vagrant を使ってアプリケーションをデプロイする時に必要となります。 results-app
、 vote-worker
、 web-vote-app
ディレクトリには Dockerfile が入っています。これは、 アプリケーションの各コンポーネントとして必要になるカスタム・イメージを構築するために必要なファイルです。
swarm-microservice-demo-v1/web-vote-app
ディレクトリに移動します。
$ cd swarm-microservice-demo-v1/web-vote-app/
- Dockerfile の内容を確認します。
$ cat Dockerfile
# Using official python runtime base image
FROM python:2.7
# Set the application directory
WORKDIR /app
# Install our requirements.txt
ADD requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
# Copy our code from the current folder to /app inside the container
ADD . /app
# Make port 80 available for links and/or publish
EXPOSE 80
# Define our command to be run when launching the container
CMD ["python", "app.py"]
ご覧の通り、このイメージは公式の Python:1.7
とタグ付けされたイメージをベースにします。 /app
ディレクトリに必要なファイルを追加し、依存関係のあるものをインストールし、構築コンテクストに含めるファイルをコンテナ内にコピーし、コンテナのコマンド実行時にポート 80
を公開するよう命令しています。
- 投票アプリケーションの他のパーツも、
results-app/Dockerfile
とvote-worker/Dockerfile
を時間をかけて確認します。
ステップ2:カスタム・イメージの構築¶
- Swarm
manager
ノードにssh
で入っていなければ、入ります。
DOCKER_HOST
が設定されているのを確認します。
$ export DOCKER_HOST="tcp://192.168.33.11:3375"
swarm-microservice-demo-v1
をクローンしたディレクトリに移動します。
- 各フロントエンドのノード上で
web-votes-app
イメージを構築します。
frontend01:
$ docker -H tcp://192.168.33.20:2375 build -t web-vote-app ./web-vote-app
frontend02:
$ docker -H tcp://192.168.33.21:2375 build -t web-vote-app ./web-vote-app
これらのコマンドは frontend01
と frontend02
ノード上に web-vote-app
イメージを構築します。これらのコマンドを実行すると、 manager
ノード上の swarm-microservice-demo-v1/web-vote-app
サブディレクトリの内容が、各フロントエンドのノードにコピーされます。そして、このコマンドは各フロントエンド・ノード内でローカルにイメージを構築・保管します。
このサンプルでは -H
フラグを使いイメージを取得するホストを指定します。これがこのサンプルのアーキテクチャの概念を理解する手助けになるでしょう。プロダクション環境のデプロイでは、この作業を省略し、Swarm マネージャでイメージを配布させることも可能です。マネージャはイメージを必要とする各ノード上で、個々にイメージを取得(pull)することができます。
イメージ構築には数分ほど時間がかかるかもしれません。構築完了までお待ち下さい。
worker01
ノード上でvote-worker
イメージを構築します。
$ docker -H tcp://192.168.33.200:2375 build -t vote-worker ./vote-worker
イメージ構築には数分ほど時間がかかるかもしれません。構築完了までお待ち下さい。
store
ノード上でresults-app
を構築します。
$ docker -H tcp://192.168.33.250:2375 build -t results-app ./results-app
アプリケーションが必要とする各カスタム・イメージを構築し、実行する各ノードのローカルに保管しました。
ステップ3:Docker Hub からイメージを取得¶
パフォーマンス上の理由により、それぞれのインスタンスの必要性に応じて、Docker Hub からイメージをダウンロードするのは良い方法です。そうすることで、必要とするコンテナを迅速に実行できます。
- Swarm
manager
ノードにログインします。
- フロントエンド・ノード で
redis
イメージを取得します。
frontend01:
$ docker -H tcp://192.168.33.20:2375 pull redis
frontend02:
$ docker -H tcp://192.168.33.21:2375 pull redis
store
ノードにpostgres
イメージを取得します。
$ docker -H tcp://192.168.33.250:2375 pull postgres
interlock
ノードにehazlett/interlock
イメージを取得します。
$ docker -H tcp://192.168.33.12:2375 pull ehazlett/interlock
クラスタ上のノードだけでなく、 interlock
ノードの準備も整いました。これで次のように各ノードで必要なイメージがローカルに保管されている状態です。
これで全てのイメージを構築・取得し、ローカルに保存しました。次のステップはアプリケーションの起動です。
ステップ4:投票用アプリケーションを起動¶
以下の手順は、投票用アプリケーションのコンテナを起動します。
- Swarm
manager
ノードにssh
接続していなければ、接続します。
interlock
ノードでinterlock
コンテナを起動します。
$ docker -H tcp://192.168.33.12:2375 run --restart=unless-stopped -p 80:80 --name interlock -d ehazlett/interlock --swarm-url tcp://192.168.33.11:3375 --plugin haproxy start
このコマンドは interlock
インスタンスのポート 80 をコンテナ内のポート 80 に割り当てます。これにより、コンテナがポート 80 (HTTP)に来たトラフィックを負荷分散できます。また、このコマンドはコンテナに対して --restart=unless-stopped
ポリシーを設定しています。これはコンテナが不意に停止することがあれば、コンテナを(自動的に)再起動します。
- コンテナが起動していることを確認します。
$ docker -H tcp://192.168.33.12:2375 ps
- フロントエンド・ノード上で
redis
コンテナを起動します。
frontend01:
$ docker run --restart=unless-stopped --env="constraint:node==frontend01" -p 6379:6379 --name redis01 --net mynet -d redis
$ docker -H tcp://192.168.33.20:2375 ps
frontend02:
$ docker run --restart=unless-stopped --env="constraint:node==frontend02" -p 6379:6379 --name redis02 --net mynet -d redis
$ docker -H tcp://192.168.33.21:2375 ps
Swarm クラスタに対して2つのコマンドを実行します。このコマンドはノード制約(code constrains)を指定し、Swarm に frontend01
と frontend02
でコンテナを起動するよう指定しています。また、デバッグ目的のために各コンテナのポート 6379 を各インスタンスのポート 6379 に割り当てます。さらにコンテナに対する --restart=unless-stopped `` ポリシーと、コンテナを ``mynet
オーバレイ・ネットワークに接続する設定を行っています。
- フロントエンド・ノード上で
web-vote-app
コンテナを起動します。
frontend01:
$ docker run --restart=unless-stopped --env="constraint:node==frontend01" -d -p 5000:80 -e WEB_VOTE_NUMBER='01' --name frontend01 --net mynet --hostname votingapp.local web-vote-app
frontend02:
$ docker run --restart=unless-stopped --env="constraint:node==frontend02" -d -p 5000:80 -e WEB_VOTE_NUMBER='02' --name frontend02 --net mynet --hostname votingapp.local web-vote-app
Swarm クラスタに対して2つのコマンドを実行します。このコマンドはノード制約(code constrains)を指定し、Swarm に frontend01
と frontend02
でコンテナを起動するよう指定しています。また、各コンテナのポート 80
を各インスタンスのポート 5000
に割り当てます。これは各ノード上のポート 5000
に接続すると、各コンテナのポート 80
に転送されます。
どちらのコンテナも mynet
オーバレイ・ネットワークに接続し、どちらも votingapp-local
ホスト名を持ちます。コンテナに対して --restart=unless-stopped
ポリシーも指定しています。
store
ノード上でpostgres
コンテナを起動します。
$ docker run --restart=unless-stopped --env="constraint:node==store" --name pg -e POSTGRES_PASSWORD=pg8675309 --net mynet -p 5432:5432 -d postgres
このコマンドは Swarm クラスタに対して store
上でコンテナを起動します。 store
ノード上のポート 5432 をコンテナ内の 5432 に割り当てて、コンテナを mynet
オーバレイ・ネットワークに接続します。
プロダクションでの利用ではパスワード共有は推奨されません。
worker01
ノード上でworker01
コンテナを起動します。
$ docker run --restart=unless-stopped --env="constraint:node==worker01" -d -e WORKER_NUMBER='01' -e FROM_REDIS_HOST=1 -e TO_REDIS_HOST=2 --name worker01 --net mynet vote-worker
このコマンドは Swarm マネージャに対して worker01
ノード上でコンテナを起動するよう制約(constraint)を使っています。これは環境変数を通して設定用のデータを渡しています。これは worker コンテナに対して、 frontend01
と frontend02
にあるキューをクリアにするよう命令しています。また、コンテナを mynet
オーバレイ・ネットワークに追加し、コンテナに --restart=unless-stopped
ポリシーを適用しています。
store
ノード上でresults-app
コンテナを起動します。
$ docker run --restart=unless-stopped --env="constraint:node==store" -p 80:80 -d --name results-app --net mynet results-app
このコマンドはノード制約(node constraint)によって store
ノード上に results-app コンテナを起動します。 store
ノードのポート 80 をコンテナ内のポート 80 に割り当てます。コンテナを mynet
オーバレイ・ネットワークに接続し、 --restart=unless-stopped
ポリシーをコンテナに適用します。
下図の状態となれば、これでアプリケーションのデプロイは完了です。
ステップ5:アプリケーションのテスト¶
これでアプリケーションはデプロイが終わり、実行中になりました。さぁ、テストの時間です。そのためにはウェブ・ブラウザが実行中のマシンから参照できるよう、DNS 設定を調整する必要があります。そのために「votingapp.local」DNS名を interlock
ノードのパブリック IP アドレスに割り当てます。
- ブラウザで参照できるようにするため、ローカルのマシン上の DNS 名前解決の設定を変更します。
- Windows マシンの場合は
C:\Windows\System32\Drivers\etc\hosts file
ファイルにvotingapp.local <interlock-パブリックIP>
の行を追加します。管理者権限でファイルを開くためにC:\Windows\System32\notepad.exe
を右クリックし、管理者として実行
を選びます。メモ帳が開いたら、ファイル
→開く
でファイルを開き、編集します。 - OSX マシンの場合は
votingapp.local <interlock-パブリックIP>
を/private/etc/hosts
に追加します。 - 殆どの Linux マシン上では
votingapp.local <interlock-パブリックIP>
を/etc/hosts
に追加します。
<interlock-パブリックIP>
の部分は、各自の interlock
ノードの IP アドレスに置き換えてください。 AWS EC2 コンソール内の interlock
EC2 インスタンスの場所からノードのパブリック IP アドレスを確認できます。
- 正常に名前解決できるか確認するために、自分のマシン上で
ping
コマンドを実行します。
ping votingapp.local
Pinging votingapp.local [54.183.164.230] with 32 bytes of data:
Reply from 54.183.164.230: bytes=32 time=164ms TTL=42
Reply from 54.183.164.230: bytes=32 time=163ms TTL=42
Reply from 54.183.164.230: bytes=32 time=169ms TTL=42
- ブラウザで http://votingapp.local を開きます。
ウェブページ上の文字列にご注意ください。ここに表示されているのは、どのウェブ・コンテナ・サービスに対してリクエストしているかです。これが frontend02
であれば、ウェブ・ブラウザを再読込すると、 interlock ロード・バランサは入ってきたリクエストを両方のコンテナに振り分けるのが分かります。
Interlock サービスの負荷分散に関する詳細なデータは、ブラウザで http://stats:interlock@votingapp.local/haproxy?stats を開きます。
- 投票します。「Dogs」を選ぶことを推奨します ;-)
- 投票結果を見るには、
store
ノードのパブリック IP アドレスをブラウザで開きます。
次のステップ¶
おめでとうございます。マイクロサービスをベースとしたアプリケーションを Swarm クラスタ上に手動でデプロイできました。もちろん、すべてが上手くいくとは限りません。どのようにスケールするアプリケーションをデプロイするかを学びましたので、次は Swarm クラスタ上で大規模アプリケーション実行時のトラブルシューティング を学ぶべきでしょう。
参考
- Deploy the application
- https://docs.docker.com/swarm/swarm_at_scale/04-deploy-app/