Skip to content

Usable Dockerfile for CLightning #1318

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Dockerfile
6 changes: 5 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Declare files that will always have CRLF line endings on checkout.
*.sh text eol=lf
*.py text eol=lf
Makefile text eol=lf
configure text eol=lf
Makefile text eol=lf
hooks/build text eol=lf
configure text eol=lf
.gitmodules text eol=lf
121 changes: 121 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
FROM alpine:3.7 as builder

RUN apk add --no-cache \
ca-certificates \
autoconf \
automake \
build-base \
libressl \
libtool \
gmp-dev \
python \
python-dev \
python3 \
sqlite-dev \
wget \
git \
file \
gnupg \
swig \
zlib-dev

WORKDIR /opt

ENV BITCOIN_VERSION 0.16.0
ENV BITCOIN_URL https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/bitcoin-$BITCOIN_VERSION-x86_64-linux-gnu.tar.gz
ENV BITCOIN_SHA256 e6322c69bcc974a29e6a715e0ecb8799d2d21691d683eeb8fef65fc5f6a66477
ENV BITCOIN_ASC_URL https://bitcoincore.org/bin/bitcoin-core-$BITCOIN_VERSION/SHA256SUMS.asc
ENV BITCOIN_PGP_KEY 01EA5486DE18A882D4C2684590C8019E36C2E964

RUN mkdir /opt/bitcoin && cd /opt/bitcoin \
&& wget -qO bitcoin.tar.gz "$BITCOIN_URL" \
&& echo "$BITCOIN_SHA256 bitcoin.tar.gz" | sha256sum -c - \
&& gpg --keyserver keyserver.ubuntu.com --recv-keys "$BITCOIN_PGP_KEY" \
&& wget -qO bitcoin.asc "$BITCOIN_ASC_URL" \
&& gpg --verify bitcoin.asc \
&& BD=bitcoin-$BITCOIN_VERSION/bin \
&& tar -xzvf bitcoin.tar.gz $BD/bitcoin-cli --strip-components=1 \
&& rm bitcoin.tar.gz
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the rm (here and below for litecoin) needed when its using a multi-stage build?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because multi-stage build still create layer when you build. It is good practice to make layer smalls.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note this has no impact if you download the full image. Only if you build it yourself without asking to clean the intermediate layers.


ENV LITECOIN_VERSION 0.14.2
ENV LITECOIN_URL https://download.litecoin.org/litecoin-0.14.2/linux/litecoin-0.14.2-x86_64-linux-gnu.tar.gz
ENV LITECOIN_SHA256 05f409ee57ce83124f2463a3277dc8d46fca18637052d1021130e4deaca07b3c
ENV LITECOIN_ASC_URL https://download.litecoin.org/litecoin-0.14.2/linux/litecoin-0.14.2-linux-signatures.asc
ENV LITECOIN_PGP_KEY FE3348877809386C

# install litecoin binaries
RUN mkdir /opt/litecoin && cd /opt/litecoin \
&& wget -qO litecoin.tar.gz "$LITECOIN_URL" \
&& echo "$LITECOIN_SHA256 litecoin.tar.gz" | sha256sum -c - \
&& gpg --keyserver keyserver.ubuntu.com --recv-keys "$LITECOIN_PGP_KEY" \
&& wget -qO litecoin.asc "$LITECOIN_ASC_URL" \
&& gpg --verify litecoin.asc \
&& BD=litecoin-$LITECOIN_VERSION/bin \
&& tar -xzvf litecoin.tar.gz $BD/litecoin-cli --strip-components=1 --exclude=*-qt \
&& rm litecoin.tar.gz

ENV LIGHTNINGD_VERSION=master

WORKDIR /opt/lightningd
COPY . .

ARG DEVELOPER=0
RUN ./configure && make -j3 && cp lightningd/lightning* cli/lightning-cli /usr/bin/

FROM alpine:3.7

RUN apk add --no-cache \
gmp-dev \
sqlite-dev \
inotify-tools \
socat \
bash \
zlib-dev

ARG TRACE_TOOLS=false
ENV TRACE_TOOLS=$TRACE_TOOLS

ENV GLIBC_VERSION 2.27-r0
ENV GLIBC_SHA256 938bceae3b83c53e7fa9cc4135ce45e04aae99256c5e74cf186c794b97473bc7
ENV GLIBCBIN_SHA256 3a87874e57b9d92e223f3e90356aaea994af67fb76b71bb72abfb809e948d0d6

ENV TRACE_LOCATION=/opt/traces
VOLUME /opt/traces

# Download and install glibc (https://github.com/jeanblanchard/docker-alpine-glibc/blob/master/Dockerfile)
RUN apk add --update curl && \
curl -Lo /etc/apk/keys/sgerrand.rsa.pub https://raw.githubusercontent.com/sgerrand/alpine-pkg-glibc/master/sgerrand.rsa.pub && \
curl -Lo glibc.apk "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-${GLIBC_VERSION}.apk" && \
echo "$GLIBC_SHA256 glibc.apk" | sha256sum -c - && \
curl -Lo glibc-bin.apk "https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VERSION}/glibc-bin-${GLIBC_VERSION}.apk" && \
echo "$GLIBCBIN_SHA256 glibc-bin.apk" | sha256sum -c - && \
apk add glibc-bin.apk glibc.apk && \
/usr/glibc-compat/sbin/ldconfig /lib /usr/glibc-compat/lib && \
echo 'hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4' >> /etc/nsswitch.conf && \
( ! $TRACE_TOOLS || \
( \
sed -i -e 's/v[[:digit:]]\.[[:digit:]]/edge/g' /etc/apk/repositories && \
echo "http://nl.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories && \
apk add --no-cache perf perl && \
mkdir FlameGraph && cd FlameGraph && \
curl -Lo FlameGraph.tar.gz "https://github.com/brendangregg/FlameGraph/archive/v1.0.tar.gz" && \
tar -zxvf FlameGraph.tar.gz --strip-components=1 && rm FlameGraph.tar.gz && cd .. \
) \
) && \
apk del curl && \
rm -rf glibc.apk glibc-bin.apk /var/cache/apk/*

ENV LIGHTNINGD_DATA=/root/.lightning

RUN mkdir $LIGHTNINGD_DATA && \
touch $LIGHTNINGD_DATA/config
VOLUME [ "/root/.lightning" ]

COPY --from=builder /opt/lightningd/cli/lightning-cli /usr/bin
COPY --from=builder /opt/lightningd/lightningd/lightning* /usr/bin/
COPY --from=builder /opt/bitcoin/bin /usr/bin
COPY --from=builder /opt/litecoin/bin /usr/bin
COPY tools/docker-entrypoint.sh entrypoint.sh

EXPOSE 9735 9835
ENTRYPOINT [ "./entrypoint.sh" ]
70 changes: 69 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,82 @@ For the impatient here's the gist of it for Ubuntu and Debian:
./configure
make

Or if you like to throw `docker` into the mix:
Or if you like to throw `docker` into the mix, you have the choice with two different docker images:

The first docker image is [cdecker/lightningd](https://hub.docker.com/r/cdecker/lightningd/), it provides c-lightning with a bundled bitcoin core:

sudo docker run \
-v $HOME/.lightning:/root/.lightning \
-v $HOME/.bitcoin:/root/.bitcoin \
-p 9735:9735 \
cdecker/lightningd:latest

The second docker image is [elementsproject/lightningd](https://hub.docker.com/r/elementsproject/lightningd/) (from this [Dockerfile](Dockerfile)), it is meant to be used inside docker-compose.

Image tags with `-dev` at the end are images built with `DEVELOPER=1`.

If you build the image yourself, you can use the build arg `DEVELOPER=1` to build c-lightning in developer mode.

It has the following environment variable:

* `EXPOSE_TCP` default to false, if true, use expose c-lightning on port 9835. (Use this only for testing)
* `LIGHTNINGD_OPT` is the content of the config file of the c-lightning instance.

On top of this, to make configuration easier, if `LIGHTNINGD_OPT` contains the parameter `chain=`, then, the `network=` parameter will be rewritten before starting c-lightning:

| chain= | network= | New network= |
|---|---|---|
| btc | mainnet | bitcoin |
| btc | testnet | testnet |
| btc | regtest | regtest |
| ltc | mainnet | litecoin |
| ltc | testnet | litecoin-testnet |

Here is an example of a docker-compose file with litecoind and c-lightning on `testnet` which expose litecoin's rpc interface on port `32610` and c-lightning API on port `32611`:

```
version: "3"

litecoind:
image: nicolasdorier/docker-litecoin:0.15.1
environment:
BITCOIN_EXTRA_ARGS: |
testnet=1
whitelist=0.0.0.0/0
rpcport=43782
server=1
ports:
- "32610:43782"
expose:
- "43782"
volumes:
- "litecoin_datadir:/data"

clightning_litecoin:
image: elementsproject/lightningd
environment:
EXPOSE_TCP: "true"
LIGHTNINGD_OPT: |
bitcoin-datadir=/etc/litecoin
bitcoin-rpcconnect=litecoind
network=testnet
alias=myawesomenode
chain=ltc
ports:
- "32611:9835"
expose:
- "9835"
volumes:
- "clightning_litecoin_datadir:/root/.lightning"
- "litecoin_datadir:/etc/litecoin"
links:
- litecoind

volumes:
litecoin_datadir:
clightning_litecoin_datadir:
```

### Starting `lightningd`

In order to start `lightningd` you will need to have a local `bitcoind`
Expand Down
18 changes: 18 additions & 0 deletions hooks/build
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

# This file is a hook for dockerhub.
# If the tag ends with -dev or -bench, make sure to build with DEVELOPER=1
# If the tag ends with -bench, make sure trace tools (perf, flamegraph and sample.sh are included)

DEVELOPER=0
TRACE_TOOLS=false

if [[ "$DOCKER_TAG" == *-dev ]] || [[ "$DOCKER_TAG" == *-bench ]]; then
DEVELOPER=1
fi

if [[ "$DOCKER_TAG" == *-bench ]]; then
TRACE_TOOLS=true
fi

docker build --build-arg "DEVELOPER=$DEVELOPER" --build-arg "TRACE_TOOLS=$TRACE_TOOLS" -t "$IMAGE_NAME" .
84 changes: 84 additions & 0 deletions tools/docker-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#!/bin/bash

cat <<-EOF > "$LIGHTNINGD_DATA/config"
${LIGHTNINGD_OPT}
EOF

: "${EXPOSE_TCP:=false}"

NETWORK=$(sed -n 's/^network=\(.*\)$/\1/p' < "$LIGHTNINGD_DATA/config")
CHAIN=$(sed -n 's/^chain=\(.*\)$/\1/p' < "$LIGHTNINGD_DATA/config")

sed -i '/^chain=/d' "$LIGHTNINGD_DATA/config"

REPLACEDNETWORK="";
if [ "$CHAIN" == "btc" ]; then
if [ "$NETWORK" == "mainnet" ]; then
REPLACEDNETWORK="bitcoin"
fi
fi

if [ "$CHAIN" == "ltc" ]; then
if [ "$NETWORK" == "mainnet" ]; then
REPLACEDNETWORK="litecoin"
fi
if [ "$NETWORK" == "testnet" ]; then
REPLACEDNETWORK="litecoin-testnet"
fi
if [ "$NETWORK" == "regtest" ]; then
echo "REGTEST NOT AVAILABLE FOR LTC"
exit
fi
fi

if [[ $TRACE_TOOLS == "true" ]]; then
echo "Trace tools detected, installing sample.sh..."
echo 0 > /proc/sys/kernel/kptr_restrict
echo "
# This script will take one minute of stacktrace samples and plot it in a flamegraph
LIGHTNING_PROCESSES=\$(pidof lightningd lightning_chann lightning_closi lightning_gossi lightning_hsmd lightning_oncha lightning_openi lightning_hsmd lightning_gossipd lightning_channeld | sed -e 's/\s/,/g')
perf record -F 99 -g -a --pid \$LIGHTNING_PROCESSES -o \"$TRACE_LOCATION/perf.data\" -- sleep 60
perf script -i \"$TRACE_LOCATION/perf.data\" > \"$TRACE_LOCATION/output.trace\"
cd /FlameGraph
./stackcollapse-perf.pl \"$TRACE_LOCATION/output.trace\" > \"$TRACE_LOCATION/output.trace.folded\"
svg=\"$TRACE_LOCATION/\$((\$SECONDS / 60))min.svg\"
./flamegraph.pl \"$TRACE_LOCATION/output.trace.folded\" > \"\$svg\"
rm \"$TRACE_LOCATION/perf.data\"
rm \"$TRACE_LOCATION/output.trace\"
rm \"$TRACE_LOCATION/output.trace.folded\"
echo \"flamegraph taken: \$svg\"
" > /usr/bin/sample.sh
chmod +x /usr/bin/sample.sh

echo "
# This script will run sample.sh after 2 min then every 10 minutes
sleep 120
sample.sh
while true; do
sleep 300
. sample.sh
done
" > /usr/bin/sample-loop.sh
chmod +x /usr/bin/sample-loop.sh
fi

if [[ $REPLACEDNETWORK ]]; then
sed -i '/^network=/d' "$LIGHTNINGD_DATA/config"
echo "network=$REPLACEDNETWORK" >> "$LIGHTNINGD_DATA/config"
echo "Replaced network $NETWORK by $REPLACEDNETWORK in $LIGHTNINGD_DATA/config"
fi

if [ "$EXPOSE_TCP" == "true" ]; then
set -m
lightningd "$@" &
echo "C-Lightning starting"
while read -r i; do if [ "$i" = "lightning-rpc" ]; then break; fi; done \
< <(inotifywait -e create,open --format '%f' --quiet "$LIGHTNINGD_DATA" --monitor)
echo "C-Lightning started"

socat "TCP4-listen:$LIGHTNINGD_PORT,fork,reuseaddr" "UNIX-CONNECT:$LIGHTNINGD_DATA/lightning-rpc" &

fg %-
else
lightningd "$@"
fi