Help us understand the problem. What is going on with this article?

Swarm と組み合わせて Compose(Fig) をマルチホスト環境で使う

More than 5 years have passed since last update.

概要

Swarm と組み合わせることで、Compose(Fig) がマルチホスト環境下で使えるようになるという話。

Sinatra コンテナと Redis コンテナからなるアプリケーションを複数の Docker ホストにまたがって配置する。

マルチホスト環境での Compose

Swarm クラスタの構築

を参考に 3 台の Docker ホストを用意する。

$ docker -H core-01:2377 info
Containers: 4
Nodes: 3
 core-01: core-01:2375
  └ Containers: 2
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 998 MiB
 core-03: core-03:2375
  └ Containers: 1
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 998 MiB
 core-02: core-02:2375
  └ Containers: 1
  └ Reserved CPUs: 0 / 1
  └ Reserved Memory: 0 B / 998 MiB

それぞれ 2375 ポートから Docker Remote API が使える状態。

  • core-01: tcp://core-01:2375
  • core-02: tcp://core-02:2375
  • core-03: tcp://core-03:2375
$ docker -H core-01:2377 ps -a
CONTAINER ID        IMAGE               COMMAND                CREATED              STATUS              PORTS                         NAMES
8a6d378fd434        swarm:latest        "/swarm join --addr=   7 seconds ago        Up About a minute   2375/tcp                      core-02/swarm-agent-core-02
0cd3fbda1f31        swarm:latest        "/swarm join --addr=   About a minute ago   Up About a minute   2375/tcp                      core-03/swarm-agent-core-03
62b93d0e9f7c        swarm:latest        "/swarm join --addr=   7 minutes ago        Up 7 minutes        2375/tcp                      core-01/swarm-agent-core-01
df7b39a2eeba        swarm:latest        "/swarm manage --tls   8 minutes ago        Up 8 minutes        172.17.8.101:2377->2375/tcp   core-01/swarm-manager

Swarm マネージャは core-01 に立っていて、core-01:2377 がエンドポイント。(だから $ docker -H core-01:2377 としている)
Swarm エージェントは各ノードにそれぞれいる。

  • core-01
    • swarm manager
    • swarm agent 01
  • core-02
    • swarm agent 02
  • core-03
    • swarm agent 03

Compose をシングルホスト環境で使う

まずはシングルホスト環境下で Compose を使ってみる。

を参考に compose をインストールし、

で使った構成をベースに使う

# docker-compose.yml
web:
  image: quay.io/spesnova/sinatra-hello-world
  command: bundle exec ruby app.rb
  ports:
    - 4567
  links:
    - redis
  environment:
    - REDIS_HOST=redis
    - REDIS_PORT=6379
redis:
  image: redis:latest

ポイント 3 つ

  • コンテナのスケールをする際のポートの衝突を避けるために web サービスの ports80:4567 から 4567 に変える
  • どの Docker ホストからでもイメージが取得できるよう build の代わりに image を指定する(イメージも push しておく)
  • 開発時は手元のコードをコンテナと共有したいので VOLUME を使っていたが、今回はできたイメージを使うので web サービスコンテナの volumes を外す

起動してみる

# at core-01
$ cd sample
$ docker-compose up -d
Creating sample_redis_1...
Creating sample_web_1...

こんな状態

$ docker-compose ps
     Name                  Command             State              Ports
-----------------------------------------------------------------------------------
sample_redis_1   /entrypoint.sh redis-server   Up      6379/tcp
sample_web_1     bundle exec ruby app.rb       Up      172.17.8.101:49153->4567/tcp

スケールしてみる

$ docker-compose scale web=2
Creating sample_web_2...
Starting sample_web_2...

$ docker-compose ps
     Name                  Command             State            Ports
------------------------------------------------------------------------------
sample_redis_1   /entrypoint.sh redis-server   Up      6379/tcp
sample_web_1     bundle exec ruby app.rb       Up      0.0.0.0:49155->4567/tcp
sample_web_2     bundle exec ruby app.rb       Up      0.0.0.0:49156->4567/tcp

当たり前だけど core-01 に web サービスコンテナが 2 つ起動している。

一旦コンテナは停止、削除しておく

$ docker-compose kill && docker-compose rm
Killing sample_web_2...
Killing sample_web_1...
Killing sample_redis_1...
Going to remove sample_web_2, sample_web_1, sample_redis_1
Are you sure? [yN] y
Removing sample_redis_1...
Removing sample_web_2...
Removing sample_web_1...

Swarm を利用して Compose(Fig) をマルチホスト環境で使う

Swarm API は既存の Docker API と互換性があるように作られているので、core-01 の Docker API の代わりに Swarm API を使うことができる。
Swarm API を使うと、たとえば、docker run busybox echo hello world するとマルチホストのどこかで busybox コンテナが実行される。同じように Compose から使えば、 Sinatra コンテナ+ Redis コンテナの組み合わせがマルチホストのどこかで起動するということ。

図にするとこういうこと

# シングルホスト環境での Compose の利用
Compose ---> Docker Remote API (Docker Host, core-01)


# マルチホスト環境での Compose の利用
                           ---> Docker Remote API(Docker Host, core-01)
                          /
Compose ---> Swarm API --- ---> Docker Remote API(Docker Host, core-02)

                          \---> Docker Remote API(Docker Host, core-03)

Swarm 用に docker-compose.yml の編集

デフォルトで Swarm API を使うように設定する

$ export DOCKER_HOST=tcp://core-01:2377

さらに docker-compose.yml をいじる

web:
  image: quay.io/spesnova/sinatra-hello-world
  command: bundle exec ruby app.rb
  ports:
    - 4567
  environment:
    - REDIS_HOST=172.17.8.101 # 追加
    - REDIS_PORT=6379
    - affinity:container!=sample_web_* # 追加
redis:
  image: redis:latest
  ports:
    - 6379:6379 # 追加
  environment:
    - constraint:node==core-01 # 追加

マルチホストで web サービスコンテナを動かす場合 LINK で連携はできないので、

  • web サービスコンテナから link を外す
  • web サービスコンテナの Redis ホストを core-01 に向ける
  • redis サービスコンテナのポートを外部にさらす
  • redis コンテナが core-01 で動くように Swarm 用に contraint を設定

さらに web サービスコンテナ同士は別々の Docker ホストで起動するような設定を付けた。affinity:container!=sample_web_*sample_web_* という名前のコンテナがいたらそこでは web サービスコンテナは立てないという条件。

Swarm を使ってスケール

docker-compose up -d してみる

$ docker-compose up -d
Creating sample_redis_1...
Creating sample_web_1...

docker-compose psdocker ps してみる

$ docker-compose ps
     Name                  Command             State             Ports
--------------------------------------------------------------------------------
sample_redis_1   /entrypoint.sh redis-server   Up      6379/tcp
sample_web_1     bundle exec ruby app.rb       Up      172.17.8.101:80->4567/tcp

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS                  PORTS                       NAMES
0fa8b600d765        redis:latest        "/entrypoint.sh redi   9 seconds ago       Up Less than a second   6379/tcp                    core-01/sample_redis_1
599a99f51659        sample_web:latest   "bundle exec ruby ap   9 seconds ago       Up Less than a second   172.17.8.101:80->4567/tcp   core-01/sample_web_1

docker-compose コマンドを実行しているホストと同じ core-01 でコンテナが立ったもよう。ここまでは普通。

web サービスコンテナをスケールしてみる

$ docker-compose scale web=2
Creating sample_web_2...
Starting sample_web_2...

web_2 が core-03 に立った

$ docker ps
CONTAINER ID        IMAGE                                         COMMAND                CREATED             STATUS                  PORTS                          NAMES
23d5276ef844        quay.io/spesnova/sinatra-hello-world:latest   "bundle exec ruby ap   3 seconds ago       Up Less than a second   172.17.8.103:49155->4567/tcp   core-03/sample_web_2
f94b9cf27ba3        redis:latest                                  "/entrypoint.sh redi   43 seconds ago      Up 16 seconds           172.17.8.101:6379->6379/tcp    core-01/sample_redis_1
8469bdd81f5a        quay.io/spesnova/sinatra-hello-world:latest   "bundle exec ruby ap   43 seconds ago      Up 17 seconds           172.17.8.101:49165->4567/tcp   core-01/sample_web_1

$ docker-compose ps
     Name                  Command             State              Ports
-----------------------------------------------------------------------------------
sample_redis_1   /entrypoint.sh redis-server   Up      172.17.8.101:6379->6379/tcp
sample_web_1     bundle exec ruby app.rb       Up      172.17.8.101:49165->4567/tcp
sample_web_2     bundle exec ruby app.rb       Up      172.17.8.103:49155->4567/tcp

で Hello World 及びアクセス数のインクリメントができる

さらにスケールする

$ docker-compose scale web=3
Creating sample_web_3...
Starting sample_web_3...

今度は core-02 に立った

$ docker ps
CONTAINER ID        IMAGE                                         COMMAND                CREATED                  STATUS                  PORTS                          NAMES
737f31bf1d0a        quay.io/spesnova/sinatra-hello-world:latest   "bundle exec ruby ap   Less than a second ago   Up Less than a second   172.17.8.102:49153->4567/tcp   core-02/sample_web_3
23d5276ef844        quay.io/spesnova/sinatra-hello-world:latest   "bundle exec ruby ap   2 minutes ago            Up 2 minutes            172.17.8.103:49155->4567/tcp   core-03/sample_web_2
f94b9cf27ba3        redis:latest                                  "/entrypoint.sh redi   3 minutes ago            Up 2 minutes            172.17.8.101:6379->6379/tcp    core-01/sample_redis_1
8469bdd81f5a        quay.io/spesnova/sinatra-hello-world:latest   "bundle exec ruby ap   3 minutes ago            Up 2 minutes            172.17.8.101:49165->4567/tcp   core-01/sample_web_1

$ docker-compose ps
     Name                  Command             State              Ports
-----------------------------------------------------------------------------------
sample_redis_1   /entrypoint.sh redis-server   Up      172.17.8.101:6379->6379/tcp
sample_web_1     bundle exec ruby app.rb       Up      172.17.8.101:49165->4567/tcp
sample_web_2     bundle exec ruby app.rb       Up      172.17.8.103:49155->4567/tcp
sample_web_3     bundle exec ruby app.rb       Up      172.17.8.102:49153->4567/tcp

172_17_8_103_49155_と_172_17_8_102_49153_と_172_17_8_101_49165_と_Compose_yml_-_Docker_Documentation.png

さらにスケールすると

$ docker-compose scale web=4
Creating sample_web_4...
unable to find a node that satisfies container!=sample_web_*

web コンテナがいない Docker ホストが見つからないので立てられないよというメッセージ。affinity がちゃんと動いている

マルチホスト環境でもまとめてログが見られる

$ docker-compose logs

1__core_core-01___sample__ssh_.png

REF

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away