[Ethereum] How to completely automate a Docker image and Dockerfile for a geth test network

dockergo-ethereum

I would like to create a Docker image for a test network that has everything ready to go – pre-created accounts with ether already allocated.

The problem is there doesn't seem to be a way to do this the Docker Way(tm). In order to create ether out of thin air, I have to put addresses in the genesis.json 'alloc' section. In order to get the addresses, I have to create accounts with multiple invocations of geth and then manually edit genesis.json. Manual steps are not the Docker Way(tm), you are supposed to create a Docker file that does all these steps automatically.

My current best bet seems to be to to create a script that creates the accounts I need and the gets the account addresses from the geth command line option for that and then edits genesis.json on the fly. That seems… rather crude, and adds more tools to the docker image to do this (at least something that can parse JSON). Creation of accounts is not idempotent, so I can't just run the same script every time I start the container.

I'm sure the geth community has solved this problem for their own automated testing. Please share 🙂

I've read everything on the first page of this Google Search. They all have manual steps, which doesn't work for automation that Docker and automated test systems demand.

Best Answer

Here's the steps I used to create a Docker image that recreates a consistent test environment:

  1. Create a Docker file (see listing below) with empty geth data directory and files as noted in the Docker file. Also set up directory structure as noted in Docker file below.
  2. user docker build -t ethereum/client-go:test . to build an image
  3. start a container, login by overriding entrypoint with bash: docker run -i -t --entrypoint "/bin/bash" ethereum/client-go:test
  4. Start geth using the script noted in the dockerfile
  5. create required accounts for your testing environment (e.g. via console)
  6. edit genesis.json so that those accounts are pre-allocated with ether
  7. verify via geth console that the accounts are there, with ether allocated
  8. stop geth.
  9. user docker cp to copy off the entire contents of /root/.ethereum to your host to the directory noted in the Dockerfile below.
  10. stop and remove your container.
  11. run docker build to create a new image. The new image now has the saved off starting state that can be reproduced as needed for your test environment.
  12. I suggest using a volume for /root/.ethereum so that you don't lose data if geth restarts for some reason. See Docker documentation

The Dockerfile:

FROM ethereum/client-go

# our own custom bult geth that mines really fast
COPY geth /usr/bin/geth

# script that invokes with all those
# command line options
COPY rungeth.docker /usr/bin/rungeth

# these two files and directory of geth state belong together and must be 
# kept in sync if changes  are ever made
# Note we are taking advantage of Docker's copy-on-mount feature
COPY geth.password /root/geth.password
COPY genesis.json  /root/genesis.json
COPY ethereum /root/.ethereum

ENTRYPOINT []
ENTRYPOINT [/usr/bin/rungeth]

# use non-standard ports so don't accidently connect to real servers
# XXX Docker inheritance doesn't override, it extends the port      list...
EXPOSE 8110
EXPOSE 30310
EXPOSE 6110

I will attempt at some point to put an image on dockerhub so you don't have to do the above save run it.

Here's the script I use to build a docker container:

#!/bin/bash
docker build -t ethereum/client-go:test .

Here's the script I use to run a docker container instance.

#!/bin/bash
docker run --name geth -d -p 8110:8110  --entrypoint "usr/bin/rungeth" --volumes-from gethdb  ethereum/client-go:test

and the script that runs geth in the container:

#!/bin/bash
/usr/bin/geth --datadir /root/.ethereum --password /root/geth.password --unlock "0 1 2 3 4 5" --port 30310 --rpc --rpcaddr "0.0.0.0" --rpcport 8110 --networkid 4567890 --dev --lightkdf --nodiscover --maxpeers 0 --vmdebug --verbosity 6 --pprof --genesis /root/genesis.json --gpomin "50" --gpomax "50" --pprofport 6110 --mine --minerthreads 1 2> /tmp/geth.log