之前我们就讲解过HyperLedger Besu的PoA联盟链并且也成功部署到服务器了,那么Geth同为以太坊系列的是不是也安排一下呢…今天它来了。

与之前一样,这次Geth区块链部署也是使用Docker版本部署来避免不同环境带来的不可预料的情况。

1. 下载Docker镜像

首先,先下载geth的docker镜像

yuanzhenhui@MacBook-Pro ~ % docker pull ethereum/client-go:latest latest: Pulling from ethereum/client-go df20fa9351a1: Downloading c91bff5b9242: Pulling fs layer 5f274eeeb65e: Pulling fs layer latest: Pulling from ethereum/client-go df20a9351a1: Pull complete c91bff5b9242: Pull complete5274eeeb65e: Pull completeDigest: sha256:094f1baec8ecc6f73142cf2aa135dc9741b8593219b09d88cac672eb715b66cStatus:Downloadednewerimageforethereum/client-go:latestdocker.io/ethereum/client-go:latest

与Besu不一样,geth的引导节点镜像要另外下载,如下图:

yuanzhenhui@MacBook-Pro ~ % docker pull hawyasunaga/ethereum-bootnode :latestlatest: Pulling from hawyasunaga/ethereum-bootnode 88286f41530e: Pull completec9849f710038: Pull completeDigest: sha256: c3a855ade 70648864ec263c1cfee3719532677ada69da1d21c4897cdfbfc351eStatus: Downloaded newer image for hawyasunaga/ethereum-bootnode: latestdocker.io/hawvasunaaa/ethereum-bootnode:latest

2. 部署引导节点

镜像下载下来后就可以配置并部署引导节点了,如下脚本:

docker run -itd -m 256M --privileged=true \--memory-swap -1 \-p 30301:30301/udp \-p 30301:30301/tcp \-v /Users/yuanzhenhui/Documents/docker_data/geth/bootnode:/root/bootnode \--name geth_boot hawyasunaga/ethereum-bootnode:latest \bootnode --genkey=/root/bootnode/boot.key

执行上面语句会在bootnode文件夹中生成一个boot.key文件,如下图:


之后就可以运行bootnode节点了

docker run -itd -m 256M --privileged=true \--memory-swap -1 \-p 30301:30301/udp \-p 30301:30301/tcp \-v /Users/yuanzhenhui/Documents/docker_data/geth/bootnode:/root/bootnode \--name gethboot hawyasunaga/ethereum-bootnode:latest bootnode --nodekey=/root/bootnode/boot.key \-addr 172.17.0.4:30301

由于我这边使用的是docker内网络,所以使用的是172.17.0.4的ip地址,这个可以根据实际情况进行二次配置。

3. 部署区块节点

由于并不清楚这个docker镜像关于区块节点的数据文件部署路径,于是先直接运行镜像进入docker镜像内部查看

docker run -d --name geth1 -p 8545:8545 -p 30303:30303 ethereum/client-go:latest

发现geth的数据文件保存在/root/.ethereum文件夹中,于是分别修改启动节点的挂载地址,如下:
geth1(节点1)

docker run -d --privileged=true \--name geth1 \-p 8555:8545 \-p 30353:30303 \-v /Users/yuanzhenhui/Documents/docker_data/geth/node1:/root/.ethereum ethereum/client-go:latest

geth2(节点2)

docker run -d --privileged=true \--name geth2 \-p 8565:8545 \-p 30363:30303 \-v /Users/yuanzhenhui/Documents/docker_data/geth/node2:/root/.ethereum ethereum/client-go:latest 

4. 创建账号

节点创建之后就可以通过CLI创建账号了,进入docker容器内部调用命令创建新账户

geth --datadir /root/.ethereum account new

由于挂载文件夹是/root/.ethereum,因此将账号创建指向这个目录,如下图:

既然系统让我好好保存用户名和密码,那么我就生成一个account.txt文件保存在挂载点上吧 (生产环境下建议采用更安全的方式),如下脚本:

geth1(节点1)

echo 'account: 0x22d19690c9F15a894DF4A5Ad0b3a28e7EAD8a8E4 password: 123456' >> /root/.ethereum/account.txt

geth2(节点2)

echo 'account: 0x66d546cCBF139F3aF4b4EdeC1e02E8796544F37f password: 123456' >> /root/.ethereum/account.txt

5. 创建创世块

接下来就可以生成创世块,由于使用的是docker版本所以不存在网上说的puppeth工具这里只能够通手写创世块了,还好之前在第一次做geth的时候已经编写过一次(详情可查阅《【区块链】搭建Geth私有链(PoW)》一文),所以问题不大。

geth1(节点1)

{"config": {"chainId": 20,"homesteadBlock": 0,"eip150Block": 0,"eip155Block": 0,"eip158Block": 0},"nonce": "0x0000000000000042","timestamp": "0x0","parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000","extraData": "","gasLimit": "0xffffffff","difficulty": "0x40","mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000","coinbase": "0x0000000000000000000000000000000000000000","alloc": {"0x22d19690c9F15a894DF4A5Ad0b3a28e7EAD8a8E4":{"balance": "1000000000000000"},"0xdB10376FD880480c8Aa1a87a46Bb0f11eB89Df0b":{"balance": "70000000000000"}}}

geth2(节点2)

{"config": {"chainId": 20,"homesteadBlock": 0,"eip150Block": 0,"eip155Block": 0,"eip158Block": 0},"nonce": "0x0000000000000042","timestamp": "0x0","parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000","extraData": "","gasLimit": "0xffffffff","difficulty": "0x40","mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000","coinbase": "0x0000000000000000000000000000000000000000","alloc": {"0x66d546cCBF139F3aF4b4EdeC1e02E8796544F37f": {"balance": "50000000000000"}}}

之后将docker的geth1节点和geth2节点关闭并删除容器。然后去到宿主机数据挂载文件夹将node1和node2文件夹中的geth文件夹删除。 之后就可以执行初始化创世块的命令,如下脚本:

geth1(节点1)

docker run -itd --privileged=true \-v /Users/yuanzhenhui/Documents/docker_data/geth/node1:/root/.ethereum \--name geth1 ethereum/client-go:latest \--datadir /root/.ethereum \--networkid 8765639436932780 init /root/.ethereum/genesis.json

geth2(节点2)

docker run -itd --privileged=true \-v /Users/yuanzhenhui/Documents/docker_data/geth/node2:/root/.ethereum \--name geth2 ethereum/client-go:latest \--datadir /root/.ethereum \--networkid 8765639736932780 init /root/.ethereum/genesis.json

执行之后node1和node2文件夹下将重新生成geth文件。

6. 遇见问题

在创世块编写完成后启动或许会遇到以下问题,如下图:

Fatal: Failed to write genesis block: unsupported fork ordering: eip150Block not enabled, but eip155Block enabled at 0 genesis block

geth相关文件也生成不成功。这个错误是由于在创世块中没有将eip150Block的配置信息导致的。由于最新镜像是包含“EIP150”提案优化的(EIP150提案:解决拒绝服务攻击,而通过提高IO 操作相关的Gas 来预防攻击)所以这次要加上。

7. 结果

在上述操作都完成后,可以将docker中的geth容器删除之后就将最终配置写上就可以启动节点了。