Esta imagem é derivada (indiretamente) da imagem oficial "ethereum/go-client", mas ligeiramente modificada para aceitar argumentos que simplifiquem a criação de uma rede Ethereum privada com múltiplos nós. Esta imagem está publicada no Docker Hub como "vertigo/ethereum".
Alguns scripts no projeto agilizam o uso desta imagem ou mesmo permitem sua construção local. Há um artigo publicado que descreve com mais acuidade estes passos.
Para isolar uma rede blockchain Ethereum das redes públicas conhecidas não é necessário de forma alguma construir uma rede isolada. Os nós de uma rede privada podem ainda residir na Internet mas, pela natureza do próprio blockchain, estarão implementado uma rede fechada e privada, composta apenas por nós que compartilhem o mesmo bloco gênese.
Com esta imagem - e scripts associados - o usuário pode fornecer argumentos que irão gerar um bloco gênese previsível, criando um nói em um container Docker de um mesmo blockchain Ethereum privado em qualquer host na Internet (ou rede local, ou mesmo em localhost).
As variáveis de ambiente passadas como argumentos pelos scripts aos containers são:
- GEN_NONCE: any value your nodes agree upon, the default is "0xeddeadbabeeddead"
- NET_ID: any integer value your nodes agree upon, the default is 1981
The GEN_NONCE variable is used during the start script to create the "genesis.json" used when initializing the blockchain. Similarly, the NET_ID variable defines the "network_id" of the network. All members of the private network must have the same genesis block and network_id, so all you'll have to do is run the containers with the same "-e" arguments for these variables (the provided scripts do it).
A bootnode is a "dumb" node in the network that aids other nodes on P2P discovery.
There are several valid strategies to enable node discovery (including a static topology with disabled discovery). Having one or more bootnodes seems to be the best one, for it creates no obstacles for a dynamic network.
As a dumb node, the bootnode is a cheap and effective solution to aid the network self-discovery. It fits container-land perfectly, because any swarm can ressurect such a node almost instantly. The main Ethereum network itself is served by a set of bootnodes whose addresses are hard-coded in the "geth" client code.
The bootnode.sh
script runs a specialized bootnode container named "ethereum-bootnode". You can check its dynamically generated URL checking its log:
docker logs ethereum-bootnode
...
I0908 14:46:45.899423 p2p/discover/udp.go:217] Listening, enode://52f4bf370b6f407a6b3bca149b2fe24fc54ce6ac19ffe0926ad41d9bfc86ccf9bd8703fa5a4961ab28bba2a81eacba183652f744d3ff02602ecb63b7ccd3643f@172.17.0.4:30301
There is another useful script that parses the "enode" URL from this very same log (it is used in other scripts to find the bootnode URL automatically):
./getbootnodeurl.sh
enode://76e50d0dd4ae583d2653d414f9acd1df4e7a75f4bab53c7cafedc6433696ba9596c6dc84626423e629760b3ab2af9f97220dfee73961cb5be1a8ce1fa40a0bff@172.17.0.4:30301
The provided utility scripts are meant for local development use and rely on local volumes to persist data. For example, the script runnode.sh <node_name>
creates a local volume ".ether-<node_name>" at the current folder. When using this container in production you should try another strategy to guarantee the node portability.
The folders created bu each script are:
- bootnode.sh: volume ".bootnode"
- runnode.sh: volume ".ether-" (ex: "./runnode node1" creates the volume ".ether-node1")
- runminer.sh: volume ".ether-" (id.)
Note: if ran without arguments the scripts runnode.sh
and runminer.sh
assume the argument "node1" and "miner1", respectively.
The script runnode.sh
runs the first node in your private Ethereum network (a container named "ethereum-node1"). It is important to notice that it looks for and connects to the bootnode, but since it is alone in the world it won't find any peer (yet) - the bootnode is a dumb node that doesn't count as a peer.
./runnode.sh
The same script runnode.sh
can be used to run as many other nodes you want, all you need is to supply a node name as its argument. A container named "ethereum-<node_name>" will be created and started, looking for the bootnode and eventually finding the first node (and the others you ran) as its peer.
./runnode.sh node2
Self-discovery can take a few seconds, but it is easy to check it with the script showpeers.sh
. The command below shows the peers of container "ethereum-node":
./showpeers.sh
An optional argument can specify another node container to be checked:
./showpeers.sh ethereum-node2
The nodes "ethereum-node1" e "ethereum-node2" are non-mining nodes - they served the purpose of testeing the ability to create a private Ethereum network capable of self-discovery. Another script runminer.sh
is similar to the runnode.sh
, but it starts mining nodes (it assumes "miner1" if ran without arguments):
./runminer.sh [node_name]
To check if it discovered its peers "node1" and "node2":
./showpeers.sh ethereum-miner1
Mining can take quite a long time to run for the first time. Onde again, to check the node work and status you can always go for the container log:
docker logs -f ethereum-miner1