まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:docker

以前にとある人から
 (例えば仮想マシン環境と比較して)コンテナ環境のデメリットはなんですか?
と質問され、一瞬返答に詰まってしまったことがありました。メリットを考えたことはあったけど、積極的にデメリットを考えたことがなく、即答できませんでした。ちゃんと正しく理解していないとなかなか難しい質問だと思っています。

改めて時間のある時に考えてみるといくつか思いつきます。まあ「デメリット」といえるかどうかはともかく、「VMでできてコンテナでできないこと」はいくつかあります。

その一つが "cron" ジョブだと思っています。特定時刻とか、何分おきにとか、実行タイミングのスケジュールを決めた上で実行する機能です。例えば kubernetes であれば CronJob を使って実現するなど、厳密には「コンテナで実現できない」わけではないのですが、そのコンテナ環境に合わせた対応が必要になるのはそれはそれでデメリットになりえますよね。

一方、アプリケーション開発レベルでは、これらのスケジュールジョブを併用することでアプリケーションとしての必要な機能を実現することは珍しくありません。1分毎にどこかからデータを取得して更新するとか、毎日○時に自動的にバックアップを取得するとかといった場合です。それらの機能が必要なアプリケーションをコンテナ環境で動かす可能性がある中で実装する場合、どういった方法を検討する必要があるでしょうか?


その答えの1つが「アプリケーションレベルで(アプリケーションの機能の一部として) cron ジョブを実装する」方法です。Node.js アプリケーションの場合は Node-Schedule ライブラリを使うと簡単に実現できそうだったので、その内容を以下で紹介します:
2020071200



Node-Schedule は Node.js で使えるライブラリで、cron ライクなスケジュールジョブを比較的簡単に(setTimeout とかを意識することなく)実現できます。またスケジュールの定義フォーマットは cron のものと互換性があるので、crontab に1行追加する感覚で、アプリケーション内にスケジュールジョブを追加・更新・削除できるものです。アプリケーションの中でスケジュールジョブを定義できるので、アプリケーションの実行環境(実機とか、VM とか、コンテナとか、・・)を意識する必要もありません。

例を1つ記述しておきます。以下のコードで1分おきにコンソールにメッセージを表示するウェブアプリケーションが作成できます(Node-Schedule に関係している部分のみ赤字):
// app.js
var schedule = require( 'node-schedule' );
var express = require( 'express' );
var app = express();

//. 毎分実行
schedule.scheduleJob( '* * * * *', function(){
  console.log( 'running a task every minute' );
});


app.get( '/', function( req, res ){
  res.write( JSON.stringify( { status: true }, null, 2 ) );
  res.end();
});


var port = process.env.PORT || 8080;
app.listen( port );
console.log( 'server started on ' + port );

上記コードから赤字部分を抜くと、ごくシンプルな Node.js + Express のウェブアプリケーションになるのがわかると思います。つまり Node-Schedule に関係しているのは赤字部分の実質4行だけです。

で、その赤字部分で何をしているのかというと、まず先頭行で require() して Node-Schedule ライブラリのモジュールを呼び出します:
// app.js
var schedule = require( 'node-schedule' );

そして scheduleJob() メソッドを使ってジョブを(イメージとしては cron に)登録します:
//. 毎分実行
schedule.scheduleJob( '* * * * *', function(){
  console.log( 'running a task every minute' );
});

この第一パラメータは cron に登録する時に指定する時刻フォーマットと互換性のある文字列表現を使います。'* * * * *' は「毎分実行」を意味しています。

そして第二パラメータには該当時刻になったら実行するコールバック関数を指定します。上の例では 'running a task every minute' とコンソールに表示するだけの内容にしていますが、実際にはここに crontab の最後に指定するコマンドを登録することになります。これで1分ごとに 'running a task every minute' という文字列がコンソールに表示され続けるジョブが登録できたことになります。


なお、一度登録したジョブをキャンセルするには登録時の scheduleJob() メソッドの実行結果オブジェクトを受け取り、そのオブジェクトの cancel() メソッドを実行します:
//. 毎分実行
var job = schedule.scheduleJob( '* * * * *', function(){
  console.log( 'running a task every minute' );
});

  :

job.cancel(); //. 登録したジョブをキャンセル

ジョブの実行条件や実行内容を更新する場合は一度キャンセルしてから再登録することで実現できます。


最近のクラウド環境は PaaS 化が進み、どういうコンテナ環境を使っているのかよくわからないことがあるかもしれません。アプリケーションを Node.js で記述するという条件はありますが、この方法で実装していればコンテナ環境に依存しないスケジュールジョブが実現できそうです。


不定期(要するに「ふと思い立ったタイミング」)で LinuxONE の紹介をしています。LinuxONE はメインフレームのハードウェア上で動く Linux です。そういえば LinuxONE で docker って使えるんだろうか?使えるとしたらどのあたりまで使える?? ということを確認したくなって、久しぶりに LinuxONE コミュニティクラウドの環境構築をしてみました。なお、以下の内容は 2019/05/27 時点の状況を紹介したものです。
2019052700


LinuxONE コミュニティクラウドは最大 120 日間無料で利用可能な LinuxONE の環境です。パブリックな IP アドレスが割り振られるので、インターネットから利用することもできます。FAQ も参照ください:
https://developer.ibm.com/linuxone/resources/faq/


LinuxONE コミュニティクラウドの申し込み方法は以前(2017年)のブログエントリで紹介したものとほとんど変わっていません。こちらを参照してください:
http://dotnsf.blog.jp/archives/1063515821.html

ここで記載されている情報と異なる点として、2019/05/27 現在では OS として RHEL 6.x を選択することはできなくなっています。そのため今回は RHEL 7.x を選択しました(RHEL 7.6 が導入されました)。またサーバーのスペック選択肢が廃止され、常に 2CPU + 4GB メモリ + 50 GB ディスク の環境が提供されるようになっていました。

仮想サーバーができたら IP アドレスとサーバー作成時に作ってダウンロードした鍵ファイル(*.pem)を指定して linux1 ユーザーでログインします:
2019052701


ログインできました。実際に試していただくとわかるのですが「ほぼ x86_64 版の RHEL 7.6」です。明示的にアーキテクチャを確認しないと s390x 版であることに気づかないかもしれません。

そしてこの後の docker 環境構築の手順に備えて root ユーザーに切り替えます:
$ sudo -i
#


さて、docker および docker-compose をこの LinuxONE 環境に導入していきます。手順そのものはこちらで紹介されているものをほぼそのまま使うのですが、2019/05/27 現在の環境では記載そのままの手順では途中でエラーになってしまい、導入できませんでした。エラー回避のため、少し異なる手順で導入します(異なる部分をで記載しています)。
https://github.com/IBM/Cloud-Native-Workloads-on-LinuxONE/blob/master/README-ja.md


【docker の導入】
まずインストールする docker の s390x 向けパッケージファイルをダウンロードします。RHEL 7.3 以上向けに docker 17.05 の CE(Community Edition)版が用意されているのでダウンロードします:
# wget ftp://ftp.unicamp.br/pub/linuxpatch/s390x/redhat/rhel7.3/docker-17.05.0-ce-rhel7.3-20170523.tar.gz

ダウンロードしたアーカイブファイルを展開し、バイナリを /usr/local/bin/ 以下にコピーします:
# tar -xzvf docker-17.05.0-ce-rhel7.3-20170523.tar.gz
# cp docker-17.05.0-ce-rhel7.3-20170523/docker* /usr/local/bin/

2019/05/27 時点では標準状態では /usr/local/bin にパスが通っていませんでした。このままだと docker コマンドがそのまま使えないので、パスを通しておきます:
# export PATH=$PATH:/usr/local/bin

これで docker コマンドが使えるようになったので、docker デーモンを起動します:
# docker daemon -g /local/docker/lib &


【docker-compose の導入】
続いて docker-compose もインストールします。実はこちらがドキュメント通りにいかない部分が多く、少し厄介でした。

手順としては pip を使って docker-compose をインストールします。そのため pip を先にインストールするのですが、pip をインストールするための依存ライブラリを先に導入します:
# yum install -y python-setuptools

そして pip をインストールします:
# easy_install pip

インストールした pip を使って、まず backports.ssl_match_hostname をアップグレードするのですが、このコマンドをドキュメント通りに入力すると既に導入済みの環境とのコンフリクトが起こってエラーになってしまいました。というわけで --ignore-installed オプションを付けて実行します:
# pip install backports.ssl_match_hostname --upgrade --ignore-installed

そして pip で docker-compose をインストール・・・するのですが、ここでもドキュメントのまま実行すると依存関係ライブラリが足りないというエラーになってしまいます。そのためまずは依存ライブラリを導入しておきます:
# yum install python-devel
# yum install gcc libffi-devel openssl-devel
# pip install glob2

改めて pip で docker-compose をインストールします。ここでもドキュメントそのままの指定だとエラーになってしまうので、バージョン 1.13.0 を明示してインストールします:
# pip install docker-compose==1.13.0

これで docker および docker-compose が LinuxONE 環境にインストールできました:
# docker -v
Docker version 17.05.0-ce, build 89658be

# docker-compose -v
docker-compose version 1.13.0, build 1719ceb

2019052702


【WordPress の導入】
では導入した docker と docker-compose を使ってコンテンツ管理システムである WordPress を導入してみます。

テキストエディタ(vi とか)を使うなどして、docker-compose.yml というファイルを以下の内容で作成して保存します:
version: '2'

services:

  wordpress:
    image: s390x/wordpress
    ports:
      - 80:80
    environment:
      WORDPRESS_DB_PASSWORD: example

  mysql:
    image: brunswickheads/mariadb-5.5-s390x
    environment:
      MYSQL_ROOT_PASSWORD: example

このファイルは docker-compose 向けの定義ファイルで wordpress と mysql という2つのコンテナ環境を定義しています。wordpress は PHP, Apache HTTPD, および WordPress が含まれる s390x 向けのイメージで 80 番ポートで HTTP リクエストを待ち受けます。また mysql は MySQL(正確には mariaDB)が含まれる s390x 向けイメージです。これら2つのイメージから2コンテナ環境を作り出して WordPress として挙動するようにしています。

では、docker-compose と、この docker-compose.yml ファイルを使って docker コンテナを起動します:
# docker-compose up -d

(必要に応じて)イメージをダウンロードし、イメージからコンテナが作られて起動します。プロンプトが戻ってきたら、docker ps コマンドを実行して wordpress と mariadb の2つのコンテナが起動していることを確認します:
# docker ps
CONTAINER ID        IMAGE                              COMMAND                  CREATED             STATUS              PORTS                NAMES
65af9dfa6ee9        s390x/wordpress                    "docker-entrypoint..."   3 hours ago         Up 3 hours          0.0.0.0:80->80/tcp   dockers_wordpress_1
3eb78f3ef1c1        brunswickheads/mariadb-5.5-s390x   "/docker-entrypoin..."   3 hours ago         Up 3 hours          3306/tcp             dockers_mysql_1

起動が確認できたらウェブブラウザから(LinuxONE 環境の) IP アドレスを指定してアクセスします(http://xxx.xxx.xxx.xxx/)。以下のような WordPress の環境設定画面になれば成功です:
2019052801


言語やユーザーID、パスワードなどの設定が完了すると管理画面にログインできるようになりました:
2019052802


この時点でユーザーページにもアクセス可能です:
2019052803


とりあえずメインフレーム上の Linux に docker & docker-compose 環境を構築して WordPress を導入することができました!


この記事の続きです:
"Play with Docker" で遊ぶ(1)

前回は Play with Docker(以下 "PwD")というサービスを使うことで Docker をインストールすることなく、ブラウザだけで docker コマンドを体験できることを紹介しました。今回はこのサービスの標準機能として提供されている Docker Swarm を使ったクラスタリング環境構築の手順を確認してみます。

Docker Swarm は Docker に対応したネイティブ&軽量なクラスタリング用のツールです。Docker の標準機能の一部として提供されているので、Kubernetes のように Docker 導入の後から追加でインストールする必要なく(Swarm モードに切り替えるだけで)利用できます。

では早速 PwD で Docker Swarm を使ってみましょう。まずは前回同様、Docker Hub のアカウントで PwD にログインします:
2019041901


PwD のダッシュボード画面が表示されます。まずは前回同様に "+ ADD NEW INSTANCE" をクリックして Docker インスタンスを追加します:
2019042101


"node1" という名称の Docker ノードインスタンスが追加され、操作するためのコンソールも表示されました。ここまでは前回と同じです:
2019042102


今回はクラスタリング環境を構築したいので、更に2つの Docker ノードインスタンスを追加します(合計3つにします)。あともう2回 "+ ADD NEW INSTANCE" をクリックして、"node2" と "node3" を追加します。こんな感じで Docker ノードを気軽に増やせるのは本当に便利です。。
2019042103


この時点で3つの Docker が(独立した状態で)準備できました。ではこの3つの Docker ノードを使ってクラスタリング環境を構築します。今回は node1 を管理ノード、node2 と node3 をワーカーノードとするクラスタリング環境とします。

まずは管理ノードを準備します。node1 を選択して、node1 のコンソールに以下のコマンドを入力します:
$ docker swarm init --advertise-addr eth0

2019042104


成功すると出力結果に
$ docker swarm join --token XXXXXX...
という内容が表示されます。これはワーカーノードとなるノードで入力すべきコマンドです。これで管理ノードの準備はできました。


では次にワーカーノードをこの管理ノードに接続します。先程の管理ノードでのコマンド出力結果の "docker swarm join --token XXXXXX..." 部分をそのまま node2 のコンソールにコピー&ペーストして実行します:
2019042105


"This node joined a swarm as a worker." というメッセージが表示されれば正しくワーカーノードとしてクラスタリングに追加し、初期化できたことになります。

同様に node3 でも同じコマンドを実行して、ワーカーノードとしてクラスタリングに追加します:
2019042106


これで3つの Docker インスタンスノードによるクラスタリング環境が構築できているはずです。念の為、node1 ノードで以下のコマンドを実行します:
$ docker node ls

実行結果を見ると、node1, node2, node3 の3つのノードがクラスタリングを構成している様子が表示され、かつ node1 が "Leader" (管理ノード)と表示されているはずです:2019042107



では、このクラスタリング環境でアプリケーションを実行してみます。なお原則的には以下のコマンドはすべて管理ノードである node1 ノードのコンソールを使います。

改めて node1 ノードで nginx のイメージを使って 80 番ポートで、1インスタンスで、"web" という名前でサービスを作成します:
$ docker service create --replicas 1 --name web -p 80:80 nginx

初回はイメージのダウンロードもあるので少し時間がかかりますが、以下のようなメッセージが表示され、正しくサービスが作成されます:
2019042108


動作確認する前に、この時点でサービスの様子を確認します。node1 ノードで以下のコマンドを実行します:
$ docker service ls

"web" というサービスがレプリカ1つで定義され、そのうちの1つが動いている形で 80 番ポートで作成されている様子が確認できます:
2019042109


実際に動作確認してみます。80 番ポートで公開されているので、curl コマンドを使って以下のコマンドを実行します(このコマンドは node2 や node3 で実行しても確認できます):
$ curl http://localhost/

Nginx 標準のトップページの HTML が表示されます。正しくサービスが動いている様子が確認できました:
2019042110


では、現在1インスタンスで稼働しているこのサービスを複数インスタンスとなるように node1 でスケールアウトさせてみます:
$ docker service scale web=3

3インスタンスで稼働するように指定しました。少し待ちますが、3つのインスタンスが "running" となることを確認します:
2019042101


改めてnode1 でレプリカ数を確認します:
$ docker service ls

結果、以下のように3つのレプリカが定義されており、そのうちの3つが動いている様子が確認できます:
2019042102


最後に作成したサービス(web)を削除する方法を紹介しておきます。node1 で以下のコマンドを実行します:
$ docker service rm web

これで web サービスはクラスタリング環境から削除されました:
2019042103



PwD 環境を使ったクラスタリング環境構築と、簡単なサービス作成&スケールアウト&削除といった手順を紹介しました。 通常、同じことを行うには3台のマシンを用意した上で、それぞれに Docker をインストールしておかないとこのような動作確認はできないのですが、PwD を使うと Docker 導入の手順を省略することができる上、全ての操作を1つのブラウザ画面上で行うことができるという点が勉強しやすいと感じました。




"Play with Docker" (以下、"PwD")というサービスを使ってみました:
https://labs.play-with-docker.com/


2019041901


一言でいうと「ブラウザだけで docker コマンドを体験できるサービス」です。普通、Docker を使うには(当然ですが)Docker 環境が必要です。自分でインストールすることもできますし、各種クラウドサービスで提供されているものを使ってもいいです。自分でインストールせずにクラウドサービスの Docker サービスを利用する場合は別途手元のマシンに docker クライアントを導入&セットアップして使うことになります。一度セットアップしてしまえばいい話ではありますが、慣れてなかったり「そもそも Docker って何?」という人がこれから勉強するために用意することを考えると「ちと面倒」です。

この PwD は、そんな Docker のセットアップ手順をすっ飛ばして Docker を使うことができるサービスです。具体的には Docker Hub のアカウントを取得し、そのアカウントでログインするとブラウザ上で docker 他の各種コマンドが使えるターミナルが提供され、裏で動いている Docker エンジンや、オーケストレーション環境である Docker Swarm エンジンを利用することができる、というものです。

利用するにはブラウザで PwD サイトへアクセスし、"Login" と書かれたボタンをクリックして Docker Hub のアカウントでログインします(所有していない場合はここで作成してログイン):
2019041901


ログイン後に改めて同ページを参照し、今度は "Start" ボタンをクリックしてサービス開始です:
2019041902


PwD サービス画面に切り替わります。画面左上にこのセッションで使える残り時間が表示されています。カウントダウンも始まっていますが、約4時間使える、ということみたいです。この時点ではまだdocker インスタンスが1つも起動していません。まずは1つ使ってみましょう。"+ ADD NEW INSTANCE" と書かれた箇所をクリックします:
2019041903


"node1" という名称のインスタンスが追加されました。同時に画面右にコンソールが現れて、プロンプト状態になります。すでに docker エンジンは起動している状態になっていて、ここから docker コマンドなどを実行することができる状態になってます。簡単すぎる・・・:
2019041904


試しに "$ docker version" を実行してみました。サーバー側もちゃんと動いてそうです:
2019041905


では深く考えずに nginx のイメージからコンテナを1つ起動してみます:
$ docker pull nginx

$ docker run -d -p 80:80 nginx


そして起動中であろう nginx にアクセスしてみます:
$ curl http://localhost/

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

  :

</html>

普通に使えてますね、これはすごい!

ほぼ準備することなく Docker コマンドが使えて、コンテナの実行もできて、勉強目的であればとてもいい環境だと思いました。

次回はこの PwD で(使えることになっている)オーケストレーション環境である Docker Swarm を使ってみる予定です。




きっかけはこのツイートでも紹介した、豊島屋の鳩サブレ缶がちょうどラズベリーパイを4つ格納できるような仕切りになっていることに気付いたことでした:
20190117


面白そうなので、本当にラズパイのケースにしてみよう、それもせっかくなのでこの鳩サブレ缶の中だけでクラスタリング環境を作ることに挑戦してみよう、と思いたちました。ちなみに私自身はクラスタ化とか専門ではなく、あまり得意な方ではないです。思いついた時点では構築方法として Docker Swarm か、Kubernetes か、まあその辺りが動けばいいな、くらいに考えていました。。

当初は「さてとりあえずラズパイを4台買って・・」と思っていましたが、冷静に考えるとスイッチングハブとか、USBハブとか、電源周りとか、ラズパイ本体以外でもそこそこのサイズの機器を収納する必要がありそうだと気づきました。というわけで、それらをどこか1つにまとめるとして、ラズパイ本体は3台体制で行けるかな・・・ という想定でお買い物しました:
IMG_3782


購入したモノリスト:
買ったモノ個数目的
Raspberry Pi 3 Model B3クラスタノードになるホスト
マイクロ USB ケーブル上記ラズパイの電源ケーブル
マイクロSDカード(64GB)上記ラズパイのストレージ
ラズパイケースプラスチックの仕切りの上にラズパイ本体を直接載せるのは熱的にまずいかと思ったので・・・
LANケーブル3台のラズパイを同一ネットワークに接続(結局、今回は使わず※)
スイッチングハブ1LANケーブルのハブ(結局、今回は使わず※)
USB ハブ電源ケーブルのハブ(結局、今回は使わず※)


※今回は結局無線 LAN で接続することにしたので有線の LAN ケーブルとハブを使わずに構築しました。また USB ハブは購入したのですが、この USB ハブ1つに3台のラズパイを接続すると電流量が足りませんでした。というわけで別途 USB からの電源変換プラグ3つと、テーブルタップ1つを買い足しています。

上記に含まれていないものとして、マイクロ SD カードにイメージを書き込むための Windows PC と、マイクロ SD カードを読み書きするための USB アダプタ、USB -> 電源プラグの変換アダプタ、各ホストでネットワークが有効になるまでの操作用に LCD モニタ、HDMI ケーブル、USB キーボードと USB マウスを使います(これらは所有していたものをそのまま使います)。加えてケースとなる 18 枚入りの鳩サブレー缶を用意しました。

また構築する環境は最近流行り(遅い?)の Kubernetes 、にしたかったのですが、訳あって Docker Swarm にしました。コンテナ・オーケストレーションとしてはほぼデファクトスタンダートになった Kubernetes を選びたかったのですが、とりあえず 2019/01/21 時点ではマスターノードを初期化する kubeadm init コマンドを実行した際に再現率 100% で Timeout エラーになってしまうようでした。


どうもこの Issue に近い現象だと思っています:
2019012101


ただ Issue そのものは Closed になっていて、でもスレッドを見ていると本当に治っているのかなんとも微妙・・ 一方で成功例も報告されているのでラズパイで発生する環境依存問題なのか、タイミングが悪かったのか・・・ なんとも言えないのですが、仮に Kubernetes の障害であったとしてもその修正を待つのも変なので、Docker Swarm によるクラスタリング環境構築を優先することに決めました。

というわけで、改めて3台のラズパイを使った Docker Swarm 環境の構築を目標に作業を進めてみます:
2019012200



【構成図】
このような最終型を目指すことにします:
2018012201

raspi001, raspi002, raspi003 の3台のラズベリーパイを Docker Swarm でクラスタリングします。raspi001 を管理ノード、raspi002 と raspi003 をワーカーノードとします。



【ラズパイノードの準備】
Docker Swarm 環境の核となる3台のノードをラズパイで作ります。前提として最新版の Raspbian OS をマイクロ SD カードに書き込んで起動し、初回起動時のセットアップは3台ぶん済んでいるものとします。また SSH も有効にしておいてください。そして以下の手順を3台それぞれに対して行います。

【ホスト名の変更】
今回は3台のラズパイに raspi001, raspi002, raspi003 という3つの名前をそれぞれ付与して使いますこのため、まずは各ラズパイのホスト名をそれぞれ変更します。
$ sudo vi /etc/hostname

raspberrypiraspi001  raspberrypi をホスト名に変更して保存


また raspi001, raspi002, raspi003 の名前でアクセスできるよう、/etc/hosts も変更しておきます(DNS などが有効であればそちらで対応いただくのがいいと思います):
$ sudo vi /etc/hosts

127.0.1.1       raspberrypiraspi001  raspberrypi をホスト名に変更

192.168.10.101  raspi001
192.168.10.102  raspi002
192.168.10.103  raspi003   raspi00X の名前でアクセスできるよう IP アドレスを指定して追加し保存

【SSH 鍵の共有】
この3台のラズパイ間ではパスワードなしで SSH 接続ができるように SSH 鍵を共有しておきます:
$ ssh-keygen -t rsa
$ ssh-copy-id raspi001
$ ssh-copy-id raspi002
$ ssh-copy-id raspi003

【Docker のインストール】
こちらで紹介した手順でラズパイに Docker をインストールします:
$ curl -sSL https://get.docker.com | sh

$ sudo usermod -aG docker pi

(このコマンドの後、一度ログアウトして再ログインする)

以上、ここまでの手順は3台のラズパイ全てで共通に行っておく必要があります。ちと面倒ですが、全てのラズパイに Docker をインストールするところまで実行しておきます。


【管理ノードの作成】
ここからは3台のラズパイの役割ごとに作業が変わる部分になります。まずは管理ノードを作成します。raspi001 において、自分のアドレスを指定して以下のコマンドを実行します:
$ docker swarm init --advertise-addr 192.168.10.101

Swarm initialized: current node (xenxp2w34x5dhvtdmq0ndwolk) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join --token SWMTKN-1-0dg4im1kvb41odjj9zmhwug0bcvg6n8tt0d8548jxho5cp8cvo-df89pmegbdf4a3vy37apftv8r 192.168.10.101:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.


↑コマンドが成功すると青字のような出力になります。この中の太字部分(docker swarm join で始まる行)は後でワーカーノードで実行することになるコマンドなのでコピペできるようにしておきましょう。


【ワーカーノードの接続】
次にワーカーノード側(raspi002, raspi003)から管理ノードに接続します。上記の管理ノード作成時に実行したコマンドの実行結果をそのまま入力して実行します:
$ docker swarm join --token SWMTKN-1-0dg4im1kvb41odjj9zmhwug0bcvg6n8tt0d8548jxho5cp8cvo-df89pmegbdf4a3vy37apftv8r 192.168.1.153:2377

コマンドの実行が成功すると "This node joined a swarm as a worker." といったメッセージが表示されます。これを raspi002 と raspi003 の両方で(4台以上で構成する場合は全てのワーカーノードで)実行します。


【ノードの状態を確認】
ここまでの作業でこの環境が作れています:

2018012201


ノードの状態を確認してみます。raspi001 から以下のコマンドを実行します:
2019012202

$ docker node ls
ID                            HOSTNAME            STATUS              AVAILABILITY        MANAGER STATUS      ENGINE VERSION
xenxp2w34x5dhvtdmq0ndwolk *   raspi001            Ready               Active              Leader              18.09.0
hztpov7qya7y99m4oifx73ugt     raspi002            Ready               Active                                  18.09.0
wksx0mlyu9wsilk9c4jigvcib     raspi003            Ready               Active                                  18.09.0

実行結果↑の青字部分をみると raspi001, raspi002, raspi003 がリストされ、全て Active になっています。また raspi001 の MANAGER STATUS が Leader とマークされており、ここが管理ノードになっていることが確認できました。


あとはこの3つのラズパイと電源ケーブル等をつなげて鳩サブレー缶に押し込みます:
IMG_3802


鳩サブレ版の(?) docker swarm 環境が完成しました!
IMG_3800



(参考)
https://blog.ruanbekker.com/blog/2018/10/23/setting-up-a-docker-swarm-cluster-on-3-raspberrypi-nodes/


このページのトップヘ