Docker usage in Blockchain

Johannes Bertens
oneupcompany
Published in
8 min readMay 24, 2018
Container terminal in Hamburg, Germany

Docker is the single most important tool when developing blockchain applications.

Why?
When you are developing blockchain applications,

  1. … you are creating a distributed application, locally.
  2. … you need automation to reduce the time spent on error-prone steps involved in deploying and testing.
  3. … you want to test your application with real users as soon as possible!

These factors, and many more, make Docker an invaluable tool in your toolkit. Not only is Docker a tool to ease your development, it also enables and encourages a different way of working — a way of working which lowers technical debt and increases agility (the reaction speed to changing environments).

The Docker logo is a Whale carrying containers (like a container ship)

What is Docker?

Docker is a container platform — much like the containers found on container ships — which enables the creation, shipment and deployment of small, self-contained, software components. These components can then be combined to create a service offering (SaaS), web or mobile application (app), or distributed blockchain application (dApp).

The Docker engine (Community Edition or CE) is free of use and runs on nearly every platform. Installing it is easy, just download and run the installer found on the Docker docs page. Once it is installed, creating and running Docker containers is just a matter of entering ‘docker run <image>’ from the command line, where <image> is the name of the image published on the Docker Hub. A private image can also be run, by prepending the image name with the name of the private or local hub.

It’s time to code! (Photo by Hitesh Choudhary on Unsplash)

How can I create my own Docker Image?

After installing Docker and running the ‘hello world’ example, it is time to create your first image and run it. Before you alt-tab out of here: this is easier than it sounds! All you need, is a single text-file called ‘Dockerfile’. These are the steps to follow:

  1. Create a new folder, called ‘my-first-docker-image’ for example.
  2. Create a file in this folder, called ‘Dockerfile’ (exact naming, no extension)
  3. Open this file, and enter the following 2 lines of text:
FROM python:2
CMD [ "python","-c", "print '\\n'.join(\"%i Byte = %i Bit = largest number: %i\" % (j, j*8, 256**j-1) for j in (1 << i for i in xrange(8)))" ]

4. Save & close the file, then execute docker build -t python-test .

5. After a while (some base images will be downloaded), your image is built and ready to use! Enter the following command to get it up and running: docker run -it --rm python-test

The output should be:

1 Byte = 8 Bit = largest number: 255
2 Byte = 16 Bit = largest number: 65535
4 Byte = 32 Bit = largest number: 4294967295
(...)

Even without any version of python installed on your local machine (this command itself also does not install python), the script is executed and its result shown in your terminal.

Some explanation of the commands used in these steps:

docker = The keyword to execute docker-related commands

docker build = Builds new docker images. You can give them a name (python-test in our example) with the -t option and it requires a path to the Dockerfile ( . in our example)

docker run = Runs docker images. You can use -it to attach an (interactive) terminal to the docker container and --rm to automatically remove the container when it finishes. An identifier for the image to run is required (again python-test in our example).

Speeding up like Usain… no Daphne! :)

How do I speed up blockchain application development using Docker?

So now we have Docker installed and can download, build and run docker containers, we are ready for the next step: speeding up blockchain application development using Docker.

First up, it is important to see that there are 3 distinct components that interact in a basic blockchain application, namely:

  • A web interface (we’ll use Vue from https://vuejs.org/)
  • Smart contracts + tests and deployment (we’ll use the Truffle framework from http://truffleframework.com/)
  • An Ethereum node, a test-node for now (we’ll use ganache-cli, also from the Truffle framework)

These 3 components are a perfect fit for independent Docker containers, so let’s get started!

Step 0: NPM init
First, create a new folder for this project. I’ve called it minimal-blockchain-docker, but you’re free to be more creative of course.

Then run npm init in this folder and just go with all the default answers.

Step 1: Creating the UI using Vue
Create a services folder and navigate to it using the command line, install the Vue CLI (https://github.com/vuejs/vue-cli) if you haven’t done so yet and initialise the web interface:

npm install -g @vue/cli
# or
yarn global add @vue/cli

vue create ui

The output should look like the following snippet:

(...)
🎉 Successfully created project ui.
👉 Get started with the following commands:
$ cd ui
$ yarn serve

You can do this, if you want to check if the standard Vue page gets hosted correctly and works out of the box. (it should!)

We now have a working UI component. Yay! 🍾

Step 2: Create some smart contracts
Let’s get working on thew smart contracts now, it’s the heart of our blockchain application!

First, go back to the services folder, and create a smart-contracts subfolder in which we init a basic Truffle project (after installing Truffle, if we haven’t done so yet):

npm install -g trufflemkdir smart-contracts
cd smart-contracts
truffle unbox metacoin

There we go, we now have a boilerplate smart contract in solidity, ready to compile and run!

The compilation of the contract we can already do by executing truffle compile . At the time of writing, this gives some deprecation warnings on the boilerplate code, but it does compile (which is good!).

To actually run the code, we also need a testing environment to run this on… so let’s create one!

Step 3: Install and run Ganache-CLI
This one is a bit different from the other two components: we are just going to run it out of the box (kinda).

What is Ganache-CLI? (https://github.com/trufflesuite/ganache-cli)
It’s a test framework on which we can deploy our smart contracts and use to test our blockchain application. Installation and running it is straightforward:

npm install -g ganache-cli
ganache-cli

So, once this is running you can then

  • “Migrate” the smart contracts, and,
  • Start the UI

However, if you change a smart contract — it is required to restart ganache-cli, compile and migrate the solidity contracts and restart the UI (if needed). That’s a hassle?! Also — if you host this software somewhere or want to run it on a different machine for any reason, you have to go through all these steps again.

We can do better than this!

Step 4: Putting it all together in a single docker-compose file
Docker-compose (https://docs.docker.com/compose/) is a tool for running multi-container Docker applications.

Having each component “Dockerized”, we can now put it together in a docker-compose.yml file. In docker-compose files, one defines different services, and their dependencies and interactions. For the previously mentioned docker images, our docker-compose.yml file looks like this:

version: '3'

services:
# gateway/reverse proxy
nginx:
build: ./services/nginx
restart: always
depends_on:
- api
- ui
- ganache
volumes:
- ./logs:/var/log/nginx
ports:
# proxy api + ui
- "80:9000"
# proxy ethereum node so you can connect with metamask from browser
- "8545:9001"

# starts webpack watch server with hot reload for ui (vue) code
ui:
build:
context: ./services/ui
dockerfile: Dockerfile.development
restart: always
env_file:
- ./services/ui/.env
volumes:
- ./services/ui/src:/app/ui/src/
- ./logs:/logs

# api, handles browser requests initiated from ui api:
api:
build:
context: ./services/api
dockerfile: Dockerfile.development
restart: always
env_file:
- ./services/api/.env
depends_on:
- mongo
volumes:
- ./services/api/src:/app/api/src/
- ./logs:/logs

# smart contracts source, tests and deployment code
smart-contracts:
build:
context: ./services/smart-contracts
dockerfile: Dockerfile.development
env_file:
- ./services/smart-contracts/.env
depends_on:
- ganache
volumes:
# mount the output contract build files into a host folder
- ./services/smart-contracts/src/build:/app/smart-contracts/build/
# mount the output test coverage report folder into a host folder
- ./services/smart-contracts/coverage-report:/app/smart-contracts/coverage/
- ./logs:/logs

# ganache-cli ethereum node
ganache:
image: trufflesuite/ganache-cli
command: "--seed abcd --defaultBalanceEther 100000000"

# mongodb
mongo:
build: ./services/mongodb
restart: always
ports:
# allow acces from (only!) localhost to mongo port 27017 so you can use
# MongoHub or some other app to connect to the mongodb and view its contents
- "127.0.0.1:27017:27017"
volumes:
- ./data/mongo:/data/db
- ./logs:/var/log/mongodb

Tip: this file is also accessible in our Github page: docker-compose.yml

Building and starting these docker images is as simple as running docker-compose up . Try it! 🚀
Tip: to hide all the output, you can use the -d flag, after which you can check the separate logs with docker logs xxx where xxx is the name of the instance.

This fixes us having to start all the containers ourselves, but we still need to find a way to automate the building and deployment of the solidity smart contracts. For this, we use the NPM scripting language:

(...)
"start": "npm run deploy:smart-contracts && docker-compose up --build nginx api ui ganache mongo",
(...)

Tip: All of the scripts are in the package.json file in our Github repository.

This can be started with the npm run start command! The single command needed to start the boilerplate. Stopping the boilerplate is also simple, by using the npm run stop command. (yarn start and yarn stop also work)

All changes made to the code will automatically reflect in the running dApp due to shared folders 😃

That’s it, we’ve automated pretty much everything to get this running on your laptop (or any other laptop or VM). So…

Photo by Denys Nevozhai on Unsplash

Where do I go from here?

Well, next step is to get this into production and monitor the running dApps.

Next blog we will get into how we can run these containers (and the smart contracts) on a Kubernetes cluster!

If you spot any errors, or have any suggestions on improvements: please leave either a comment here, or at the Github page.

--

--