前回ビルドに挑戦したHyperledger Indyですが引き続き動作確認を行ってまいります。というか、ユースケースがいまいちピンと来ないので、懲りずに古いサンプルを動かしてみました。
紆余曲折ありましたがなんとか動いたので手順などの解説をいたします。(めちゃくちゃ大変だった。)
まず、修正済みのソースはこちらです。
手っ取り早く動かしたい方、DockerインストールしたUbuntuで上記リポジトリをcloneしてReadmeの手順に従っていただければOKです!
以下では通常の動作手順について、順を追って解説します。
1. コンテナのビルド
まず、Rustでのindyソースをコンテナ内でビルドして、デモに必要な各種のコンテナを作成します。
こちらの修正済みのプロジェクト からソースをクローンしておきます。以下では、~/indy-ssivc-tutorial
にクローン済みとして説明いたします。
また、docker コマンドは sudo
付きで動かす環境であるとして説明します。
1-1. indy コンテナのビルド
以下のコマンドで、indy 本体のネットワークを構成する docker コンテナをビルドします。
$ cd ~/indy-ssivc-tutorial/von-network
$ sudo ./manage build
1-2. API コンテナのビルド
以下のコマンドで indy とアクセスする API や管理ツールなどのコンテナ群をビルドします。
$ cd ~/indy-ssivc-tutorial/TheOrgBook/docker
$ sudo ./manage.sh build
1-3. デモアプリコンテナのビルド
以下のコマンドで indy のデモを行う Web アプリ用のコンテナ群をビルドします。
$ cd ~/indy-ssivc-tutorial/permitify/docker
$ sudo ./manage build
このあたりになるとディスクスペースやメモリなど逼迫してくるかもしれません。不要な docker イメージは削除して軽くしておいたほうがいいかもしれません。
2. 起動
無事に docker コンテナがビルドできたら同様の順番でコンテナを起動していきます。
2-1. indy ネットワークの起動
以下のコマンドで indy のテストネットワークを起動します。
$ cd ~/indy-ssivc-tutorial/von-network
$ sudo ./manage start
これでindy用のコンテナがいくつか起動します。
2-2. API コンテナ群の起動
続いて indy に直接接続する API 用のコンテナ群を起動します。
新しいコンソールを開き、
$ cd ~/indy-ssivc-tutorial/TheOrgBook/docker
$ sudo ./manage.sh start
で、API用のコンテナがいくつか起動します。
2-2-1. 起動するサイト・サービス
この時点でいくつかのサイトが立ち上がります。
- ダッシュボード Web UI ・・・ http://localhost:9000
- チュートリアルサイト ・・・ http://localhost:8080
- Swagger ・・・ http://localhost:8081
- Solr ・・・ http://localhost:8983
- PostgreSQL・・・tcp://localhost:5432
Solrはまぁ、おまけみたいなものです。
2-3. デモアプリコンテナ群の起動
以下のコマンドでデモアプリ用のコンテナ群を起動します。
新しいコンソールを開き、
$ cd ~/indy-ssivc-tutorial/permitify/docker
$ sudo ./manage start all APPLICATION_URL=http://192.168.1.10 THE_ORG_BOOK_APP_URL=http://192.168.1.10:8080
で、OKです。
ここで重要なのが、APPLICATION_URL
で渡しているのが、デモアプリ用のコンテナ群が立ち上がるホストのIPアドレス、THE_ORG_BOOK_APP_URL
で渡しているのが、上記のAPI用コンテナ群が立ち上がるホストのアドレス(ポート番号込み)です。
今回は1台のDockerホスト上で全てのコンテナを動かすので同一のIPアドレスとなっています。
また、この変数を設定せずに単に ./manage start all
と実行した場合は、ローカルホストからのみのアクセス が有効になります。
2-3-1. 起動するサイト・サービス
ここでデモ用のサイト群がわーっと立ち上がります。
- Gov ID ・・・ http://localhost:5000
- Fabor 大学 ・・・ http://localhost:5006
- Acme 就職 ・・・ http://localhost:5007
- Acme 給与受け取り ・・・ http://localhost:5008
- Thrift 銀行 ・・・ http://localhost:5009
上記の手順で APPLICATION_URL
を使用している場合は、localhostの代わりにそのIPアドレスでアクセス可能です。
3. コンテナの停止
各コンソールで Ctrl+C
でプロセスを落とせば Graceful Shutdown
となります。
4. 使用済みの container と volume の削除
前回の記事でも注意として記載しましたが、indyはブロックチェーンのプロダクトでありますので一度、動かしてブロックが生成されてしまうと後戻りができません。
テストネットを止めて再起動、ということが簡単にできませんので、デモサイトを落とした後はこの削除の手順が必須です。
4-1. indy 用コンテナの削除
以下のコマンドで削除を行います。
$ cd ~/indy-ssivc-tutorial/von-network
$ sudo ./manage rm
4-2. API用コンテナの削除
同様に以下のコマンドで使用済みコンテナの削除を行います。
$ cd ~/indy-ssivc-tutorial/TheOrgBook/docker
$ sudo ./manage.sh rm
4-3. デモサイト用コンテナの削除
同様に以下の手順で削除します。
$ cd ~/indy-ssivc-tutorial/permitify/docker
$ sudo ./manage rm
基本的な動作方法は以上です。
4-4. 動かし方
実際のデモサイトのアクセス方法などはこちらをご覧ください。
また、ここでどんなことを実現したいのか?については以下の記事でわかりやすく解説していただいてます。
これらのデモサイトでどんなことができるのか、できるようにしたいのか、はお分かりいただけたかと思います。
5. どうやって動かしたのか
ここからが一応の本題です。このちょい古めのサンプル
は、最新の Rust ではコンパイルが通りません。
また、API用サーバーやデモサイトなどのコードが大量にあるため、libindy を最新のものにしてコンパイル通ればオK☆、なんてことにはなりません。
当時の AS IS で動作確認が必要なのであります。
そんなわけで今回の古めのサンプル(といっても一昨年だけど。。。)をちゃんと動作させるに当たって、どうやって手当てをしたか、について述べていきたいと思います。
1. Rustのビルド
まず、もっとも困難だったのが どのバージョンのRustならビルドが通るのか
、そして同時に 全体がよろしく収まってくれるか
です。上記でも述べましたが各種パッケージを最新にすれば現状のRustでビルドが通るのは前回のトライで確認済みです。しかし、参照するコードが大量にあるためコア部分のみバージョンアップする、なんてことはとてもできないのです。
というわけで、**当時の libindy はどうやってビルドしていたの?**をどうやって調べたか、ですが、まず cargo のパッケージを調べました。
以下が、例えばですが、indy 1.6.7 の登録情報です。
https://crates.io/crates/indy/1.6.7
当たり前ですがちゃんとビルドされてcargoに登録されています。・・・どうやって?
でも、単にビルドして、アップロードしてるわけじゃないよね・・・?
たぶん jenkins か circle-ci とかでUTは通してるはずでしょう・・・というわけで・・・
はい、libindy が ci でテストを実施している流れは ubuntu.dockerfile
に書いてあります。そしてlibindyをビルドするrustをインストールする箇所で・・・
...
USER indy
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.36.0
ENV PATH /home/indy/.cargo/bin:$PATH
...
はい、Rustのバージョン指定してますね!つまり、その当時の ubuntu.dockerfile を見ればいい というわけですね!
そして 当時
とはいつなのか?というと・・・indy-ssivc-tutorial/von-network/Dockerfile
に以下の記述があります。
...
RUN git clone https://github.com/hyperledger/indy-sdk.git
WORKDIR /home/indy/indy-sdk/libindy
RUN git fetch
RUN git checkout 778a38d92234080bb77c6dd469a8ff298d9b7154
...
この checkout 778a38d92234080bb77c6dd469a8ff298d9b7154
のハッシュ値を github のURLに貼り付けるとコミットログを見ることができます。具体的には以下のURLで確認できます。
6 Mar 2018
のコミットであることが確認できます。この当時の ubuntu.dockerfile を見ればいいというわけですね!いや、大変だった!w
というわけでubuntu.dockerfile
のコミットログを確認してみましょう。
このリストから2018.03.06以前の最新版を探してくればOK、ということになります。
というわけで・・・
この 26 Feb 2018
のコミット近辺の rust のバージョンが分かればいいんですね~というわけで、ubuntu.dockerfile
を見てみますと・・・
...
ENV RUST_ARCHIVE=rust-1.21.0-x86_64-unknown-linux-gnu.tar.gz
ENV RUST_DOWNLOAD_URL=https://static.rust-lang.org/dist/$RUST_ARCHIVE
...
上記の定義で 1.21.0
をダウンロードしてますね。。。う~ん、tar.gz をそのままダウンロードしてるのはちょっとなぁ。。。と、次のコミットを確認します。
ここでの ubuntu.dockerfile
を見てみますと・・・
...
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.21.0
...
rustup
でバージョン指定する方法が書かれてますね!これっぽい!!
いや、実際には 1.21.0
ではダメで、次の "Apr 23, 2018" の "Update rust to 1.25.0." が微妙にダメ(ビルドは通ったけど、サイト動かすとダメ)で、次の "May 30, 2018" の "Increment Rust version to 1.26.0" でうまくいくようになりました。
これで Rust のコンパイルエラーはなくなりました。すでに3日ほど経過してます。
2. 参照パッケージのバージョン
Dockerfile 内で apt install
で indy_plenum
などをインストールしてますが、リポジトリサイトの "deb https://repo.sovrin.org/deb xenial $indy_stream"
からご指定のバージョンは既に削除されているのですね・・・
というわけで現在登録されているバージョンの最古のものから順にちゃんとバージョン間の依存性の整合性がとれているものを割と総当たりで試してみました。とは言え、古いもの順ではうまくいく組み合わせはすぐ見つかりました。
結果、indy_plenum_ver=1.2.242
、indy_node_ver=1.2.301
が適しているようです。
3. tob-web のビルドが通らない
tob-web/package.json
に以下のような参照があります。
...
"localize-router": "git+https://github.com/cywolf/localize-router.git",
...
これは最新版ではコケます。当時の依存関係とは変わっているのですから当然です。(っていうかリポジトリ直接はやめてw)
そして以下の issue を発見しました。
やっぱりビルド通らないよね?と思っていたら・・・"バージョン 1.0.1
に直したよ" というコメントがあったので、その通りにいたしました。
あら不思議、ビルドが通っちゃう・・・
4. permitify のビルドが通らない。
このIndyのサンプルプログラムは permitify など Django ベースのWebサイトを多数、起動するのですが、Django の起動がうまくいったか失敗したかがぱっと見ではわからないので、ちょっとハマりました。
コンテナではうまくいっているように見えて、コンテナの中に入って psするとpyhton のプロセスもあるけど、ssコマンドで確認するとポートをlistenしていない。。。というわけで manage.py start
とかやってみると初めてエラーメッセージがダラーっと出てて来る、そんな状態でした。Pythonプロセスが無駄に生きてるからやっかいなんですよね~。
とりあえず、エラーメッセージが出てくれればもう後はググって対応だけなのでなんとかなりました。
依存関係のバージョンを以下のように修正しただけです。
- attr : 17.3.0 -> 17.4.0
- von-agent: 0.5.0 -> 0.5.2
これだけで半日かかってますけど。
5. localhost からしか動作しない
これはだいぶ困りました。実際の手順では http://localhost:8080 のチュートリアルサイトから http://localhsot:500x の各サイトへリンクが表示されています。
そしてそれが localhost
決め打ちなんですね。。。
いや、それはどうなのよ~?とソース(Angular) を見てみましたが、外のAPI(http://localhost:8081)から取得するだけで Angular側では全然、決めていない・・・オーマイ。。。となってしまったわけです。
いろいろ見てみると、docker-compose.ymlで以下のような記述があります。
...
TEMPLATE_NAME: faber_college
THE_ORG_BOOK_API_URL: ${THE_ORG_BOOK_API_URL}
THE_ORG_BOOK_APP_URL: ${THE_ORG_BOOK_APP_URL}
APPLICATION_IP: 0.0.0.0
APPLICATION_PORT: 8080
APPLICATION_URL: ${APPLICATION_URL}:5006
...
これはなんか、${APPLICATION_URL}
は自分のサイトのアドレスで ${THE_ORG_BOOK_APP_URL}
は http://localhost:8080 に戻る時のURLなんじゃないの?っぽいよね??という勘と、manage
スクリプトで
...
configureEnvironment () {
for arg in $@; do
case "$arg" in
*=*)
export ${arg}
;;
esac
done
export APPLICATION_URL=${APPLICATION_URL-http://localhost}
# export THE_ORG_BOOK_API_URL=${THE_ORG_BOOK_API_URL-https://django-devex-von-dev.pathfinder.gov.bc.ca/api/v1}
# export THE_ORG_BOOK_APP_URL=${THE_ORG_BOOK_APP_URL-https://devex-von-dev.pathfinder.gov.bc.ca}
export THE_ORG_BOOK_API_URL="http://$DOCKERHOST:8081/api/v1"
export THE_ORG_BOOK_APP_URL="http://$DOCKERHOST:8080"
export TOB_INDY_SEED=the_org_book_issuer_000000000000
export LEDGER_URL=http://von-web:8000
}
...
ここで、'=' が含まれていたら export
しているので変数渡せるようにしてくれているんだということと、APPLICATION_URL
、THE_ORG_BOOK_APP_URL
のアドレスがlocalhostとdockerのhostでlocalhostじゃないとダメな理由がはっきりしましたね。localhost
は100歩譲って外から見たIPでも動くと思いますが、Docker host
は完全に docker が動いているホストのdockerネットワーク上のIPアドレスなのでそのマシンから見ないとこのアドレスは解決できないでしょう、ということですね。たぶん。
そんなわけで THE_ORG_BOOK_APP_URL
はいきなり$DOCKERHOST
を使わずに、外からちゃんと指定できる余地を残しておけばよいのです。以下のように。
...
export THE_ORG_BOOK_APP_URL=${THE_ORG_BOOK_APP_URL-http://$DOCKERHOST:8080}
...
で、起動時に外から見えるIPアドレスを教えてあげればOKなわけです。きっと。
$ ./manage start all APPLICATION_URL=http://192.168.1.10 THE_ORG_BOOK_APP_URL=http://192.168.1.10:8080
この指定がうまく動いたので、Indyデモサイトは外部から http://192.168.1.10:8080 でめでたくアクセスできるようになりました。
いったん、以上といたします。いや~長かった。。。