主页 > imtoken怎么用 > 使用Docker搭建以太坊私有链并部署合约
使用Docker搭建以太坊私有链并部署合约
阅读本文后,您将能够在物理机上搭建一条完整的以太坊私链,并部署自己的合约。 用于开发、调试和学习以太坊。
本文涉及的知识和技术有:
Docker环境搭建
如何搭建Docker环境,可以参考我之前的文章。 以下内容基于本文搭建的环境。 如果你已经有一个工作的 Docker 环境,你可以忽略它。
文章地址:
主机配置
这里需要补充的是,如果你使用的是虚拟机、云主机或者老破机,你需要保证分配给主机的内存至少在2GB以上。 因为为了抵制比特大陆等ASIC矿机对算力的垄断,以太坊采用了与比特币完全不同的PoW算法——ethash。 该算法的特点是对计算能力不敏感,对内存敏感。 该算法目前需要在内存中创建一个1GB左右的DAG用于PoW计算,DAG会随着区块的增加逐步增长,因此建议至少为挖矿节点的宿主机分配2GB的内存,保留内存容量的扩展灵活性。
获取图像
docker hub上有现成的geth镜像。 直接获取。
docker pull ethereum/client-go:v1.8.12
试试看
docker run -it --rm -v /workspace:/workspace --entrypoint /bin/sh ethereum/client-go:v1.8.12
这里修改镜像的默认入口点,防止节点自动运行。 后面我们会自定义节点的配置,使其成为私链节点。
-v 将本地/workspace目录挂载为容器的/workspace目录,实现容器与宿主机共享文件
创建一个 Docker 网络
旧版本的 docker 容器依赖于链接来建立彼此之间的关系。
新版docker推荐创建自己的网络,然后将需要互联的容器配置到同一个网络中。
因此,我们创建了一个名为“ethnet”的网络。 网络配置如下:
docker network create -d bridge --subnet=172.18.0.0/16 ethnet
docker network ls
配置以太坊网络
运行以下命令进入容器:
docker run -it --rm --network ethnet --ip 172.18.0.50 -v /workspace:/workspace --entrypoint /bin/sh ethereum/client-go:v1.8.12
--network ethnet参数指定容器加入刚刚创建的ethnet网络
--ip 172.18.0.5 指定容器的固定IP。
创建账户
首先在容器中的/workspace目录下创建如下目录结构和文件:
dapp\
dapp\miner\
dapp\data\
dapp\genesis.json
然后运行以下命令创建一个帐户:
cd /workspace/dapp/miner
geth -datadir ./data account new
输入密码两次以获取地址。 记下地址以备后用。
重复上述步骤创建多个帐户。
创建创世块
编辑刚刚创建的 dapp\data\genesis.json 文件
{
"config": {
"chainId": 88,
"homesteadBlock": 0,
"eip155Block": 0,
"eip158Block": 0
},
"alloc" : {
"0x4c283287839fd441b8c8d18771321bc06a81edae": {"balance": "100000000000000000000"},
"0x8dadb9ec6a82413c389e677baa9e7b589fe92b68": {"balance": "1000000000000000000"},
"0x39c70ad710e07953dea150b1a5f1d0534bf0f135": {"balance": "1000000000000000000"},
"0xb9592b51d40d66bc583f8ed2755861372fb4afb0": {"balance": "1000000000000000000"}
},
"coinbase" : "0x0000000000000000000000000000000000000000",
"difficulty" : "0x400",
"extraData" : "",
"gasLimit" : "0x2fefd8",
"nonce" : "0x0000000000000000",
"mixhash" :
"0x0000000000000000000000000000000000000000000000000000000000000000",
"parentHash" :
"0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp" : "0x00"
}
完成以太坊网络配置
此时就可以退出之前的容器了。 由于我们添加了--rm参数来运行容器,所以刚才的容器会被删除,但是宿主机/workspace下的文件会被保存下来。
矿业
以上步骤只是配置了一个以太坊私有网络,并没有真正创建网络。 我们知道,以太坊网络是分布式网络,有矿工,就有网络。 所以,我们首先要有一个矿工。
创建一个“主”矿工节点
我们接下来要创建的矿工节点,成为“主”矿工,因为它需要具备以下特征:
于是运行以太坊节点有收益吗,根据这个需求,我们开始一步步创建矿工节点。
创建入口点脚本
创建文件:/workspace/dapp/init.sh
文件内容如下:
#!/bin/sh
geth -datadir ~/data/ init /workspace/traceability/genesis.json
if [ $# -lt 1 ]; then
exec "/bin/sh"
else
exec /bin/sh -c "$@"
fi
这个脚本的作用是让以太坊节点(容器)自动初始化以太坊网络,并接受一个自动运行脚本作为输入。
创建自动运行脚本
创建文件:/workspace/dapp/mine.sh
内容如下:
#!/bin/sh
cp -r /workspace/dapp/miner/data/keystore/* ~/data/keystore/
geth -datadir ~/data/ --networkid 88 --rpc --rpcaddr "172.18.0.50" --rpcapi admin,eth,miner,web3,personal,net,txpool --unlock "0x4c283287839fd441b8c8d18771321bc06a81edae" --etherbase "0x4c283287839fd441b8c8d18771321bc06a81edae" console
创建容器
docker run -it --name=miner --network ethnet --ip 172.18.0.50 --hostname node -v /workspace:/workspace --entrypoint /workspace/dapp/init.sh ethereum/client-go:v1.8.12 /workspace/dapp/mine.sh
此命令创建一个持久容器。 容器的入口点和自动运行脚本被指定为我们刚刚创建的两个脚本。
创建一个“从属”矿工节点
只有一个节点的网络看起来不像“分布式”网络。 所以我们需要创建更多的节点来形成一个“分布式网络”。 我们称这些节点为“奴隶”矿工。
这类矿工不需要交易,不需要发布合约,所以不需要解锁账户,也不需要接受rpc。 他们只知道如何挖掘。
创建自动运行脚本
“从属”矿工节点和“主”矿工节点共享入口点,以确保它们创建完全相同的网络。
只有自动运行脚本不同,/workspace/dapp/node.sh:
#!/bin/sh
cp -r /workspace/dapp/miner/data/keystore/* ~/data/keystore/
geth -datadir ~/data/ --networkid 88 console
创建容器
docker run -it --name=node1 --network ethnet --ip 172.18.0.51 --hostname node1 -v /workspace:/workspace --entrypoint /workspace/dapp/init.sh ethereum/client-go:v1.8.12 /workspace/dapp/node.sh
操作节点
上面创建了多个以太坊节点,在同一个网络下运行。 每个节点可以执行以下操作。 以供参考。
节点发现查看节点信息
geth -datadir ~/data/ --networkid 88 console
>admin.nodeInfo.enode
配置静态节点文件
~/data/geth/static-nodes.json
[
"enode://@:",
...
]
查看连接的节点
geth -datadir ~/data/ --networkid 88 console
>admin.peers
动态添加节点
>admin.addPeer("enode://@:")
矿业
启动矿工容器
>miner.start(1)
部署合约以创建松露图像
由于我没有找到有用的松露镜运行以太坊节点有收益吗,所以我自己制作了一个。 Dockerfile的内容如下:
FROM alpine:3.8
MAINTAINER Cary Tan tx-cary@163.com
ENV PS1='[truffle@docker $PWD]\$ '
RUN echo "http://mirrors.tuna.tsinghua.edu.cn/alpine/v3.8/main" > /etc/apk/repositories \
&& echo "http://mirrors.tuna.tsinghua.edu.cn/alpine/v3.8/community" >> /etc/apk/repositories \
&& apk update \
&& apk add npm \
&& mkdir -p /workspace \
&& npm config set registry https://registry.npm.taobao.org \
&& npm install -g truffle
WORKDIR /workspace
CMD /bin/sh
我已经把镜像上传到dockerhub了,大家也可以直接下载使用:
docker pull txcary/truffle:180806
启动松露容器
docker run -it --rm -v /workspace:/workspace --network ethnet txcary/truffle:180806
测试节点 RPC
curl 172.18.0.50:8545 -X POST --data '{"id":1,"jsonrpc":"2.0","method":"eth_accounts", "params":[]}' -H "Content-Type: application/json"
curl 172.18.0.50:8545 -X POST --data '{"id":1,"jsonrpc":"2.0","method":"eth_getBalance", "params":["0x4c2832
87839fd441b8c8d18771321bc06a81edae","latest"]}' -H "Content-Type: application/json"
创建一个新的松露项目
truffle init
修改truffle.js
module.exports = {
networks: {
development: {
host: "172.18.0.50",
port: 8545,
network_id: 88,
gas: 2900000,
gasPrice: 10000000000
}
}
};
为合约 Yourname.sol 编写一个新的部署脚本
2_deploy_contracts.js
var Yourname = artifacts.require("./Yourname.sol");
module.exports = function(deployer) {
deployer.deploy(Yourname);
};
编译合约
truffle compile
部署合约
truffle migrate --network development --verbose-rpc