一.我们可以通过 docker-compose 来启动多个 container
通过官方文档我们知道启动 tendermint 集群需要下面几个步骤:
- 每个 node 都需要通过 tendermint init 来进行初始化;
- 需要有一个包含所有 validator 节点 public key 的 genesis.json 文件, 然后用这个文件覆盖所有节点对应的文件; 在我们的示例中所有的节点都是 validator 节点;
- 通过 tendermint show_node_id 获取节点的 ID, 并通过参数 --p2p.persistent_peers=ID1@node1:46656,ID2@node2:46656 来传入种子 peer;
对应于上面环境准备需要做的工作, 我通过脚本文件 ./init_data.sh 做了自动化的处理:
#!/bin/bash
#
# Description: init tendmint node data
# Author: Hongbo Liu
node_cnt=4
tendermint_img="tendermint/tendermint:latest"
is_osx () {
[[ "$OSTYPE" =~ ^darwin ]] || return 1
}
init() {
SED=sed
if [[ "$OSTYPE" =~ ^darwin ]]; then
SED=gsed
if ! which gsed &> /dev/zero ; then
brew install gnu-sed
fi
if ! which jq &> /dev/zero; then
brew install jq
fi
else
if ! which jq &> /dev/zero; then
sudo apt-get install jq -y
fi
fi
if is_osx; then
rm -rf *data
else
sudo rm -rf *data
fi
}
init
default_genesis="./node1_data/config/genesis.json"
for (( i = 1; i <= $node_cnt; i++ )); do
if ! is_osx; then
mkdir -p node${i}_data
chmod 777 node${i}_data
fi
docker run --rm -v `pwd`/node${i}_data:/tendermint $tendermint_img init
if ! is_osx; then
sudo chmod -R 777 node${i}_data
fi
node_id=$(docker run --rm -v `pwd`/node${i}_data:/tendermint $tendermint_img show_node_id)
echo "Node$i ID: $node_id"
$SED -i "s/[0-9a-f]\{40\}@tm_node$i/$node_id@tm_node$i/g" ./docker-compose.yml
if [[ $i != 1 ]]; then
echo $(cat $default_genesis | jq ".validators |= .+ $(cat node${i}_data/config/genesis.json | jq '.validators')") > $default_genesis
fi
echo $(cat $default_genesis | jq ".validators[$i-1].name = \"tm_node$i\" ") > $default_genesis
done
for (( i = 2; i <= $node_cnt; i++ )); do
cp -f $default_genesis ./node${i}_data/config/genesis.json
done
其中打印出来的节点 ID 会在后面的 docker-compose.yml 文件中用到。然后我们就可以通过 docker-compose.yml 启动多个 container 了, 这里我们启动四个节点:
version: '2.0'
services:
tm_node1: &node
image: tendermint/tendermint:latest
container_name: tm_node1
hostname: tm_node1
tty: true
ports:
- '46667:46657'
volumes:
- ./node1_data:/tendermint
entrypoint: ["sh", "-c", "tendermint node --p2p.persistent_peers=f6e4c91a17c79b4805592603204ada8895196205@tm_node1:46656,f6859a0b40dfd2d21ae7b0f9a5796e7b62ac4ca4@tm_node2:46656,0fab048217e63e240b7eade1ed642906660bb0fa@tm_node3:46656,ccc8005a4e2a4022e79b84c946aa05b4e056a9b0@tm_node4:46656 --moniker=`hostname` --proxy_app=persistent_kvstore --consensus.create_empty_blocks=false"]
tm_node2:
<<: *node
container_name: tm_node2
hostname: tm_node2
ports:
- '46668:46657'
volumes:
- ./node2_data:/tendermint
tm_node3:
<<: *node
container_name: tm_node3
hostname: tm_node3
ports:
- '46669:46657'
volumes:
- ./node3_data:/tendermint
tm_node4:
<<: *node
container_name: tm_node4
hostname: tm_node4
ports:
- '46660:46657'
volumes:
- ./node4_data:/tendermint
接下来我们就可以通过下面的步骤来启动有四个节点的 tendermint 集群:
./init_data.sh
用上面脚本的输出的节点 ID 分别去替换 docker-compose.yml 文件中的节点 ID
docker-compose up -d
用docker ps查看容器内的信息
成功启动之后我们可以通过 curl -s localhost:46667/net_info 中的结果来判断两个节点有没有相互识别。也可用CONTAINER ID查看登陆日志
docker logs a6c2b0220899