Blockchain(Hyperledger)のローカル環境を作ってみた(Fabric Starter Kit) ★古い情報です(2017/12)


<Font color="red">【注】2017/6現在、HyperLedger Fabricは1.0を目指して動いていますので当記事の内容は古いものです。以下は保存目的でそのまま残します</font>
<Font color="red">
2017/12 V1.xの環境向けに記事 [動画コース 「Zero to Blockchain」(Hyperledger Fabric) に、ローカル開発環境を簡単に作れるシェルがあったので試してみた](https://qiita.com/ishida330/items/8f3e672596ffd0ab1142) を書きましたので、これからお取り組みされる方はそちらをご参照ください。</font>

こんにちわ！石田です。最近Blockchain界隈、盛り上がっていますね。Linux FoundationでのオープンソースのBlockchain実装であるHyperledger Fabricもv0.6になり(執筆時点:2016/10月)、Github上でのコードやドキュメントなどのリソースが充実してきています。この「Fabric」のドキュメントに自分のPC上でdockerを使って簡単にFabricの開発環境を作って試せる「Fabric Starter Kit」が紹介されていました。私もやってみましたので、手順を書いておきます。とても簡単でしたので、ご興味のある方はお試しください。( IBMのBluemix上でも[IBM Blochchain](http://www.ibm.com/blockchain/)というサービス名でHyperledger fabricの環境を年初よりご提供中(※)です。ただ、これ、取っ掛かりやデモにはいいのですが、PaaSのためか中の基盤的な動きがいまひとつよくわかりません。そういう方にはこのStarter Kitでご自分で環境を作ってみるとよろしいかと。）
※ ベータなので記事執筆時点では無償。適宜Fabricのアップデートを反映しており、現在は0.5相当。

- ネタ元の文書は[Fabric Starter Kit](https://hyperledger-fabric.readthedocs.io/en/v0.6/starter/fabric-starter-kit.html)です
- 私はWindows 7 PC上のVMWare Workstation上でubuntu 16.04を動かしましたが、ubuntuより下の層はどのような構成でもいいはずです
- 以下、肝となるコマンド操作を順を追って記載します
 
# ゴール
完成すると、こんな環境が手に入ります。作業時間はネットワークの速度次第ですが、30分-数時間でしょうか。
![image](https://qiita-image-store.s3.amazonaws.com/0/108535/a7dcadea-9ab3-218f-aaae-9fe0d38bd5ef.png)

- membersrvc/peer/starterの３つのDockerコンテナがcomposeで連携
- サンプル(go)のチェーンコードもデプロイ可能

# 手順サマリー
1.  (option) VMWare上にubuntuをインストール
2.  (option) ubuntuの環境設定
3.  dockerのインストール
4.  docker-composeのインストール
5.  Fabric Starter Kitのインストール
6.   Fabric Starter Kitを動かしてみる

# 具体的な手順

1と2は「私はこうやった」というだけで、皆様のお好みでいいと思います。基本、ubuntuでネットワーク＆シェルが使える環境があればいいはずです。以下、コマンドのコピペで作業が進められるように書きます。

### 1. (option) VMWare上にubuntu環境を作成
- [Ubuntu 16.04.1 LTS (Xenial Xerus)](http://releases.ubuntu.com/16.04/)より64-bit PC (AMD64) server imageのisoをダウンロード　 (ubuntuのエディション、私はserverを選択しましたが、desktopでもいいでしょう)
- VMWare上でisoを指定して新規に仮想マシンを作成(メモリ4GB)　～操作は割愛します

### 2. (option) ubuntuの環境設定

以下はオプションですが、私は勉強目的で自分のPC上で動かすだけなので、今はセキュリティは考慮不要＆シェル操作は [SuperPutty](https://code.google.com/archive/p/superputty/downloads)を使いたかったので 以下の設定をしました。あとは何もしていません。
- sshで楽をしたいので、Windows7のhostsに、下記で入手できるIPアドレスと適当なホスト名を設定

```bash:
ifconfig -a
```

- rootのパスワードを設定(デフォでは未設定)してsu

```bash:
sudo passwd root
su -
```

- OpenSSHのインストール

```bash:
apt-get install openssh-server
```

- rootをSSHでログイン可能に
/etc/ssh/sshd_configのPermitRootLoginを**yes**に変更→リスタート

```bash:/etc/ssh/sshd_config
# Authentication:
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
```

```bash:
service sshd restart
```

以下、rootでsshでログインした環境で操作します。rootでない方はsudoで操作してください。

### 3.Dockerのインストール
参考文献: [Docker-Ubuntu](https://docs.docker.com/engine/installation/linux/ubuntulinux/)
まずは前提となるパッケージをインストール

```bash:
apt-get update
apt-get install apt-transport-https ca-certificates
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
```

/etc/apt/sources.list.d/docker.listにリポジトリーを登録。同ファイルはubuntu 16.04 インストール直後は存在しないのでviで開いて下記1行だけ書いて保存します。(この記述内容はubuntuのバージョンにより異なりますので16.04以外の時は上記参考文献をご参照ください）

```bash:/etc/apt/sources.list.d/docker.list
deb https://apt.dockerproject.org/repo ubuntu-xenial main
```

更に環境を整えます。

```bash:
apt-get update
apt-get purge lxc-docker
apt-cache policy docker-engine
apt-get update
apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual
```

ここまで終わったら、いよいよDockerのインストールです

```bash:
apt-get install docker-engine
```

導入後の確認

```shell-session:
root@ubuntu:~# docker -v
Docker version 1.12.2, build bb80604
root@ubuntu:~# service docker start
root@ubuntu:~# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c04b14da8d14: Already exists
Digest: sha256:0256e8a36e2070f7bf2d0b0763dbabdd67798512411de4cdcf9431a1feb60fd9
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
 https://hub.docker.com

For more examples and ideas, visit:
 https://docs.docker.com/engine/userguide/
```

### 4.Docker-composeのインストール
参考文献: [Docker Compose - インストール](http://qiita.com/zembutsu/items/dd2209a663cae37dfa81)
curlをインストールしてから、docker-composeをインストールします

```bash:
apt-get install curl
curl -L https://github.com/docker/compose/releases/download/1.8.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
```

確認

```bash:
root@ubuntu:~# docker-compose -v
docker-compose version 1.8.1, build 878cff1
```

### 5. Fabric Starter Kitのインストール
参考文献: [Fabric Starter Kit](https://hyperledger-fabric.readthedocs.io/en/v0.6/starter/fabric-starter-kit.html)
ここまでで前提となるdocker/docker-compose基盤が整いました。ここからはFabric Starter Kitです。といっても環境はdocker化されているので要はpullしてbuildするだけ、であり、とても簡単です。まず、定義ファイルであるdocker-compose.yamlとアプリ環境(starter)のためのDockefileをダウンロードします。(アプリ環境は自分でも変更できるように別になっているそうです）あとはビルド。しばしお待ちを。

```bash:
curl -o docker-compose.yml https://raw.githubusercontent.com/hyperledger/fabric/master/examples/sdk/node/docker-compose.yml
curl -o Dockerfile https://raw.githubusercontent.com/hyperledger/fabric/master/examples/sdk/node/Dockerfile
docker build -t hyperledger/fabric-starter-kit:latest .
```

ご参考までに、当記事の末尾にdocker-compose.ymlとDockerfileの内容を掲載しておきます。

### 6. Fabric Starter Kitを動かしてみる
参考文献: [Fabric Starter Kit](https://hyperledger-fabric.readthedocs.io/en/v0.6/starter/fabric-starter-kit.html)
これでfabricの開発環境が整いました。この環境ではベーシックなクライアント・アプリ(node.js)とチェーン・コード(go)が準備済です。さっそく実行しましょう。

#### コンテナの起動
docker-composeによりmembersrvcのイメージがpullされた後、コンテナが３つ起動します。

```bash:
# backgroundで起動するとき
docker-compose up -d
# foregroundで起動するとき
docker-compose up 
```

以下のように３つのコンテナが起動します

```shell-session:
root@ubuntu:~# docker ps
CONTAINER ID        IMAGE                            COMMAND                  CREATED              STATUS              PORTS               NAMES
ed772ca27bb0        hyperledger/fabric-starter-kit   "sh -c 'sleep 20; /op"   About a minute ago   Up About a minute                       starter
627a185d8d03        hyperledger/fabric-peer          "sh -c 'sleep 10; pee"   About a minute ago   Up About a minute                       peer
88bb4cb7b745        hyperledger/fabric-membersrvc    "membersrvc"             About a minute ago   Up About a minute                       membersrvc
```

- membersrvc ...ブロックチェーン内でCAなど認証を司るfabricのコンポーネントです
- peer　　　　... ブロックチェーン内でのPeerです。当kitは開発用なので最低限である1つのみ起動しますが、実際はチェーン内で複数のpeerが起動されP2Pで協調して動作します。チェーンの外部にあるクライアント・アプリケーション（業務）はPeer（のポート)に対して各種の要求を出します。チェーンコードはpeerにデプロイされ、実行されます。
- starter        ... ブロックチェーンへ要求を出す業務アプリケーションです。当環境ではnode.jsで実装されており、[fabric-node-sdk](https://github.com/hyperledger/fabric-sdk-node)を使ってgRPCで各種の要求を出します。

なお、backgroundで起動した場合のログは`docker logs peer`で見られます。ログをみると、内部の動きがわかるので一度見てみるとよいと思います。

```shell-session:
root@ubuntu:~# `docker logs peer`
08:00:02.261 [logging] LoggingInit -> DEBU 001 Setting default logging level to DEBUG for command 'node'
08:00:02.261 [nodeCmd] serve -> INFO 002 Running in chaincode development mode
08:00:02.261 [nodeCmd] serve -> INFO 003 Set consensus to NOOPS and user starts chaincode
08:00:02.261 [nodeCmd] serve -> INFO 004 Disable loading validity system chaincode
08:00:02.262 [peer] func1 -> INFO 005 Auto detected peer address: 172.17.0.3:7051
08:00:02.263 [peer] func1 -> INFO 006 Auto detected peer address: 172.17.0.3:7051
08:00:02.265 [eventhub_producer] AddEventType -> DEBU 007 registering BLOCK
08:00:02.265 [eventhub_producer] AddEventType -> DEBU 008 registering CHAINCODE
08:00:02.265 [eventhub_producer] AddEventType -> DEBU 009 registering REJECTION
08:00:02.265 [eventhub_producer] AddEventType -> DEBU 00a registering REGISTER
```

#### アプリ(starter)を起動する
docker execでstarterのコンテナに入り、内部からnode.jsのapp.jsを起動します。結果、chaincodeがデプロイされ、起動されます。

```bash:
root@ubuntu:~# docker exec -it starter /bin/bash
root@b5b4b75d4607:/opt/gopath/src/github.com/hyperledger/fabric/examples/sdk/node# node app.js
 **** starting HFC sample ****
member services address =membersrvc:7054
peer address =peer:7051
DEPLOY_MODE=dev
enrolling user admin ...
Enrolled JohnDoe successfully

deploying chaincode; please wait ...
deploy complete; results: {"uuid":"mycc","chaincodeID":"mycc"}
invoke chaincode ...
invoke submitted successfully; results={"uuid":"00342f32-a591-4f36-b098-9897d1c7ad2b"}
invoke completed successfully; results={"result":"Tx 00342f32-a591-4f36-b098-9897d1c7ad2b complete"}
querying chaincode ...
query completed successfully; results={"result":{"type":"Buffer","data":[57,57]}}
```

コンテナの内部からはapp.jsのソースも見られます。

```shell-session:
root@ubuntu:~# docker exec -it starter /bin/bash
root@b5b4b75d4607:/opt/gopath/src/github.com/hyperledger/fabric/examples/sdk/node# ls
Dockerfile  app.js  docker-compose.yml  node_modules  web-app.js
```

#### 停止
（もし上記でコンテナに入っていたらexitしてから）docker-composeのコマンドでまとめて停止します。

```shell-session:
root@ubuntu:~# docker-compose down
Stopping starter ... done
Stopping peer ... done
Stopping membersrvc ... done
Removing starter ... done
Removing peer ... done
Removing membersrvc ... done
```

### それ以外に見ておいたらよさげな場所
docker exec -it xxxx(どれでも同じ) /bin/bashでコンテナに入ると、**/opt/gopath/src/github.com/hyperledger/fabric/** の下に下記のファイル/ディレクトリがあります。これらを一回見てみるとご理解が進むかと思います。

| ファイル/ディレクトリ | 説明 | 
|:-----------|:------------|
|membersrvcの定義 | membersrvc/membersrvc.yaml | 
| peerの定義 |peer/core.yaml | 
| サンプル・コード(チェーンコードやsdk) | examples |

### 最後に
- 念のためですが、当環境は開発環境を迅速に準備するためのものであり、Peerはセキュリティ面を甘くしたdevelopment modeで起動します。より本格的な環境を作る手順も公開されていますので下記の「文献」をご参照ください。
- Fabricはまだ開発途上のためか、プロジェクト側の不備で操作が失敗するようなケースもありました。がビルドは頻繁に行われているようで、数日たって改めてやってみたらうまくいったりしました。記事執筆時点(2016/10月)ではOKですが、皆様がご自身で試したら失敗するような場面もあるかもしれません。その場合は数日たってからリトライされるとよろしいかと思います。（または積極的にissueを伝える、とか）

# 文献
[Fabric Starter Kit](https://hyperledger-fabric.readthedocs.io/en/v0.6/starter/fabric-starter-kit.html)
[Fabric Developer Guide](http://hyperledger-fabric.readthedocs.io/en/latest/#developer-guides) - ChainCode/Application/Fabricの開発ガイド
[Steps to setup Blockchain (Hyperledger Fabric 0.6) development environment on Ubuntu ](https://www.ibm.com/developerworks/community/blogs/8d277a63-4204-4fd3-8cb8-b7cb222cd522/entry/Steps_to_setup_Blockchain_Hyperledger_Fabric_0_6_development_environment_on_Ubuntu?lang=en) - 環境構築ガイド(シリーズもの)
[Hyperledger github](https://github.com/hyperledger) - ぜんぶ
[IBM-Blockchain github](https://github.com/IBM-Blockchain) - Blockchainのデモ等が充実

# ご参考

```yaml:docker-compose.yml
membersrvc:
  # try 'docker ps' to see the container status after starting this compose
  container_name: membersrvc
  image: hyperledger/fabric-membersrvc
  command: membersrvc

peer:
  container_name: peer
  image: hyperledger/fabric-peer
  environment:
    - CORE_PEER_ADDRESSAUTODETECT=true
    - CORE_VM_ENDPOINT=unix:///var/run/docker.sock
    - CORE_LOGGING_LEVEL=DEBUG
    - CORE_PEER_ID=vp0
    - CORE_SECURITY_ENABLED=true
    - CORE_PEER_PKI_ECA_PADDR=membersrvc:7054
    - CORE_PEER_PKI_TCA_PADDR=membersrvc:7054
    - CORE_PEER_PKI_TLSCA_PADDR=membersrvc:7054
    - CORE_PEER_VALIDATOR_CONSENSUS_PLUGIN=noops
  # this gives access to the docker host daemon to deploy chain code in network mode
  volumes:
    - /var/run/docker.sock:/var/run/docker.sock
  # have the peer wait 10 sec for membersrvc to start
  #  the following is to run the peer in Developer mode - also set sample DEPLOY_MODE=dev
  command: sh -c "sleep 10; peer node start --peer-chaincodedev"
  #command: sh -c "sleep 10; peer node start"
  links:
    - membersrvc

starter:
  container_name: starter
  image: hyperledger/fabric-starter-kit
  volumes:
    # tweak this to map a local developmnt directory tree into the container
    - ~/mytest:/user/mytest
  environment:
    - MEMBERSRVC_ADDRESS=membersrvc:7054
    - PEER_ADDRESS=peer:7051
    - KEY_VALUE_STORE=/tmp/hl_sdk_node_key_value_store
    # set to following to 'dev' if peer running in Developer mode
    - DEPLOY_MODE=dev
    - CORE_CHAINCODE_ID_NAME=mycc
    - CORE_PEER_ADDRESS=peer:7051
  # the following command will start the chain code when this container starts and ready it for deployment by the app
  command: sh -c "sleep 20; /opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02/chaincode_example02"
  stdin_open: true
  tty: true
  links:
    - membersrvc
    - peer

```

```bash:Dockerfile
FROM hyperledger/fabric-peer:latest
# setup the chaincode sample
WORKDIR $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
RUN go build
WORKDIR $GOPATH/src/github.com/hyperledger/fabric/examples/sdk/node
# install the hfc locally for use by the application
RUN npm install hfc
```