Summary
- Check that there is network connectivity between the two Docker containers and reconfigure if necessary. Check there is sufficient memory allocated to each container.
In each Docker container
- Install the go-ethereum
geth
program
- Create two accounts (Ethereum addresses)
- Run
geth
with the exact same custom genesis.json
file, same --networkid
, --datadir
set to your preferred directory and with the parameter for geth
to start mining.
- Test that
geth
is working
- Connect the
geth
instances.
Short Answer To Your Questions
Q: How the connectivity between the two can be enabled?
- A: First set up connectivity between the Docker containers. Some references provided, but don't use
127.0.0.1
as this is normally confined to be used within your operating system / Docker container.
Q: Is it that the wrong IP address is being used? In general, is it possible to utilize a specific IP address from the host by forwarding the IP Address appropriately.
- A: There should be a non-
127.0.0.1
IP address available from within the Docker container. Instructions below to find this address.
Q: Should the console not be exited in Step 2 above?
- A: Test your setup first using
geth ... console
. Don't exit the geth
command prompt while you are testing.
Q: In either of the above cases, how do we connect to an existing geth instance? I tried using geth attach "http://127.0.0.1:3001", but it gave me an error saying, connection refused. Any suggestions as to how we can attach to an existing geth instance?
- A: I've listed some tests below to check your Docker container networking connectivity. Once connectivity is resolved, use your
--rpc*
parameters and your should be able to connect using geth attach ...
with the non-127.0.0.1
address and port.
EDIT 23/04/2016 - OP solved the connectivity issue using 192.*.*.*
instead of 127.0.0.1
for the IP addresses as shown in the following Docker commands:
docker run -it -p 192.XXX.XXX.XXX:30303:30303 --name e1 <eth image>
and
docker run -it -p 192.XXX.XXX.XXX:30304:30304 --name e2 --link e1:e1 <eth image>
EDIT 24/04/2016 - OP has the data directories to be created in the root (/
) directory. This will require superuser (root) permission. It is better to store the data directory within your home directory. Use $HOME/tempdatadir1
instead of /tempdatadir1
. By default, geth
will create your data directory in $HOME/.ethereum
.
Details Below
Docker Container Connectivity And Requirements
Memory
geth
will require more than 512 Mb so you may want to test with 1 Gb and increase it if necessary.
Docker Networking
Aim
You will need to set up your Docker containers so that geth
in Container #1 can connect to geth
in Container #2 and vice versa.
In your question, you have mapped 127.0.0.1:30303
to be accessed externally through port 30303
. The 127.0.0.1
IP address is a localhost addresses that normally does not allow communication from outside the operating system. Please check for the non-127.0.0.1
IP address by using ifconfig -a
within your Docker containers to determine what your non-localhost IP addresses are. Try using these IP addresses to communicate across the Docker containers.
References
Check Connectivity
Get the IP address from within Container #1 using ifconfig -a
:
ifconfig -a
lo ...
inet addr:127.0.0.1 ...
...
docker0 ...
inet addr:192.168.0.1
Run geth
on port 30303 in Container #1 as shown in the next section (or as you documented in your Question).
From Container #2 or the host, you should be able to run the following command - you will have to hit Control-C to teminate the connection:
user@Kumquat:~$ telnet 192.168.0.1 30303
Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.
If your IP address is not set up to receive your connection attempt, your results should look like:
user@Kumquat:~$ telnet 192.168.0.1 30303
Trying 192.168.0.1...
telnet: Unable to connect to remote host: No route to host
If your IP address is correct, but your port is not mapped correctly, you should see:
user@Kumquat:~$ telnet 192.168.0.1 30303
Trying 192.168.0.1...
telnet: Unable to connect to remote host: Connection refused
Configure geth
Configure geth
with the basic parameters so we can verify that it is working as expected, without the P2P connection between the Docker containers. You will firstly need to configure two accounts to test your mining.
New Accounts
In Container #1, run the following command twice to create two new accounts:
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}
Data related to your account (in encrypted format) is stored in your --datadir
directory under the subdirectory keystore
. Make sure that you back these files up (and remember your password) if you are using this account in the main Ethereum network.
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
And the same in Container #2, using the --datadir
for Container #2.
Run geth
Miner
Run the following command in Container #1, and you should see messages like the ones listed below:
geth --datadir "/tempdatadir1" --port "30303" \
--genesis genesis.json --networkid 6161 \
--mine --minerthreads 1 console
Same for Container #2:
geth --datadir "/tempdatadir2" --port "30304" \
--genesis genesis.json --networkid 6161 \
--mine --minerthreads 1 console
The messages you should be seeing follow:
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
Sending An Ether From Account #1 to Account #2
In each container, run the sendTransaction
command in the geth
console. You mining operation should be adding ethers to eth.accounts[0] (first account, also called coinbase). This command will send an ether from eth.accounts[0] to eth.accounts[1]:
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: web3.toWei(1, "ether")})
"0xde465790a8ae4ce1aad3179d071ac49ed447c09199de26ce02327e8790e63e4b"
Wait for the transaction to be mined. Then run the getTransaction
command to check the transaction has been mined into a block:
> eth.getTransaction("0xde465790a8ae4ce1aad3179d071ac49ed447c09199de26ce02327e8790e63e4b")
{
...
blockNumber: 6266,
...
}
Check the account balance of eth.accounts[1]
:
> web3.fromWei(eth.getBalance(eth.accounts[1]), "ether")
1
Connect The geth
Instances
You will need to find the enode information for each geth
instance. I've shortened the long node public key from "d9d93b749257a1d4eaec18ab1c1ad39dc9220e449cfe248aceafc586193ead0ac14a088be5afb8455bd8f14bab7428162b8fbeda399ec748f5df0369789730d9" to "d9d9...30d9" for ease of reading - use the full version in your configuration.
In Container #1, run the following command in the geth ... console
:
> admin.nodeInfo
{
enode: "enode://d9d9...30d9@[::]:30303?discport=0",
...
}
Get the same information from geth
in Container #2.
In the Peer Discovery section below, replace [::] in your enode with the externally accessible IP address of your Docker container, and remove the ?discport=0
text.
Peer Discovery
You have 3 methods to get geth
in your Docker containers to connect to each other:
Bootnodes
In Container #1, add the --bootnodes
parameter to your geth
command line like, where "d9d9...30d9" needs to be replaced by the appropriate public key for geth
in Container #2:
geth --bootnodes "enode://[email protected]:30304" ...
In Container #2, you can add the similar parameters:
geth --bootnodes "enode://[email protected]:30303" ...
This will connect your geth
nodes for the initial peer discovery where they should discover each other an maintain a P2P connection.
static-nodes.json
Add the following text, replaced with your node information, in your --datadir
directory in a file named static-nodes.json
:
[
"enode://[email protected]:30304",
"enode://[email protected]:30303"
]
trusted-nodes.json
Same as static-nodes.json
above, but the node connections here do not count towards the --maxpeers
parameter if specified.
Try the different configuration styles until I find one that is stable for at least a few days.
Peer Discovery References
How To Run geth
In The Background
To run geth
as a background process, remove the console
parameter from your geth
command and append the &
symbol that will start the process in the background. As you may want to inspect the messages from geth
, you should pipe (send) the output from geth
into a log file.
This is how I do it:
Make a subdirectory logs
in your $HOME directory:
mkdir $HOME/logs
Set up a script file with your geth
command line option. I call mine runGeth
and save it in $HOME/bin
. Ths full filename is $HOME/bin/runGeth
, and this file contains:
#!/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 &
You will have to run the following command to make this script executable:
user@Kumquat:~$ chmod 700 $HOME/bin/runGeth
You can now start geth
running the script from your command line:
user@Kumquat:~$ runGeth
If this does not work, use the full pathname:
user@Kumquat:~$ $HOME/bin/runGeth
To attach to your geth
instance running in the background, use the command:
geth attach
This will use the IPC protocol to connect to the geth
instance running in the background.
If you want to connect to the geth
instance from your other Docker container, or from outside your Docker container, use the following command with the correct IP and port numbers:
geth attach rpc:http://192.XXX.XXX.XXX:8545
Note that the port 8545
is the default RPC port that can be set using the --rpcport {port}
command line parameter.
You can exit from these geth attach
processes without affecting the geth
instance running in the background.
And as I don't like typing out long command line parameters, I create the file $HOME/bin/attachGeth
with the following contents:
#!/bin/sh
geth attach rpc:http://192.XXX.XXX.XXX:8545
And chmod 700 $HOME/bin/attachGeth
so I can attach to the background running geth
using the command attachGeth
or $HOME/bin/attachGeth
.
To view the log files from the geth
instance running in the background:
tail -F $HOME/logs/geth.log
Hit Control-C to terminate this process.