之前我们就讲解过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 complete
5274eeeb65e: Pull complete
Digest: sha256:094f1baec8ecc6f73142cf2aa135dc9741b8593219b09d88cac672eb715b66c
Status:Downloadednewerimageforethereum/client-go:latest
docker.io/ethereum/client-go:latest
与Besu不一样,geth的引导节点镜像要另外下载,如下图:
yuanzhenhui@MacBook-Pro ~ % docker pull hawyasunaga/ethereum-bootnode :latest
latest: Pulling from hawyasunaga/ethereum-bootnode
88286f41530e: Pull complete
c9849f710038: Pull complete
Digest: sha256: c3a855ade 70648864ec263c1cfee3719532677ada69da1d21c4897cdfbfc351e
Status: Downloaded newer image for hawyasunaga/ethereum-bootnode: latest
docker.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容器删除之后就将最终配置写上就可以启动节点了。