使用 docker 執行自定義私有 go-ethereum 節點集群
這是我一直在研究的設置,但在與對等方創建專用網路的能力方面存在問題。基本設置:使用來自https://github.com/ethereum/ethereum-dockers/tree/master/go-ethereum-base的 dockerfile ,並在鏡像中添加了安裝乙太坊的行。
- 創建圖像後,我執行了 2 個圖像實例(請注意,它們都包含基本的自定義 genesis JSON 文件)
docker run -it -p 127.0.0.1:30303:30303 -p 3001:3001 --name e1
和
docker run -it -p 127.0.0.1:30304:30304 -p 3002:3002 --name e2 \ --link e1:e1
- 接下來,我附加到容器 e1 並執行以下命令:
geth --identity "ethnode1" --datadir "/tempdatadir1" --rpc \ --port "30303" --rpccorsdomain "*" --rpcport "3001" \ --genesis genesis.json --networkid 6161 \ --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \ --rpcapi "db,eth,net,web3" --nat "any" --maxpeers 2 console
這啟動了一個
geth
控制台,我可以在其中使用諸如admin.nodeInfo
等命令檢查節點資訊。提取用於連接第二個節點的 enode 值:enode://@[::]:30303
使用 Crtl-C 退出控制台
- 附加到容器 e2,並執行以下命令:
geth --identity "ethnode2" --datadir "/tempdatadir2" --rpc \ --port "30304" --rpccorsdomain "*" --rpcport "3002" \ --genesis genesis.json --networkid 6161 \ --ipcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" \ --rpcapi "db,eth,net,web3" --nat "any" --maxpeers 2 console
這啟動了一個
geth
控制台,我可以在其中使用諸如admin.nodeInfo
等命令檢查節點資訊。此時,我嘗試使用以下命令添加第一個節點:admin.addPeer("enode://@127.0.0.1:30303")
,它返回 true。但是,當我嘗試使用其中之一列出對等方時admin.Peers
,我看到一個空數組並且使用net.peerCount
給出 0。建議,至於如何啟用兩者之間的連接?
- 是不是使用了錯誤的IP地址?通常,是否可以通過適當地轉發 IP 地址來利用來自主機的特定 IP 地址。
- 不應該在上面的步驟 2 中退出控制台嗎?
- 在上述任何一種情況下,我們如何連接到現有
geth
實例?我嘗試使用geth attach "http://127.0.0.1:3001"
,但它給了我一個錯誤,說連接被拒絕。關於我們如何附加到現有geth
實例的任何建議?
概括
- 檢查兩個 Docker 容器之間是否存在網路連接,並在必要時重新配置。檢查是否為每個容器分配了足夠的記憶體。
- 在每個 Docker 容器中
- 安裝 go-ethereum
geth
程序- 創建兩個帳戶(乙太坊地址)
geth
使用完全相同的自定義genesis.json
文件(相同)執行--networkid
,--datadir
設置為您的首選目錄並使用參數 forgeth
開始探勘。geth
正在執行的測試
- 連接
geth
實例。簡短回答您的問題
問:如何啟用兩者之間的連接?
- A:首先設置Docker容器之間的連接。提供了一些參考資料,但不要使用
127.0.0.1
,因為這通常僅限於在您的作業系統/Docker 容器中使用。Q:是不是使用了錯誤的IP地址?通常,是否可以通過適當地轉發 IP 地址來利用來自主機的特定 IP 地址。
127.0.0.1
答: Docker 容器中應該有一個可用的非IP 地址。以下說明可找到此地址。問:控制台是否應該在上面的第 2 步中不退出?
- 答:首先使用
geth ... console
. 測試時不要退出geth
命令提示符。問:在上述任何一種情況下,我們如何連接到現有的 geth 實例?我嘗試使用 geth attach“ http://127.0.0.1:3001 ”,但它給了我一個錯誤,說連接被拒絕。關於我們如何附加到現有的 geth 實例的任何建議?
- 答:我在下面列出了一些測試來檢查您的 Docker 容器網路連接。解決連接後,使用您的
--rpc*
參數,您應該能夠使用geth attach ...
非127.0.0.1
地址和埠進行連接。編輯 23/04/2016
192.*.*.*
- OP 使用而不是IP 地址解決了連接問題127.0.0.1
,如以下 Docker 命令所示:docker run -it -p 192.XXX.XXX.XXX:30303:30303 --name e1 <eth image>
和
docker run -it -p 192.XXX.XXX.XXX:30304:30304 --name e2 --link e1:e1 <eth image>
編輯 24/04/2016 - OP 在根 (
/
) 目錄中創建了數據目錄。這將需要超級使用者 (root) 權限。最好將數據目錄儲存在您的主目錄中。使用$HOME/tempdatadir1
而不是/tempdatadir1
. 預設情況下,geth
將在$HOME/.ethereum
.詳情如下
Docker 容器連接和要求
記憶
geth
將需要超過 512 Mb,因此您可能希望使用 1 Gb 進行測試,並在必要時增加它。碼頭工人網路
目標
您需要設置 Docker 容器,以便
geth
在 Container #1 中可以連接到geth
Container #2 中,反之亦然。在您的問題中,您已映射
127.0.0.1:30303
為通過 port 進行外部訪問30303
。127.0.0.1
IP 地址是一個 localhost地址,通常不允許從作業系統外部進行通信。127.0.0.1
請通過在 Docker 容器中使用來檢查非IP 地址,ifconfig -a
以確定您的非本地 IP 地址是什麼。嘗試使用這些 IP 地址跨 Docker 容器進行通信。參考
檢查連接
使用以下命令從 Container #1 中獲取 IP 地址
ifconfig -a
:ifconfig -a lo ... inet addr:127.0.0.1 ... ... docker0 ... inet addr:192.168.0.1
在 Container #1 中的埠 30303 上執行
geth
,如下一節所示(或如您在問題中記錄的那樣)。從 Container #2 或主機,您應該能夠執行以下命令 - 您必須按 Control-C 來終止連接:
user@Kumquat:~$ telnet 192.168.0.1 30303 Trying 192.168.0.1... Connected to 192.168.0.1. Escape character is '^]'.
如果您的 IP 地址未設置為接收您的連接嘗試,您的結果應如下所示:
user@Kumquat:~$ telnet 192.168.0.1 30303 Trying 192.168.0.1... telnet: Unable to connect to remote host: No route to host
如果您的 IP 地址正確,但您的埠未正確映射,您應該會看到:
user@Kumquat:~$ telnet 192.168.0.1 30303 Trying 192.168.0.1... telnet: Unable to connect to remote host: Connection refused
配置
geth
使用基本參數進行配置
geth
,以便我們可以驗證它是否按預期工作,而 Docker 容器之間沒有 P2P 連接。您首先需要配置兩個帳戶來測試您的挖礦。新賬戶
在 Container #1 中,執行以下命令兩次以創建兩個新帳戶:
user@Kumquat:~$ geth --datadir "$HOME/tempdatadir1" account new Your new account is locked with a password. Please give a password. Do not forget this password. Passphrase: Repeat Passphrase: Address: {a6847de2447db964ef89644752921c204bf563ab}
與您的帳戶相關的數據(以加密格式)儲存在您
--datadir
的子目錄下的目錄keystore
中。如果您在乙太坊主網路中使用此帳戶,請確保備份這些文件(並記住您的密碼)。user@Kumquat:~$ ls -al $HOME/tempdatadir1/keystore total 12 drwx------ 2 user user 4096 Apr 24 16:11 . drwx------ 3 user user 4096 Apr 24 16:11 .. -rw------- 1 user user 491 Apr 24 16:11 UTC--2016-04-24T06-11-04.534736154Z--a6847de2447db964ef89644752921c204bf563ab
在 Container #2 中也一樣,使用
--datadir
for Container #2。執行
geth
礦工在 Container #1 中執行以下命令,您應該會看到如下所示的消息:
geth --datadir "/tempdatadir1" --port "30303" \ --genesis genesis.json --networkid 6161 \ --mine --minerthreads 1 console
容器 #2 相同:
geth --datadir "/tempdatadir2" --port "30304" \ --genesis genesis.json --networkid 6161 \ --mine --minerthreads 1 console
您應該看到的消息如下:
I0422 23:24:07.347255 8218 worker.go:348] 🔨 Mined block (#6248 / 11175b1e). Wait 5 blocks for confirmation I0422 23:24:07.347868 8218 worker.go:569] commit new work on block 6249 with 0 txs & 0 uncles. Took 521.208µs I0422 23:24:07.348356 8218 worker.go:569] commit new work on block 6249 with 0 txs & 0 uncles. Took 378.62µs I0422 23:24:18.248751 8218 worker.go:348] 🔨 Mined block (#6249 / 50cdfdeb). Wait 5 blocks for confirmation I0422 23:24:18.249306 8218 worker.go:569] commit new work on block 6250 with 0 txs & 0 uncles. Took 470.831µs
從賬戶 #1 向賬戶 #2 發送乙太幣
在每個容器中,在控制台中執行
sendTransaction
命令。geth
您的挖礦操作應該將乙太幣添加到 eth.accounts$$ 0 $$(第一個帳戶,也稱為coinbase)。此命令將從 eth.accounts 發送一個乙太幣$$ 0 $$到 eth.accounts$$ 1 $$:
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether")}) "0xde465790a8ae4ce1aad3179d071ac49ed447c09199de26ce02327e8790e63e4b"
等待交易被探勘。然後執行
getTransaction
命令檢查交易是否已被探勘到一個塊中:> eth.getTransaction("0xde465790a8ae4ce1aad3179d071ac49ed447c09199de26ce02327e8790e63e4b") { ... blockNumber: 6266, ... }
查看以下賬戶餘額
eth.accounts[1]
:> web3.fromWei(eth.getBalance(eth.accounts[1]), "ether") 1
連接
geth
實例您將需要找到每個實例的enode資訊。
geth
我已將長節點公鑰從“d9d93b749257a1d4eaec18ab1c1ad39dc9220e449cfe248aceafc586193ead0ac14a088be5afb8455bd8f14bab7428162b8fbeda399ec748f5df0369789789730d9”縮短為“d9”,以便於閱讀在 Container #1 中,執行以下命令
geth ... console
:> admin.nodeInfo { enode: "enode://d9d9...30d9@[::]:30303?discport=0", ... }
geth
從Container #2 中獲取相同的資訊。在下面的 Peer Discovery 部分中,替換**$$ :: $$**在您的 enode 中使用您的 Docker 容器的外部可訪問 IP 地址,然後刪除
?discport=0
文本。對等發現
您有 3 種方法可以讓
geth
您的 Docker 容器相互連接:
- 引導節點
在 Container #1 中,將
--bootnodes
參數添加到geth
命令行中,例如,其中“d9d9…30d9”需要替換為geth
Container #2 中的相應公鑰:geth --bootnodes "enode://1234...5678@192.168.0.2:30304" ...
在 Container #2 中,您可以添加類似的參數:
geth --bootnodes "enode://d9d9...30d9@192.168.0.1:30303" ...
這將連接您的
geth
節點以進行初始對等發現,它們應該在其中發現彼此並保持 P2P 連接。 2.static-nodes.json
--datadir
在您的目錄中的一個名為 的文件中添加以下文本,替換為您的節點資訊static-nodes.json
:[ "enode://1234...5678@192.168.0.2:30304", "enode://d9d9...30d9@192.168.0.1:30303" ]
trusted-nodes.json
同上
static-nodes.json
,但這裡的節點連接不計入--maxpeers
參數,如果指定。嘗試不同的配置風格,直到找到一種至少可以穩定幾天的配置風格。
同行發現參考
如何
geth
在後台執行要
geth
作為後台程序執行,console
請從命令中刪除參數geth
並附加&
將在後台啟動程序的符號。由於您可能想要檢查來自 的消息geth
,您應該將輸出從管道(發送)geth
到日誌文件中。我就是這樣做的:
logs
在 $HOME 目錄中創建一個子目錄:mkdir $HOME/logs
geth
使用命令行選項設置腳本文件。我打電話給我runGeth
的並將其保存在$HOME/bin
. 完整的文件名是$HOME/bin/runGeth
,這個文件包含:#!/bin/sh # Kill any running geth instances gracefully killall -q --signal SIGINT geth # Wait for 10 seconds sleep 10 # Make sure that geth is really killed. Try hard killing again killall -q geth # Run geth in the background, # piping the output messages to a log file geth --rpc [other parameters] --verbosity 3 2>> $HOME/logs/geth.log &
您必須執行以下命令才能使此腳本可執行:
user@Kumquat:~$ chmod 700 $HOME/bin/runGeth
您現在可以
geth
從命令行開始執行腳本:user@Kumquat:~$ runGeth
如果這不起作用,請使用完整路徑名:
user@Kumquat:~$ $HOME/bin/runGeth
- 要附加到
geth
在後台執行的實例,請使用以下命令:geth attach
這將使用 IPC 協議連接到
geth
在後台執行的實例。如果
geth
要從其他 Docker 容器或從 Docker 容器外部連接到實例,請使用以下命令以及正確的 IP 和埠號:geth attach rpc:http://192.XXX.XXX.XXX:8545
請注意,該埠
8545
是可以使用--rpcport {port}
命令行參數設置的預設 RPC 埠。您可以退出這些
geth attach
程序,而不會影響geth
在後台執行的實例。由於我不喜歡輸入冗長的命令行參數,因此我創建了
$HOME/bin/attachGeth
包含以下內容的文件:#!/bin/sh geth attach rpc:http://192.XXX.XXX.XXX:8545
因此
chmod 700 $HOME/bin/attachGeth
我可以geth
使用命令attachGeth
或$HOME/bin/attachGeth
. 4.geth
查看後台執行的實例的日誌文件:tail -F $HOME/logs/geth.log
按 Control-C 終止此過程。