Créer un réseau privé Ethereum Geth dans des conteneurs Docker



Si vous devez déployer un réseau Ethereum privé basé sur Geth, cela peut être fait, par exemple, en créant des nœuds de réseau sur des serveurs physiques ou des machines virtuelles. Cependant, il est beaucoup plus facile d'utiliser des conteneurs Geth à partir du référentiel Docker Hub. Dans ce cas, vous pouvez installer tout un réseau de nœuds, même sur une machine virtuelle ou sur un serveur physique.

Dans cet article, nous vous expliquerons comment installer Docker sur un serveur exécutant Debian 9 (virtuel ou physique), comment créer plusieurs conteneurs avec Geth et les combiner dans un réseau privé. Nous donnerons un exemple de script pour Node.js qui accède aux nœuds Geth qui fonctionnent dans des conteneurs.

Installer Docker


L'installation de Docker est décrite sur le site officiel. Pour Debian 9 et 10, vous trouverez des instructions détaillées sur https://docs.docker.com/install/linux/docker-ce/debian/ .

Installer Docker
Tout d'abord, mettez Ă  jour les packages:

# apt-get update 

Ensuite, installez les packages nécessaires avec la commande suivante:

 # apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common 

Ajoutez la clé GPG officielle:

 # curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add - 

Assurez-vous d'obtenir la clé avec l'empreinte digitale 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88:

 # apt-key fingerprint 0EBFCD88 pub 4096R/0EBFCD88 2017-02-22 Key fingerprint = 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 uid Docker Release (CE deb) docker@docker.com sub 4096R/F273FCD8 2017-02-22 

Ajoutez un référentiel Docker stable:

 # add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable" 

Mettez Ă  jour les packages et installez Docker:

 # apt-get update # apt-get install docker-ce docker-ce-cli containerd.io 

Maintenant, il ne reste plus qu'à vérifier que tout est fait correctement. Pour ce faire, exécutez l'image (Image) hello-world:

 # docker run hello-world 

Cette commande télécharge l'image souhaitée et l'exécute pour exécution. Comme vous vous en doutez, vous verrez le message «Bonjour de Docker!» Sur la console.

Comme vous pouvez le voir, rien de compliqué! Vous pouvez maintenant commencer à créer un réseau Geth privé avec des nœuds exécutés dans des conteneurs.

Créer un utilisateur, des répertoires et des fichiers


Créez un livre sur le serveur de l'utilisateur et les sous-répertoires suivants dans son répertoire personnel:

 /home/book/dock-test /home/book/dock-test/distr 

Ensuite, dans le répertoire / home / book / dock-test, créez un Dockerfile:

Listing 1. Fichier / home / livre / dock-test / Dockerfile
 FROM ubuntu:16.04 LABEL version="1.0" LABEL maintainer="alexandre@frolov.pp.ru" ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && apt-get install --yes software-properties-common RUN add-apt-repository ppa:ethereum/ethereum RUN apt-get update && apt-get install --yes geth RUN adduser --disabled-login --gecos "" eth_book COPY distr /home/eth_book/distr RUN chown -R eth_book:eth_book /home/eth_book/distr USER eth_book WORKDIR /home/eth_book RUN geth --nousb init distr/genesis.json ENTRYPOINT bash 


Ce fichier sera utilisé lors de la création de conteneurs Docker.

Vous devrez également créer le fichier /home/book/dock-test/distr/genesis.json, nécessaire pour initialiser les nœuds du réseau Ethereum:

Listing 2. Fichier /home/book/dock-test/distr/genesis.json
 { "config": { "chainId": 98760, "homesteadBlock": 0, "eip150Block": 0, "eip155Block": 0, "eip158Block": 0 }, "difficulty": "10", "gasLimit": "5100000", "alloc": {} } 


Ici, nous définissons l'identifiant de notre réseau privé sur 98760. Pour faciliter l'extraction, nous avons spécifié 10 dans le paramètre de difficulté, ce qui nous permettra de travailler sur des machines virtuelles avec une quantité de mémoire relativement petite (par exemple, 4 Go).

Créer un réseau et des conteneurs


Afin que nos nœuds échangent des données entre eux, nous allons créer un réseau entre conteneurs:

 # docker network create PRIVATENET 

Ensuite, vous devez créer le répertoire actuel / home / book / dock-test, dans lequel se trouve le Dockerfile. Créez ensuite le nombre requis de conteneurs, par exemple trois:

 # docker build -t node01 . # docker build -t node02 . # docker build -t node03 . 

La création du premier conteneur prend un temps relativement long, car Vous devez télécharger les images nécessaires. Mais les conteneurs suivants sont créés presque instantanément - comparez avec la vitesse de création de machines virtuelles, même via le clonage.

Ouvrez maintenant les quatre fenêtres de la console. Dans trois d'entre eux, nous travaillerons avec des conteneurs et dans le quatrième, nous recevrons les données dont nous avons besoin sur les conteneurs et le réseau.

Dans la première fenêtre de console, exécutez la commande suivante:

 # docker run --rm -it -p 8545:8545 --net=PRIVATENET node01 

Vous verrez une invite comme:

 eth_book@304bf4f09063:~$ 

Dans les deuxième et troisième fenêtres de console, entrez les commandes suivantes, respectivement:

 # docker run --rm -it -p 8546:8546 --net=PRIVATENET node02 # docker run --rm -it -p 8547:8547 --net=PRIVATENET node03 

Création de nœuds et de comptes de réseau privé Ethereum


À l'heure actuelle, nous avons trois conteneurs avec Geth. Créons dans chacun d'eux le nœud de notre réseau et compte Ethereum privé.

Entrez la commande dans les trois premières fenêtres de console:

 $ geth account new 

Vous devrez saisir un mot de passe. Pour plus de simplicité, utilisez le même mot de passe sur chaque nœud pour les tests, mais notez-le quelque part. Si vous oubliez le mot de passe, il ne fonctionnera en aucun cas pour récupérer.

Après avoir créé les comptes sur la console, des adresses de clés publiques similaires à celles-ci apparaîtront:

 Public address of the key: 0xc5Df10a76Bb559332c385F8cA789C0F37dD77A54 Public address of the key: 0x0C976006a5762779bA36AC590D1D8Ebac1Ca2981 Public address of the key: 0xaB627feab4e962222a3333F3b09182dF68bB9422 

Enregistrez les adresses (vous en aurez d'autres), comme nous en avons besoin pour exécuter les nœuds.

Vous devez maintenant démarrer l'initialisation des nœuds. Cela se fait à l'aide de la commande:

 $ geth --nousb init distr/genesis.json 

Entrez cette commande dans toutes les fenêtres de console de nos conteneurs. L'option --nousb désactive toutes les communications avec les périphériques USB.

Exécuter des nœuds Geth


Ouvrez maintenant tour à tour chacune des fenêtres de la console et exécutez Geth à l'aide des commandes ci-dessous.

Première fenêtre:

 $ geth --identity="Node01" --etherbase "0xc5Df10a76Bb559332c385F8cA789C0F37dD77A54" --mine --minerthreads 1 --verbosity 3 --networkid 98760 --rpc --rpcaddr 127.0.0.1 --nousb --rpcapi="db,eth,net,web3,personal,web3" console 

Deuxième fenêtre:

 $ geth --identity="Node02" --etherbase "0x0C976006a5762779bA36AC590D1D8Ebac1Ca2981" --mine --minerthreads 1 --verbosity 3 --networkid 98760 --rpc --rpcaddr 127.0.0.1 --rpcport=8546 --nousb --rpcapi="db,eth,net,web3,personal,web3" console 

Troisième fenêtre:

 $ geth --identity="Node03" --etherbase "0xaB627feab4e962222a3333F3b09182dF68bB9422" --mine --minerthreads 1 --verbosity 3 --networkid 98760 --rpc --rpcaddr 127.0.0.1 --rpcport=8547 --nousb --rpcapi="db,eth,net,web3,personal,web3" console 

Dans chacune des fenêtres ouvertes, des messages sur la génération du DAG apparaîtront:

 … INFO [12-19|17:57:44.072] Generating DAG in progress epoch=0 percentage=34 elapsed=29.740s INFO [12-19|17:57:44.898] Generating DAG in progress epoch=0 percentage=35 elapsed=30.566s INFO [12-19|17:57:45.671] Generating DAG in progress epoch=0 percentage=36 elapsed=31.339s … 

Attendez que la génération soit terminée. Après cela, eth.hashrate et eth.blockNumber seront différents de 0:

 > eth.hashrate 4 > eth.blockNumber 2 

Vous pouvez vérifier le solde du compte courant comme suit:

 > web3.fromWei( eth.getBalance(eth.coinbase) ) 

Pour que vous ne soyez pas dérangé par les messages sur la création de nouveaux blocs et d'autres messages dans les fenêtres de console, quittez Geth avec la commande exit et redémarrez à nouveau avec le paramètre de verbosité réglé sur 1.

Nœuds de mise en réseau


Pour commencer, nous allons regarder la liste des conteneurs en cours d'exécution. Exécutez la commande suivante à partir de la quatrième fenêtre de console:

 # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fa70a5418618 node03 "/bin/sh -c bash" 2 hours ago Up 2 hours 0.0.0.0:8547->8547/tcp gifted_curran 49a028744b4b node02 "/bin/sh -c bash" 2 hours ago Up 2 hours 0.0.0.0:8546->8546/tcp reverent_wescoff 5a9ade2947eb node01 "/bin/sh -c bash" 2 hours ago Up 2 hours 0.0.0.0:8545->8545/tcp clever_ellis 

Ici, pour chaque conteneur, son identifiant, le nom de l'image, le nom du conteneur et d'autres informations sont affichés.

Pour joindre des conteneurs à un réseau, vous aurez besoin des adresses IP des conteneurs de notre réseau privé PRIVATENET. Vous pouvez obtenir ces adresses par ID de conteneur, par exemple, comme suit:

 # docker inspect 5a9ade2947eb | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "", "IPAddress": "172.21.0.2", 

Vous pouvez Ă©galement utiliser la commande docker network inspect PRIVATENET:

réseau de dockers inspecter PRIVATENET
 [ { "Name": "PRIVATENET", "Id": "576ec7edba5b4c228740deaf7fabb5e2ba003d310086153dd7f15e2c7de0c1b2", "Created": "2019-12-20T11:52:07.90695857+03:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.21.0.0/16", "Gateway": "172.21.0.1" } ] }, "Internal": false, "Attachable": false, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "49a028744b4b6073f6dbca23e78625bc58fc0cdacadec7cded4bb0e888c7e37b": { "Name": "reverent_wescoff", "EndpointID": "11006b596b5a46df9bf9f95a9456784795d333a3e6901b15bd2db746fd4b5513", "MacAddress": "02:42:ac:15:00:03", "IPv4Address": "172.21.0.3/16", "IPv6Address": "" }, "5a9ade2947ebd8e55594ede9763aac71f5e6529c03e762ef723adb2c592c5ccd": { "Name": "clever_ellis", "EndpointID": "41ef69a0a93b5b1de495836028bac1742c303de92ffe42a0855ed32c93c28953", "MacAddress": "02:42:ac:15:00:02", "IPv4Address": "172.21.0.2/16", "IPv6Address": "" }, "fa70a54186185de01db3647e7333bf6c71250162fafefb78dbe9998e5ac93f34": { "Name": "gifted_curran", "EndpointID": "d368c032bc0886c27ad4895d1856e4f00cf1b25ce040f3b42393dbff778c18e5", "MacAddress": "02:42:ac:15:00:04", "IPv4Address": "172.21.0.4/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ] 

En comparant les données reçues par ces commandes, nous allons faire une liste d'adresses IP pour nos conteneurs:

 node01 - 172.21.0.2 node02 - 172.21.0.3 node03 - 172.21.0.4 

Bien sûr, vous aurez une liste différente, et lorsque vous redémarrez les conteneurs, ces adresses peuvent changer.

Après avoir reçu la liste des adresses, redémarrez geth dans tous les conteneurs, en spécifiant l'adresse de votre conteneur dans le paramètre --rpcaddr. Vous pouvez bien sûr définir l'adresse 0.0.0.0, mais c'est mauvais du point de vue de la sécurité - n'importe qui ou n'importe quoi peut se connecter au nœud. Par exemple, il peut s'agir de robots qui tentent de "retirer" tous les fonds de ces nœuds, en attendant que le nœud soit déverrouillé.

Pour fusionner les nœuds, vous devrez utiliser la commande admin.addPeer. En tant que paramètre de cette commande, vous devez transmettre l'URL au format enode. Obtenez cette URL pour chaque conteneur à l'aide de la commande admin.nodeInfo.enode:

 > admin.nodeInfo.enode "enode://0a84e562c9b22e43269b7dca215cf2ed8c20bbf35da67bae8d5ee81b36d8bbb69e3ec704b9b6f7501059fe861843a836b2fbab641f36616cdd77365b1a522d5b@62.152.63.28:30303?discport=1350" "enode://ee49f69e25c068e006fec4a8d74370370b1d2be9715b86eddd99f97a3a5a9c692a265ab7d01fb36410d59c3f6e2b253a22f652ecbf1941eef0b3f1d30b19a535@62.152.63.28:30303?discport=1345" "enode://156d43648b47078439c7481e54f697bbf1c6b6e762029ba2969f1556ceb94e51ad03f8bd2bed35f466073165810600f52925d155f0fceef832ae86fc39a8c135@62.152.63.28:30303?discport=1348" 

Les adresses reçues sont enregistrées.

Afin de connecter un nœud à un autre, ouvrez la fenêtre de console du premier nœud et entrez la commande suivante:

 > admin.addPeer( "enode://0a84e562c9b22e43269b7dca215cf2ed8c20bbf35da67bae8d5ee81b36d8bbb69e3ec704b9b6f7501059fe861843a836b2fbab641f36616cdd77365b1a522d5b@172.21.0.3:30303") 

Ici, nous avons passé l'adresse URL, en y indiquant l'adresse IP de l'hôte connecté. Suivez la même procédure sur les autres nœuds du réseau.

Pour vérifier que la connexion est établie, utilisez la commande admin.peers. S'il n'y a pas de connexions, la commande retournera un résultat vide:

 > admin.peers [] 

Dans notre cas, la commande montre que le premier nœud avec l'adresse 172.21.0.2 est connecté aux nœuds avec les adresses 172.21.0.3 et 172.21.0.4:

Voir le résultat quand il y a des connexions
 > admin.peers [{ caps: ["eth/63", "eth/64"], enode: "enode://156d43648b47078439c7481e54f697bbf1c6b6e762029ba2969f1556ceb94e51ad03f8bd2bed35f466073165810600f52925d155f0fceef832ae86fc39a8c135@172.21.0.4:30303", id: "4dac1d10cb6ae8bfc1fdebd3f5334b24ee62ec38a50bc92c89104cfc3251b5fc", name: "Geth/Node03/v1.9.9-stable-01744997/linux-amd64/go1.13.4", network: { inbound: false, localAddress: "172.21.0.2:40652", remoteAddress: "172.21.0.4:30303", static: true, trusted: false }, protocols: { eth: { difficulty: 98414119, head: "0x6b31a5bb9cde06fab5a8cc1ae9b18bada30de0d1b76cb3286c1081e76dbf5b83", version: 64 } } }, { caps: ["eth/63", "eth/64"], enode: "enode://ee49f69e25c068e006fec4a8d74370370b1d2be9715b86eddd99f97a3a5a9c692a265ab7d01fb36410d59c3f6e2b253a22f652ecbf1941eef0b3f1d30b19a535@172.21.0.3:30303", id: "b74277d278c15317fa7f7fa492daca60492ea22053bfc53281dd0071eba1c16b", name: "Geth/Node02/v1.9.9-stable-01744997/linux-amd64/go1.13.4", network: { inbound: false, localAddress: "172.21.0.2:42576", remoteAddress: "172.21.0.3:30303", static: true, trusted: false }, protocols: { eth: { difficulty: 99041423, head: "0x0ec44735bbb425cb8db96103f52300dfaae1147ba0e03aa4892d041250ce4408", version: 64 } } }] 

Veuillez noter qu'après la combinaison et la synchronisation réussies des nœuds, la commande eth.blockNumber retournera la même valeur lorsqu'elle sera lancée dans l'un de nos trois conteneurs.

La commande web3.fromWei (eth.getBalance (eth.coinbase)), au contraire, affichera un équilibre différent sur différents nœuds, car chaque nœud a son propre compte.

Travailler avec des hĂ´tes Ă  l'aide de Node.js


Dans le Listing 3, nous avons présenté un script simple exécutant Node.js qui affiche sur la console une liste de comptes pour le nœud spécifié et le solde de chacun d'eux:

Listing 3. Fichier / home / book / list_accounts.js
 var Web3 = require('web3') var web3 = new Web3(new Web3.providers.HttpProvider("http://172.21.0.2:8545")); web3.eth.getAccounts() .then(accList => { return accList; }) .then(function (accounts) { var balancePromeses = []; for(let i = 0; i < accounts.length; i++) { balancePromeses[i] = web3.eth.getBalance(accounts[i]); } Promise.all(balancePromeses).then(values => { for(let i = 0; i < values.length; i++) { console.log('Account: ', accounts[i], 'balance: ', values[i], 'wei, ', web3.utils.fromWei(values[i], 'ether'), 'ether'); } }); }) .catch(function (error) { console.error(error); }); 


Vous pouvez exécuter ce script dans une fenêtre distincte, par exemple, dans la quatrième fenêtre de console:

 # node list_accounts.js Account: 0x0C976006a5762779bA36AC590D1D8Ebac1Ca2981 balance: 3350000000000000000000 wei, 3350 ether 

Et ensuite


Le sujet du développement de logiciels pour les crypto-monnaies en général et pour Ethereum en particulier est assez fascinant. Si après avoir lu cet article, vous avez des questions et souhaitez en savoir plus, lisez mon livre «Création de contrats intelligents Solidity pour la blockchain Ethereum. Guide pratique » , qui a été publié par Liters Publishing House.

Vous pourriez Ă©galement avoir besoin d'une bonne feuille de triche Docker .

Je serais reconnaissant pour tout commentaire et ajouts Ă  l'article et au livre!

Source: https://habr.com/ru/post/fr481052/


All Articles