EOS Dev Guide 0x04 - Docker Image

This will guide you through running nodeos, cleos, eosiocpp in gdb-peda using its docker images.
There's some points you need to pay attention to.

Build and Run Docker Image

docker pull

$ docker pull eosio/eos

add vim / gdb to the docker

if you want to debug the nodeos or cleos, you might want gdb-peda within the docker.

You could use this dockerfile to build one more layer upon the eos image.

It first installed gdb, peda, git, then setup nodeosd-gdb.sh to run nodeos inside gdb, which will appear in alias later.

FROM eosio/eos
RUN apt-get update && apt-get install -y vim gdb git &&\
    git clone https://github.com/longld/peda.git /opt/peda && \
    echo "source /opt/peda/peda.py" >> ~/.gdbinit && \
    cp /opt/eosio/bin/nodeosd.sh /opt/eosio/bin/nodeosd-gdb.sh && \
    sed -i -e 's/\/opt\/eosio\/bin\/nodeos/gdb\ --args\ \/opt\/eosio\/bin\/nodeos/g' /opt/eosio/bin/nodeosd-gdb.sh

Save the dockerfile code as Dockerfile, put it in some dir.
Then build it:

$ docker build /dir/of/the/Dockerfile/ -t xhyumiracle/eos

NOTE: use the exact name for Dockerfile. But you could replace xhyumiracle/eos with other words, this is the name and tag for the newly created image.

start docker

$ docker run -it --rm --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -v `pwd`:/tmp xhyumiracle/eos

We need --cap-add=SYS_PTRACE --security-opt seccomp=unconfined to solve the ASLR problem.

And -v flag will mount current directory of host to /tmp inside container.

Now you should get an interactive shell of the container.

start nodeos inside gdb

run this command inside the container shell:

$ gdb --args nodeos -e -p eosio --contracts-console

Then type r in gdb, the nodeos should be running now.

file locations

$ which nodeos
/opt/eosio/bin/nodeos
$ find / -name config.ini
/root/.local/share/eosio/nodeos/config/config.ini
/config.ini

Setup nodeos and cleos in Two Container

For now, we have nodeos and cleos available inside the docker container, next, we want to give alias to docker run xhyumiracle/eos nodeos... and docker run xhyumiracle/eos cleos... so that we can use them as two handy commands in the host bash.

To achieve that, we need to seperate them to two containers. And create docker compose to setup their network communication between each other.

the compose file

Here is my docker-compose.yml:

version: '2'
services:
  nodeosd:
    image: xhyumiracle/eos
    #entrypoint: "/opt/eosio/bin/nodeosd.sh --data-dir /opt/eosio/bin/data-dir -e -p eosio --contracts-console" # commented this out because I want to use nodeosd.sh or nodeosd-gdb.sh
    hostname: nodeosd
    cap_add:
      - SYS_PTRACE
    security_opt:
      - seccomp:unconfined
    networks:
      - eos_network
    ports:
      - 8888:8888
      - 9876:9876
    expose:
      - "8888"
    volumes:
      - /tmp/data-volumes/nodeos-data-volume:/opt/eosio/bin/data-dir

  cleos:
    image: xhyumiracle/eos
    #entrypoint: cleos
    hostname: cleos
    networks:
      - eos_network
    volumes:
      - /tmp/data-volumes/cleos-data-volume:/root

  eosiocpp:
    image: eosio/eos-dev
    entrypoint: eosiocpp
    hostname: eosiocpp
    networks:
      - eos_network
    volumes:
      - /tmp/data-volumes/cleos-data-volume:/root

  keosd:
    image: xhyumiracle/eos
    command: /opt/eosio/bin/keosd --wallet-dir /opt/eosio/bin/data-dir --http-server-address=127.0.0.1:8900
    hostname: keosd
    networks:
      - eos_network
    volumes:
      - /tmp/data-volumes/keosd-data-volume:/opt/eosio/bin/data-dir

networks:
  eos_network:
    driver: bridge

Here we are mapping /tmp/data-volumes/.. to the two containers, you could modify it based on your needs as long as you remember to modify the corresponding part in the following commands.

add alias

Then add alias to these two services:

$ alias nodeos='docker-compose -f /path/to/docker-compose.yml run --rm nodeosd'
$ alias nodeos-clear='rm -r /tmp/data-volumes/nodeos-data-volume'
$ alias cleos='docker-compose -f /path/to/docker-compose.yml run --rm cleos cleos'
$ alias cleos-bash='docker-compose -f /path/to/docker-compose.yml run --rm cleos bash'

You could place the alias to ~/.zshrc and $ source ~/.zshrc.

  • nodeos, cleos to run these two containers.
  • Run nodeos-clear when nodeos could not start and needs a refresh.
  • Run cleos-bash to open bash. Because the wallet state may not easy to keep if --rm cleos after everytime stop.

access container from another container

Next, we need to find out the internal address of nodeos so that the cleos could access it.

  • First, start nodeos.

  • Then type the following cmd:

$ docker network inspect  eoscompose_eos_network
[
    {
        "Name": "eoscompose_eos_network",
        ...
        "Containers": {
            "c785b5dca4a617c53c12b90b2db532011aae89cc191c22ead872297a77a9ec92": {
                "Name": "eoscompose_nodeosd_run_11",
                "EndpointID": "...",
                "MacAddress": "...",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]

Here the ip was 172.18.0.2. Thus, add it when using cleos.

To test it:
$ cleos -u http://172.18.0.2:8888 get info

data locations

You'll find that the blockchain data is in /tmp/data-volumes/nodeos-data-volume, after you run nodeos
And the wallet data is in /tmp/data-volumes/cleos-data-volume, after you run cleos wallet create

not that important

you could add -u http://172.18.0.2:8888 to the alias so that you won't type it everytime.

Setup eosiocpp

eosiocpp is a tool to compile .cpp contract to .wasm and .wast midware, which are the accept format for nodeos.

According to https://github.com/EOSIO/eos/tree/master/Docker#developbuild-custom-contracts, eosiocpp was not included in the current eosio/eos:latest image, we need to pull another docker image:

$ docker pull eosio/eos-dev

make it easy to use

$ mkdir eosiocpp
$ cat <<EOF >> Dockerfile
FROM eosio/eos-dev
RUN p=$(which eosiocpp) && d=$(dirname $p) &&\
    echo '#!/bin/sh\ncd /tmp\neosiocpp "$@"' > $d/_eosiocpp.sh && \
    chmod +x $d/_eosiocpp.sh
EOF
$ docker build . -t xhyumiracle/eosiocpp
$ alias eosiocpp='docker run -v `pwd`:/tmp -it --rm xhyumiracle/eosiocpp _eosiocpp.sh'

As said, you could always place the alias in ~/.zshrc and $ source ~/.zshrc.

Then type eosiocpp, it should work.

The input/output directory is the currenty dir in the host. (because we've mounted it)

To test it:
$ eosiocpp -n mycontract

That's it. Hope you like it.

EOS Dev Guide 0x04 - Docker Image
Share this