【CentOS】IPFSのプライベートネットワークを組む

ブロックチェーンの仕組みとIPFSの登場

皆さんIPFSというものは聞いたことあるでしょうか?

仮想通貨技術・ブロックチェーンの台頭により
分散型アプリケーションが注目を浴びるようになりました。

ブロックチェーンは、ブロックと呼ばれる単位ごとにまとめられたデータを
世界中の人がコンピュータの計算力などで競い合いながらそのデータを承認し、
そのブロックを元に新しいブロックを作ります。

このとき世界中の人から勝ち抜いて新しいブロックを作れた人に
報酬として仮想通貨が贈与されるため、皆こぞってレースに参加するわけです。

そのため、もしブロックを改ざんしそれを承認させようとするとき、
世界一の人の計算力を圧倒的に凌駕し先回りして新しいブロックを作る
必要があるが、そのようなことは現実的に不可能であるため、
ブロックの内容は改ざんされていないものと信用できるのです。

そんな中で普通に仮想通貨を使う一般貴兄が仮想通貨のやり取りをする際、
「誰が誰にいくらお金を渡したか」という情報をブロックに追記することで
絶対に改ざんされないトレード内容とすることができます。

この話だけ聞くと実に素晴らしいシステムですが、いくつか問題を抱えています。
その一つがデータ量についてです。

現在、ビットコインの全データ量は200GBを越えています。
ほぼ仮想通貨のやり取りのデータのみでこのデータ量であるため、
画像などをブロックに格納しようとすると目も当てられないことになります。

この問題を解決するために登場するのがIPFSです。

IPFSとは?

IPFSを一言で表すと「分散ストレージ」です。

一つのファイル(またはその断片)をP2Pネットワーク上の
不特定多数の人で共有することによって誰かがそのファイルを
ローカルから削除しても世界のどこかに残り続けるといった特徴を持っています。

これだけ聞くとBitTorrentとさほど差は無いように感じますが、
IPFSはコンテンツ指向型という方式でファイルの場所を表します。

コンテンツ指向型とはロケーション指向型と対をなすもので、
ロケーション指向型では'http://ドメイン/ディレクトリ/ファイル名'のようにファイルの場所を表します。

コンテンツ指向型では`Qm1234567890abcde...`というものになります。
意味不明な文字列ですがこれはファイルの内容を丸々ハッシュ関数に通したハッシュ値です。
`Qm`はどのハッシュ関数を使うかを表している部分となります。

ハッシュ関数の特徴として入力した内容が1文字でも変更されれば
そのハッシュ値は全く違うものになるというものがあります。

そのため、ハッシュ値が変わっていなければ、そのコンテンツの内容も
変わっていないことが保証されるため、ブロックチェーンの改ざんされていないことを
保証する特徴と合致するため、ブロックチェーン用のストレージとして利用できます。

IPFSのプライベートネットワークを作成

今回はgo-ipfsをdocker上にいくつかたててネットワークを作成します。
CentOS7上で作業しますが、UbuntuやArchをお使いの方はaptやpacmanなど
ディストリビューションに合わせて変更してください。

以下が作業手順になります。

 

  1. 最新の状態にし、必要パッケージのインストール
  2. Dockerのインストール
  3. CentOSイメージを使ってIPFSをインストール
  4. 仮想環境を複製し、IPFSプライベートネットワークを構築する

構築する環境は以下のイメージです。

1. 最新の状態にし、必要パッケージのインストール

実験環境のため、煩わしいselinuxやipv6はオフにしておきます。

まずはselinuxを停止します。

sudo vi /etc/selinux/config

enforcingをdisabledに変更してください。

SELINUX=disabled

次にipv6をオフにします。
以下のファイルが存在しなければ新規作成してください。

sudo vi /etc/sysctl.d/disable_ipv6.conf

以下を追記してください。

net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

設定を反映します。

sudo sysctl -p /etc/sysctl.d/disable_ipv6.conf

 

次に、updateを実行し、gitとwgetをインストールし再起動してください。
selinuxの設定は再起動しないと反映されません。

sudo yum update -y
sudo yum install -y git wget
sudo reboot

2. Dockerのインストール

Dockerとはカーネルを共有する仮想マシン作成ソフトです。
まぁPCの中に何台もPCを作れるというイメージで大丈夫です。

CentOS7ではyumで簡単にインストールできますが、
他ディストリビューションではいろいろ手順があるそうなので
環境に合わせて調べてください。

以下はCentOS7環境での手順です。

  1. dockerのインストール
  2. dockerグループ作成
  3. 作業ユーザーをdockerグループに入れる
  4. dockerデーモンをスタートアップ設定する
  5. dockerデーモンをスタート
  6. 再ログイン
sudo yum install -y docker
sudo groupadd docker
sudo gpasswd -a 作業ユーザー docker
sudo systemctl enable docker
sudo systemctl start docker

最後に再ログインをしてください。

3. CentOSイメージを使ってIPFSをインストール

まずはdockerイメージをpullします。
イメージ一覧を見ると最新のものがダウンロードされています。

docker pull centos
docker images

次にこのイメージを使ってWebサーバー用dockerを立てるのですが、
docker内とホストPCのディレクトリをリンクさせる場所を作ります。

mkdir ipfsApp

次に仮想マシンを立てて環境構築していきます。
以下のコマンドで起動してください。

※-v ホスト側ディレクトリ:docker側ディレクトリ
-p ホスト側port:docker側port

docker run -it -d -v /home/sasa/project/ipfsApp:/opt/ipfsApp -p 80:80 --name web-server docker.io/centos /bin/bash
docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
984bdda077f0        docker.io/centos    "/bin/bash"         32 seconds ago      Up 31 seconds       0.0.0.0:80->80/tcp   web-server

仮想マシンが起動出来たら中に入っていきます。

docker exec -it web-server /bin/bash

root権限でアクセスできるのでアップデートして必要パッケージをインストールし、
IPFSをインストールします。IPFSはhttps://dist.ipfs.io/#go-ipfsから最新版をDLしてください。
インストールスクリプトを実行して、ipfs versionを実行し、無事表示されたら成功です。

yum update -y
yum install -y wget git
wget https://dist.ipfs.io/go-ipfs/v0.4.22/go-ipfs_v0.4.22_linux-amd64.tar.gz
tar xvzf go-ipfs_v0.4.22_linux-amd64.tar.gz
cd go-ipfs
./install.sh
ipfs version

いったんdocker内での作業は終了しますのでCtrl+p,q(Ctrl押しながらp→qの順番に押す)を入力して抜けてください。

4. 仮想環境を複製し、IPFSプライベートネットワークを構築する

まず前項までの作業したイメージを新しいイメージとして保存します。

docker commit web-server ipfs-node
docker images

それでは一気に3つdockerを立てていきましょう。

docker run -it -d --name ipfs-node01 ipfs-node /bin/bash
docker run -it -d --name ipfs-node02 ipfs-node /bin/bash
docker run -it -d --name ipfs-node03 ipfs-node /bin/bash
docker ps

次にそれぞれのdocker内に入り、IPFSノードを接続する設定を行っていきます。
やることの概要としては、

  • ipfsの初期化
  • bootstrapの全削除
  • ipfsデーモンを起動
  • ipfsのアドレスを交換しbootstrapに追加

となります。アドレスの交換は3ノードのうちの一つを追加していれば
そのノードとつながっているノードとも繋がるので自分以外のすべてを
追加する必要はありません。

この作業はTeraTermなどで副窓して行うと楽です。
コマンドライン1つしか用意できない場合は抜けたり入ったりを繰り替えしてください。

Webサーバーのdockerも同じようにネットワークにつなぐのでそちらも
同じように以下の手順でネットワークに参加させてください。

ではまずそれぞれでifpsの初期化を行います。docker execでそれぞれのdockerに
入ってコマンドを実行してください。

docker exec -it ipfs-node01 /bin/bash
ipfs init

次にipfsのbootstrapの全削除を行います。
ipfsはbootstrapに記録されたノードのリストと通信を行います。
また、通信したノードとbootstrapを交換することでさらにそのノードと
繋がったノードと通信をすることができます。

今回はプライベートネットワークを構築するのでbootstrapを
立てたdockerのipfsノードだけにします。

ipfs bootstrap rm all

次にipfsのデーモンを起動します。
bootstrapが存在しないのでまだどのノードとも繋がりません。
「Daemon is ready」が表示されたら起動に成功しています。

ipfs daemon &

次にアドレスの交換をします。
まず交換元のノードで以下のコマンドを実行し、自分のアドレスを確認します。
Addressの部分のip4で127.0.0.1(ローカルホスト)でないやつが交換するアドレスです

ipfs id

次に交換先のノードで以下のコマンドを実行し、bootstrapに追加します。

ipfs bootstrap add <Address>

以上の操作をnode02,03にも行った後、以下のコマンドで
自分以外のIDが表示されたらプライベートネットワークの構築に成功しています。

ipfs swarm peers

IPFSの活用

IPFSはまだ発展途上の技術で何に使うか、どんな活用法があるのかは
まだ誰にもわかりません。

ですが、IPFSの使い方はだいぶ整備されてきました。
Node.jsやJavaScriptにはAPIを使うためのライブラリが存在するので
それを使ってウェブアプリを作るのもまた一つの手です。

これからどんな活用法が現れるか楽しみですね!