How to use docker to setup multiple bitcoin test nodes on your own MAC? (Phase I — bitcoind)
If you are new to bitcoins or docker , keep reading, this is for you.
What is bitcoin? Bitcoin (₿) is a cryptocurrency, a form of electronic cash. It is a decentralized digital currency without a central bank or single administrator that can be sent from user-to-user on the peer-to-peer bitcoin network without the need for intermediaries. For more technical details, read the wiki, or read the source code.
What is docker? Docker is a computer program that performs operating-system-level virtualization, also known as “containerization”. If you want to learn more about docker go read www.docker.com
If you are still interested in knowing how to have docker containers and bitcoin nodes together, keep reading.
Why do we need docker to test bitcoin? If you just want to see how bitcoin works from user point of view, go to App Store (or google play store) download any wallet with good reviews. Ask your friends send you couple bitcoins then play with it. I know bitcoin is over $6000 as of this post is written, so it has to be a really good friend who is willing to send you couple bitcoins. (In fact, you can send a portion of the bitcoin, for example 0.00076 for around $5, no need for a whole bitcoin to test your friendship).
However, if you are developer or sysadmin that want to setup a node that join the bitcoin network, you will need to do some test from time to time. During your testing, containerization of your test environment is super useful when you want to have multiple nodes setup. Bitcoin itself technically is just a protocol. There are different implementations with different languages (C++ or GOLANG or JAVA) with different code bases. Each different implementation will have different type of configuration files and run time binaries. Putting all of these on a same computer without segregation is very messy and could run into serious problem later on in your testing.
So the short answer is, put each node into a container.
Why do I need the source code? There is already binaries I can download and just run, correct? Yes and No. With source code, it’s just easier. By getting source code from GitHub and compile yourself, it’s much cooler than downloading the binaries produced by someone else and get a trojan virus within it. Plus, you said you are a developer right? 😛
Why it’s on simnet or regtest? Bitcoin mainnet is SLOW. Not the network is slow, it’s the data size, as of the time this post is written, it took 230GB disk space to store the blockchain database, it will take 1 to 3 days to download the data depends on where your computer is and how good is your ISP, not many people are willing to pay for the extra storage (for example, digitalocean charges $20 extra a month for 250GB storage). Running test on simnet or regtest can start just from genesis block, then you can mine as many blocks as you wanted for your testing, it’s done within seconds. (Hey, you also get a chance to create your own genesis block, that’s even nicer)
So seriously, how do I do it? There will be 2 post, this is first one: (phase I), we will cover how to do to it using the most popular client (by bitcoin-core team: bitcoin’s c++ implementation), known as “bitcoind”
To setup bitcoind in container. All you need is a Dockerfile to build a container image.
- If you don’t have docker installed already, on your MAC install docker by this link:https://docs.docker.com/docker-for-mac/install/, if you are on Windows, well too bad, this post doesn’t cover Windows.
- Create Dockerfile with these as the content:
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install build-essential autoconf libtool pkg-config libboost-all-dev libssl-dev libprotobuf-dev protobuf-compiler libevent-dev libqt4-dev libcanberra-gtk-module libdb-dev libdb++-dev bsdmainutils -y
WORKDIR /src/bitcoin
COPY ./bitcoin .
RUN ./autogen.sh
RUN ./configure --with-incompatible-bdb
RUN make
RUN make install
RUN mkdir -p /root/bitcoind-simnet/
- Now get to the same folder of your docker file, in command line, run git clone command: this will get the bitcoin-core source code into ./bitcoin folder.
git clone https://github.com/bitcoin/bitcoin.git
- Create a file called docker-compose.yml, here is the content:
version: '3'
services:
node1:
build: .
cap_add:
- ALL
command: bitcoind -regtest -server -addnode=10.7.0.12:12345 -addnode=10.7.0.13:12345 -addnode=10.7.0.14:12345 -rpcuser=rpc -rpcpassword=x -rpcport=10340 --datadir=/root/bitcoind-simnet/ -port=12345
networks:
vpcbr:
ipv4_address: 10.7.0.11
node2:
build: .
cap_add:
- ALL
command: bitcoind -regtest -server -addnode=10.7.0.11:12345 -addnode=10.7.0.13:12345 -addnode=10.7.0.14:12345 -rpcuser=rpc -rpcpassword=x -rpcport=10340 --datadir=/root/bitcoind-simnet/ -port=12345
networks:
vpcbr:
ipv4_address: 10.7.0.12
node3:
build: .
cap_add:
- ALL
command: bitcoind -regtest -server -addnode=10.7.0.12:12345 -addnode=10.7.0.11:12345 -addnode=10.7.0.14:12345 -rpcuser=rpc -rpcpassword=x -rpcport=10340 --datadir=/root/bitcoind-simnet/ -port=12345
networks:
vpcbr:
ipv4_address: 10.7.0.13
node4:
build: .
cap_add:
- ALL
command: bitcoind -regtest -server -addnode=10.7.0.11:12345 -addnode=10.7.0.13:12345 -addnode=10.7.0.12:12345 -rpcuser=rpc -rpcpassword=x -rpcport=10340 --datadir=/root/bitcoind-simnet/ -port=12345
networks:
vpcbr:
ipv4_address: 10.7.0.14
networks:
vpcbr:
driver: bridge
ipam:
config:
- subnet: 10.7.0.0/16
- Why do you need it? Because if you want multi-node setup, you don’t want to repeat the steps manually each time. Plus, running command of
docker-compose up
1 time is much easier than typingdocker run your-container name
4 times. - Now it’s the fun part, just run
docker-compose build
, if the build fail, debug yourself, or post the log to me, I can help you without charge. 😐 - The build command is very slow, mostly due to the first time running
make
for the cpp codebase, any incremental changes should take much shorter time to build. - Then
docker-compose up
, your 4 node setup is up and running. You will see similar output as this:
- Connect to one of the container: By running the following command
docker ps
you will see what containers you are running.
- Then docker exec:
docker exec -it test-for-blog-post_node1_1 bash
, this will get you into one of the running containers. You can run bitcoin-cli command to get basic information of your blockchain network, for example:
root@0306b4c92df0:/src/bitcoin# bitcoin-cli -regtest -rpcuser=rpc -rpcpassword=x -rpcport=10340 getblockchaininfo
{"chain": "regtest","blocks": 0,"headers": 0,"bestblockhash": "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206","difficulty": 4.656542373906925e-10,
How do you mine some blocks? First of all, why do you want to mine? Isn’t it a privilege of people who control cheap electricity and access to ASIC hardware? (IMO, current miners are so much centralized) Oh wait, this a private testnet, there is no other people, there is just you, so you have to mine the blocks to keep it going. Run the mine command.
bitcoin-cli -regtest -rpcuser=rpc -rpcpassword=x -rpcport=10340 generate 2
This command should generate 2 blocks for you. Now run the command to see if you get paid (which is most important, right?)
bitcoin-cli -regtest -rpcuser=rpc -rpcpassword=x -rpcport=10340 listaddressgroupings
Surprise, your balance is 0, shouldn’t you get paid with 100 bitcoin? (50 for each block you mine). Because there is a 100 maturation blocks you need to wait, so do the same command for mining with 200 blocks, now run the wallet command again, you will see your balance. Once you have bitcoin in your wallet, you can create different addresses and send them around. For example:
bitcoin-cli -regtest -rpcuser=rpc -rpcpassword=x -rpcport=10340 sendtoaddress myUFjFMpchpdpf19Yh6BVVJoNoxDJtDLL9 200
The command above will send 200 to address: myUFjFMpchpdpf19Yh6BVVJoNoxDJtDLL9
Conclusion: We have done a setup of multiple-node regtest network of bitcoin with docker containers, using bitcoind (c++ based).
Want to have another implementation setup? We will talk about GOLANG implementation in our next post (Phase II).