From 7c5d5699bf2c2253e27204c66867a0e14ab909ec Mon Sep 17 00:00:00 2001 From: "Andreas M. Antonopoulos" Date: Wed, 10 Jun 2020 22:46:55 -0400 Subject: [PATCH] Docker and docker-compose Build network, create keys/addresses, fund wallets. --- code/docker/bitcoind-base/Dockerfile | 41 +----- code/docker/bitcoind-regtest/Dockerfile | 33 ++--- .../bitcoind-regtest/bitcoind/bitcoin.conf | 14 +- .../bitcoind/bitcoind-start.sh | 12 ++ .../bitcoind/keys/demo_address.txt | 1 + .../bitcoind/keys/demo_mnemonic.txt | 1 + .../bitcoind/keys/demo_privkey.txt | 1 + code/docker/bitcoind-regtest/bitcoind/mine.sh | 16 ++ code/docker/devenv/Dockerfile | 60 ++------ code/docker/docker-compose/docker-compose.yml | 16 -- code/docker/lnbook-app/docker-compose.yml | 18 +++ code/docker/lnd-base/Dockerfile | 6 +- code/docker/lnd-run/Dockerfile | 8 +- code/docker/lnd-run/lnd/fund-lnd.sh | 21 +++ code/docker/lnd-run/lnd/lnd-start.sh | 3 + code/docker/lnd-run/lnd/lnd.conf | 15 +- node_client.asciidoc | 138 +++++++++--------- 17 files changed, 200 insertions(+), 204 deletions(-) create mode 100644 code/docker/bitcoind-regtest/bitcoind/bitcoind-start.sh create mode 100644 code/docker/bitcoind-regtest/bitcoind/keys/demo_address.txt create mode 100644 code/docker/bitcoind-regtest/bitcoind/keys/demo_mnemonic.txt create mode 100644 code/docker/bitcoind-regtest/bitcoind/keys/demo_privkey.txt create mode 100755 code/docker/bitcoind-regtest/bitcoind/mine.sh delete mode 100644 code/docker/docker-compose/docker-compose.yml create mode 100644 code/docker/lnbook-app/docker-compose.yml create mode 100644 code/docker/lnd-run/lnd/fund-lnd.sh create mode 100644 code/docker/lnd-run/lnd/lnd-start.sh diff --git a/code/docker/bitcoind-base/Dockerfile b/code/docker/bitcoind-base/Dockerfile index e619f1b..72f97e2 100644 --- a/code/docker/bitcoind-base/Dockerfile +++ b/code/docker/bitcoind-base/Dockerfile @@ -1,44 +1,7 @@ -FROM ubuntu:18.04 +FROM ubuntu:18.04 AS bitcoind-base ENV BITCOIND_VERSION 0.20.0 - -# # Install development tools prerequisites -# RUN apt-get update && apt-get install -y \ -# build-essential \ -# libtool \ -# autotools-dev \ -# automake \ -# pkg-config \ -# python3 \ -# wget \ -# git \ -# curl \ -# unzip - -# # Install additional Bitcoin Core (bitcoind) requirements -# RUN apt-get install -y \ -# libssl-dev \ -# libevent-dev \ -# bsdmainutils \ -# libboost-system-dev \ -# libboost-filesystem-dev \ -# libboost-chrono-dev \ -# libboost-test-dev \ -# libboost-thread-dev \ -# libminiupnpc-dev \ -# libzmq3-dev - -# # Install software-properties-common to add apt repositories -# RUN apt-get install -y \ -# software-properties-common -# -# # Add Bitcoin Core PPA repository -# RUN add-apt-repository ppa:bitcoin/bitcoin -# RUN apt-get update && apt-get install -y \ -# bitcoind - - # Install binaries for Bitcoin Core ADD https://bitcoincore.org/bin/bitcoin-core-${BITCOIND_VERSION}/bitcoin-${BITCOIND_VERSION}-x86_64-linux-gnu.tar.gz /usr/local RUN cd /usr/local/ \ @@ -46,7 +9,7 @@ RUN cd /usr/local/ \ && cd bitcoin-${BITCOIND_VERSION} \ && install bin/* /usr/local/bin \ && install include/* /usr/local/include \ - && install -v lib/* /usr/local/lib + && install -v lib/* /usr/local/lib # Confirm installation RUN bitcoind -version diff --git a/code/docker/bitcoind-regtest/Dockerfile b/code/docker/bitcoind-regtest/Dockerfile index 736896f..21f49ea 100644 --- a/code/docker/bitcoind-regtest/Dockerfile +++ b/code/docker/bitcoind-regtest/Dockerfile @@ -1,26 +1,17 @@ -FROM lnbook/bitcoind_base:latest +FROM lnbook/bitcoind-base:latest ADD bitcoind /bitcoind -WORKDIR /bitcoind RUN ln -s /bitcoind /root/.bitcoin -EXPOSE 12001 +# bitcoind P2P +EXPOSE 18444/tcp +# bitcoind regtest RPC +EXPOSE 18443/tcp +# zmqpubrawblock +EXPOSE 12005/tcp +# zmqpubrawtx +EXPOSE 12006/tcp -CMD bitcoind -datadir=/bitcoind -daemon \ - && sleep 2 \ - && export address=$(bitcoin-cli -datadir=/bitcoind getnewaddress) \ - && export privkey=$(bitcoin-cli -datadir=/bitcoind dumpprivkey $address)\ - && echo "Mining 101 blocks to unlock some bitcoin" \ - && bitcoin-cli -datadir=/bitcoind generatetoaddress 101 $address \ - && echo "================================================"\ - && echo "Mining to bitcoin address: " ${address} \ - && echo "Private key: " ${privkey} \ - && echo "Balance: " `bitcoin-cli -datadir=/bitcoind getbalance` \ - && echo "================================================"\ - && echo "Configuration:" \ - && cat /bitcoind/bitcoin.conf \ - && echo "================================================"\ - && echo "Use the command below to mine new blocks and progress the chain:"\ - && echo "bitcoin-cli -datadir=/bitcoind generatetoaddress 1" $address \ - && echo "================================================"\ - && bash +WORKDIR /bitcoind +CMD /bin/bash /bitcoind/bitcoind-start.sh \ + && /bin/bash /bitcoind/mine.sh diff --git a/code/docker/bitcoind-regtest/bitcoind/bitcoin.conf b/code/docker/bitcoind-regtest/bitcoind/bitcoin.conf index 2577ef0..d9a6c3c 100644 --- a/code/docker/bitcoind-regtest/bitcoind/bitcoin.conf +++ b/code/docker/bitcoind-regtest/bitcoind/bitcoin.conf @@ -1,15 +1,21 @@ regtest=1 -dnsseed=0 -upnp=0 server=1 debuglogfile=debug.log debug=1 printtoconsole=0 [regtest] -port=12000 -rpcport=12001 +fallbackfee=0.000001 +port=18444 +noconnect=1 +dnsseed=0 +dns=0 +upnp=0 +onlynet=ipv4 +rpcport=18443 rpcbind=0.0.0.0 rpcallowip=0.0.0.0/0 rpcuser=regtest rpcpassword=regtest +zmqpubrawblock=tcp://0.0.0.0:12005 +zmqpubrawtx=tcp://0.0.0.0:12006 diff --git a/code/docker/bitcoind-regtest/bitcoind/bitcoind-start.sh b/code/docker/bitcoind-regtest/bitcoind/bitcoind-start.sh new file mode 100644 index 0000000..e0e5a8b --- /dev/null +++ b/code/docker/bitcoind-regtest/bitcoind/bitcoind-start.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +bitcoind -datadir=/bitcoind -daemon +sleep 5 +export address=`cat /bitcoind/keys/demo_address.txt` +export privkey=`cat /bitcoind/keys/demo_privkey.txt` +echo "================================================" +echo "Importing demo private key" +echo "Bitcoin address: " ${address} +echo "Private key: " ${privkey} +echo "================================================" +bitcoin-cli -datadir=/bitcoind importprivkey $privkey diff --git a/code/docker/bitcoind-regtest/bitcoind/keys/demo_address.txt b/code/docker/bitcoind-regtest/bitcoind/keys/demo_address.txt new file mode 100644 index 0000000..ae62ea3 --- /dev/null +++ b/code/docker/bitcoind-regtest/bitcoind/keys/demo_address.txt @@ -0,0 +1 @@ +2NBKgwSWY5qEmfN2Br4WtMDGuamjpuUc5q1 diff --git a/code/docker/bitcoind-regtest/bitcoind/keys/demo_mnemonic.txt b/code/docker/bitcoind-regtest/bitcoind/keys/demo_mnemonic.txt new file mode 100644 index 0000000..37f503c --- /dev/null +++ b/code/docker/bitcoind-regtest/bitcoind/keys/demo_mnemonic.txt @@ -0,0 +1 @@ +electric flash rain cloud umbrella energy charge ozone air thunder crack wet diff --git a/code/docker/bitcoind-regtest/bitcoind/keys/demo_privkey.txt b/code/docker/bitcoind-regtest/bitcoind/keys/demo_privkey.txt new file mode 100644 index 0000000..6acc8df --- /dev/null +++ b/code/docker/bitcoind-regtest/bitcoind/keys/demo_privkey.txt @@ -0,0 +1 @@ +cSaejkcWwU25jMweWEewRSsrVQq2FGTij1xjXv4x1XvxVRF1ZCr3 diff --git a/code/docker/bitcoind-regtest/bitcoind/mine.sh b/code/docker/bitcoind-regtest/bitcoind/mine.sh new file mode 100755 index 0000000..42fdffd --- /dev/null +++ b/code/docker/bitcoind-regtest/bitcoind/mine.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +export address=`cat /bitcoind/keys/demo_address.txt` +export privkey=`cat /bitcoind/keys/demo_privkey.txt` +echo "================================================" +echo "Bitcoin address: " ${address} +echo "Private key: " ${privkey} +echo "Balance:" `bitcoin-cli -datadir=/bitcoind getbalance` +echo "================================================" +echo "Mining 101 blocks to unlock some bitcoin" +bitcoin-cli -datadir=/bitcoind generatetoaddress 101 $address +echo "Mining 1 block every 10 seconds" +while sleep 10; do \ + bitcoin-cli -datadir=/bitcoind generatetoaddress 1 $address; \ + echo "Balance:" `bitcoin-cli -datadir=/bitcoind getbalance`; \ +done diff --git a/code/docker/devenv/Dockerfile b/code/docker/devenv/Dockerfile index 8a1cee4..0342a11 100644 --- a/code/docker/devenv/Dockerfile +++ b/code/docker/devenv/Dockerfile @@ -1,62 +1,30 @@ # syntax = docker/dockerfile:1.0-experimental +# devenv Dockerfile (multi-state container) FROM ubuntu:18.04 -# Install development tools prerequisites -RUN apt-get update && apt-get install -y \ - build-essential \ - libtool \ - autotools-dev \ - automake \ - pkg-config \ - python3 \ - wget \ - git \ - curl \ - unzip +# Import Bitcoin Core files from bitcoind-base container +COPY --from=lnbook/bitcoind-base /usr/local/ /usr/local/ -# Install additional Bitcoin Core (bitcoind) requirements -RUN apt-get install -y \ - libssl-dev \ - libevent-dev \ - bsdmainutils \ - libboost-system-dev \ - libboost-filesystem-dev \ - libboost-chrono-dev \ - libboost-test-dev \ - libboost-thread-dev \ - libminiupnpc-dev \ - libzmq3-dev +# Import lnd from lnd-base container +FROM golang:1.13 +ENV GOPATH /go +ENV PATH $PATH:$GOPATH/bin +COPY --from=lnbook/lnd-base $GOPATH $GOPATH # Install software-properties-common to add apt repositories -RUN apt-get install -y \ - software-properties-common - -# Add Bitcoin Core PPA repository -RUN add-apt-repository ppa:bitcoin/bitcoin RUN apt-get update && apt-get install -y \ - bitcoind - + software-properties-common \ + apt-utils \ + curl \ + git # c-lightning RUN add-apt-repository -u ppa:lightningnetwork/ppa -RUN apt-get install -y \ +RUN apt-get update && apt-get install -y \ lightningd -# Go 1.13 for LND -RUN curl -SL https://dl.google.com/go/go1.13.linux-amd64.tar.gz \ - | tar -xzC /usr/local -ENV PATH $PATH:/usr/local/go/bin -ENV GOPATH /gocode -RUN mkdir -p $GOPATH -ENV PATH $PATH:$GOPATH/bin - -# LND -RUN go get -d github.com/lightningnetwork/lnd -WORKDIR $GOPATH/src/github.com/lightningnetwork/lnd -RUN make && make install - # OpenJDK11 for eclair -RUN apt install -y \ +RUN apt-get update && apt install -y \ openjdk-11-jdk # eclair-node diff --git a/code/docker/docker-compose/docker-compose.yml b/code/docker/docker-compose/docker-compose.yml deleted file mode 100644 index 8ca032b..0000000 --- a/code/docker/docker-compose/docker-compose.yml +++ /dev/null @@ -1,16 +0,0 @@ -version: "3.3" -services: - bitcoind-regtest: - container_name: bitcoind-regtest - build: - context: ../bitcoind-regtest/. - dockerfile: ./Dockerfile - image: lnbook/bitcoind_regtest:latest - ports: - - "12001:12001" - lnd-run: - container_name: lnd-run - build: - context: ../lnd-run - dockerfile: ./Dockerfile - image: lnbook/lnd_run:latest diff --git a/code/docker/lnbook-app/docker-compose.yml b/code/docker/lnbook-app/docker-compose.yml new file mode 100644 index 0000000..0a8669c --- /dev/null +++ b/code/docker/lnbook-app/docker-compose.yml @@ -0,0 +1,18 @@ +version: "3.3" +services: + bitcoind-regtest: + container_name: bitcoind + build: + context: ../bitcoind-regtest/. + dockerfile: ./Dockerfile + image: lnbook/bitcoind-regtest:latest + ports: + - "18443:18443" + - "12005:12005" + - "12006:12006" + lnd-run: + container_name: lnd + build: + context: ../lnd-run + dockerfile: ./Dockerfile + image: lnbook/lnd-run:latest diff --git a/code/docker/lnd-base/Dockerfile b/code/docker/lnd-base/Dockerfile index 6754d4f..3771ad2 100644 --- a/code/docker/lnd-base/Dockerfile +++ b/code/docker/lnd-base/Dockerfile @@ -1,6 +1,10 @@ FROM golang:1.13 -WORKDIR /go/src/ +ENV GOPATH /go +WORKDIR $GOPATH/src + +RUN apt update && apt install -y \ + jq # LND RUN go get -d github.com/lightningnetwork/lnd diff --git a/code/docker/lnd-run/Dockerfile b/code/docker/lnd-run/Dockerfile index 3b46f57..de69aed 100644 --- a/code/docker/lnd-run/Dockerfile +++ b/code/docker/lnd-run/Dockerfile @@ -1,5 +1,9 @@ -FROM lnbook/lnd_base +FROM lnbook/lnd-base ADD lnd /lnd +RUN ln -s /lnd /root/.lnd -CMD lnd --lnddir=/lnd +WORKDIR /lnd +CMD /bin/bash lnd-start.sh \ + && sleep 5 \ + && /bin/bash fund-lnd.sh diff --git a/code/docker/lnd-run/lnd/fund-lnd.sh b/code/docker/lnd-run/lnd/fund-lnd.sh new file mode 100644 index 0000000..b8c9b29 --- /dev/null +++ b/code/docker/lnd-run/lnd/fund-lnd.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Generate a new receiving address for LND wallet +address=$(lncli --lnddir=/lnd --network regtest newaddress np2wkh | jq .address) + +# Ask Bitcoin Core to send 10 BTC to the address, using JSON-RPC call +curl --user regtest:regtest \ + -H 'content-type: text/plain;' \ + http://bitcoind:18443/ \ + --data-binary @- < 72300a873c2c - [...] -Step 20/20 : RUN curl -SLO https://github.com/ACINQ/eclair/releases/download/v0.3.3/eclair-node-0.3.3-12ac145.jar - ---> Using cache - ---> 3a38f85ba558 -Successfully built 3a38f85ba558 -Successfully tagged lnbook/devenv:latest ----- - -Once the +devenv+ docker container is built, we can run it and access and interactive command shell like this: - ----- -$ docker run -it lnbook/devenv -root@6b5c904d899f:/lnbook# ----- - -You see a prompt +root@6b5c904d899f:/lnbook#+, which shows you the user (root), the container fingerprint (6b5c904d899f) and the current working directory (/lnbook). The prompt ends in +#+ instead of +$+ because you are the root user inside this container. - -Let's give it a quick test, by trying to run the Lightning Network Daemon command +lnd+ and see if it is installed correctly: - ----- -root@6b5c904d899f:/lnbook# lnd --version -lnd version 0.9.0-beta commit=v0.9.0-beta-148-g38b521d87d3fd9cff628e5dc09b764aeabaf011a ----- -[TIP] -==== -To exit the container, press +CTRL-D+ or type +exit+. You are returned to the prompt of your own computer's command-line terminal. -==== - -Great! You have built and ran your first docker container. In order to be able to access the book examples, we will need to connect the folder containing the book repository to our docker container. This is achieved with the +volume+ parameter, which specifies a local volume (where you cloned the book repository) and a container volume (a folder in the container) where the local volume will be mounted. - -[TIP] -==== -Docker's volume parameter needs an _absolute_ path, so that will depend on your local configuration and where you cloned or extracted the book repository files. -==== - -In the following example, we will be connecting the book repository files that were extracted in +/home/ubuntu/lnbook+ to the container volume +lnbook+. Your configuration is likely different, so you need to replace +/home/ubuntu/lnbook+ with the absolute path to the folder where you extracted the book repository: - ----- -$ docker run --volume /home/ubuntu/lnbook:/lnbook -it lnbook/devenv -root@a7da66010491:/lnbook# ls -code images CONTRIBUTING.md README.md -[...] ----- - -You should now see all the book repository files inside your container, under the folder +/lnbook+. Now you can access the examples from the code directory with all the tools, applications and utilities that are in the container. - - ==== Bitcoin Core and Regtest Most of the Lightning node implementations need access to a full Bitcoin node in order to work. -Installing a full Bitcoin node is outside the scope of this book and is a relatively complex endeavor in itself. If you want to try it, refer to _Mastering Bitcoin_ (https://github.com/bitcoinbook/bitcoinbook), "Chapter 3: Bitcoin Core: The Reference Implementation" which discusses the installation and operation of a Bitcoin node. - -A Bitcoin node can also be operated in _regtest_ mode, where the nodes creates a local simulated Bitcoin blockchain for testing purposes. In the following examples, we will be using regtest mode to allow us to demonstrate lightning without having to synchronize a Bitcoin node, or risk any funds. +Installing a full Bitcoin node and synching the Bitcoin blockchain is outside the scope of this book and is a relatively complex endeavor in itself. If you want to try it, refer to _Mastering Bitcoin_ (https://github.com/bitcoinbook/bitcoinbook), "Chapter 3: Bitcoin Core: The Reference Implementation" which discusses the installation and operation of a Bitcoin node. -There are two docker containers for Bitcoin Core. The first is a base container (+bitcoind-base+) that downloads and installs the Bitcoin Core software. The second container is +bitcoind-regtest+ that runs Bitcoin Core in regtest mode and mines a new block every 10 seconds. +A Bitcoin node can also be operated in _regtest_ mode, where the node creates a local simulated Bitcoin blockchain for testing purposes. In the following examples, we will be using regtest mode to allow us to demonstrate lightning without having to synchronize a Bitcoin node, or risk any funds. +There are two docker containers for Bitcoin Core. The first is a base container (+bitcoind-base+) that downloads and installs the Bitcoin Core software. The second container (which extends the bitcoind-base container) is +bitcoind-regtest+ that runs Bitcoin Core in regtest mode and mines a new block every 10 seconds. === c-lightning @@ -365,3 +299,69 @@ You may see a different version from that shown above, as the software continues === eclair === lightning network daemon (lnd) + + + +==== The _devenv_ bundle container + +As stated above, we have not optimized these containers for size. In that spirit, the +devenv+ folder has everything in a single container. It allows you to run any of the examples in a single environment. + +[NOTE] +==== +The devenv image is more than 2GB in size. The first time you build the image it will download a lot of data and take quite a while to finish building. However, docker efficiently caches each step, so if you rebuild it or make changes to it, it will be much faster next time! +==== + +Let's build our +devenv+ container and see how it works. Follow the steps below, while : + +[docker-build-devenv] +---- +$ cd code/docker +$ docker build devenv/ -t lnbook/devenv +Sending build context to Docker daemon 3.072kB +Step 1/20 : FROM ubuntu:18.04 + ---> 72300a873c2c + [...] +Step 20/20 : RUN curl -SLO https://github.com/ACINQ/eclair/releases/download/v0.3.3/eclair-node-0.3.3-12ac145.jar + ---> Using cache + ---> 3a38f85ba558 +Successfully built 3a38f85ba558 +Successfully tagged lnbook/devenv:latest +---- + +Once the +devenv+ docker container is built, we can run it and access and interactive command shell like this: + +---- +$ docker run -it lnbook/devenv +root@6b5c904d899f:/lnbook# +---- + +You see a prompt +root@6b5c904d899f:/lnbook#+, which shows you the user (root), the container fingerprint (6b5c904d899f) and the current working directory (/lnbook). The prompt ends in +#+ instead of +$+ because you are the root user inside this container. + +Let's give it a quick test, by trying to run the Lightning Network Daemon command +lnd+ and see if it is installed correctly: + +---- +root@6b5c904d899f:/lnbook# lnd --version +lnd version 0.9.0-beta commit=v0.9.0-beta-148-g38b521d87d3fd9cff628e5dc09b764aeabaf011a +---- +[TIP] +==== +To exit the container, press +CTRL-D+ or type +exit+. You are returned to the prompt of your own computer's command-line terminal. +==== + +Great! You have built and ran your first docker container. In order to be able to access the book examples, we will need to connect the folder containing the book repository to our docker container. This is achieved with the +volume+ parameter, which specifies a local volume (where you cloned the book repository) and a container volume (a folder in the container) where the local volume will be mounted. + +[TIP] +==== +Docker's volume parameter needs an _absolute_ path, so that will depend on your local configuration and where you cloned or extracted the book repository files. +==== + +In the following example, we will be connecting the book repository files that were extracted in +/home/ubuntu/lnbook+ to the container volume +lnbook+. Your configuration is likely different, so you need to replace +/home/ubuntu/lnbook+ with the absolute path to the folder where you extracted the book repository: + +---- +$ docker run --volume /home/ubuntu/lnbook:/lnbook -it lnbook/devenv +root@a7da66010491:/lnbook# ls +code images CONTRIBUTING.md README.md +[...] +---- + +You should now see all the book repository files inside your container, under the folder +/lnbook+. Now you can access the examples from the code directory with all the tools, applications and utilities that are in the container.