1. dockerfile
先编译tendermint
cp $GOBIN/tendermint ./
docker rmi tm
FROM ubuntu
ENV MYPATH /usr/local
WORKDIR $MYPATH
ADD ./tendermint $MYPATH
生成镜像:docker build -f dockerfile -t tm .
2. docker-compose.yaml
Tendermint的26656、26657、26658端口分别用于p2p监听、rpc监听、abci监听。对于同一主机中的docker节点,我们通过局域网IP进行peer通信,对于跨机的docker节点,我们通过公网IP+端口映射进行peer通信。
version: "3"
services:
node0:
image: tm
container_name: node0
ports:
- "26657:26657"
- "26656:26656"
volumes:
- $HOME/dockerfiles/node0:/root/.tendermint
networks:
mynet:
ipv4_address: 172.20.20.0
command:
- /bin/bash
- -c
- |
./tendermint init
./tendermint show-node-id > /root/.tendermint/nodeid.txt
tail -f /dev/null
node1:
image: tm
container_name: node1
ports:
- "36657:26657"
- "36656:26656"
volumes:
- $HOME/dockerfiles/node1:/root/.tendermint
networks:
mynet:
ipv4_address: 172.20.20.1
command:
- /bin/bash
- -c
- |
./tendermint init
./tendermint show-node-id > /root/.tendermint/nodeid.txt
tail -f /dev/null
node2:
image: tm
container_name: node2
ports:
- "46657:26657"
- "46656:26656"
networks:
mynet:
ipv4_address: 172.20.20.2
volumes:
- $HOME/dockerfiles/node2:/root/.tendermint
command:
- /bin/bash
- -c
- |
./tendermint init
./tendermint show-node-id > /root/.tendermint/nodeid.txt
tail -f /dev/null
node3:
image: tm
container_name: node3
ports:
- "56657:26657"
- "56656:26656"
networks:
mynet:
ipv4_address: 172.20.20.3
volumes:
- $HOME/dockerfiles/node3:/root/.tendermint
command:
- /bin/bash
- -c
- |
./tendermint init
./tendermint show-node-id > /root/.tendermint/nodeid.txt
tail -f /dev/null
networks:
mynet:
ipam:
driver: default
config:
- subnet: 172.20.0.0/16
3. 编排容器
docker-compose up -d
4. 统一创世文件
先通过python脚本生成本地创世文件,再进行跨机节点的统一。
linesArr = []
for i in range(0, 4):
f = open("/home/cy/dockerfiles/node%d/config/genesis.json" % i, 'r')
linesArr.append(f.readlines())
f.close()
f = open("./genesis.json", 'w')
for i in range(len(linesArr)):
lines = linesArr[i]
if i == 0:
for j in range(23):
f.write(lines[j])
for j in range(23, 32):
if i == len(linesArr) - 1:
f.write(lines[j])
else:
if j < 31:
f.write(lines[j])
else:
f.write(lines[j][:len(lines[j]) - 1])
f.write(",\n")
for i in range(32, len(linesArr[0])):
f.write(linesArr[0][i])
f.close()
覆盖掉原来的genesis.json文件:
#!/bin/bash
for((i=0;i<=3;i++))
do
cp genesis.json node${i}/config/genesis.json
done
5. 启动集群
163机器上的节点执行:
nohup ./tendermint run --p2p.persistent_peers="747702da07268e8962420266e0d29215c72d1a71@172.20.20.0:26656,61ca3cc8dcec37d60ea0c653feffc878d966ace5@172.20.20.1:26656,1e13b5d2277da2e9bf847428fafa72be792f3e4a@172.20.20.2:26656,c50d175a2c60e2eb3bca0ec1ecb0b67ee3982bc6@172.20.20.3:26656,a0ace4b8e8b8af29ced876db545fe65d4333bb36@10.77.110.164:26656,a2c54f8dc4328ff267b8eb228738a324e7e6c304@10.77.110.164:36656,3caee572c7d4afcbdc90cabfbc70c4370e9e8de7@10.77.110.164:46656,35637256a783798d68dd60f1c609da86330ef865@10.77.110.164:56656" --proxy_app=persistent_kvstore &
164机器上的节点:
nohup ./tendermint run --p2p.persistent_peers="ec28ae5d05fe759fd71019fb1c49efd1c1ac5adf@172.20.20.0:26656,739f836242624d999bc13e256fccc4c5f588d1d6@172.20.20.1:26656,af0c9cf4f2c7d69d4d3ae08f13dd7fb3e89cf60d@172.20.20.2:26656,7552685783af2f413ef1e25a5ce7b5773916fa47@172.20.20.3:26656,c62e1ba79823f3bfebefa05f6c51807c690623aa@10.77.110.163:26656,f6448f6b3e88978c3ba3e05ad9eb085fd79fc251@10.77.110.163:36656,a35f14de4e1d3efebf5713f0e80163743e9ac2ff@10.77.110.163:46656,ad497fcaf7c9f1b3ffdfa0eb15f5649e8d86be22@10.77.110.163:56656" --proxy_app=persistent_kvstore &
6. 验证
在164机器上查询163的node2的status:
在163机器上查询164的node0的status:
7. 删除容器但保存区块数据
- 在每个容器中通过kill -15优雅关闭节点服务
kill -15 $(ps aux | grep "tendermint run" | awk -F " " '{print $2}')
- 再通过docker-compose down -v删除所有容器
- docker-compose up -d重新启动容器
- 执行5中的集群启动命令(注意节点id需要重新设置)