Skip to content

Commit

Permalink
Merge pull request #114 from bitcoin-dev-project/dockerize-proj
Browse files Browse the repository at this point in the history
chore: add docker
  • Loading branch information
carlaKC authored Oct 10, 2023
2 parents 233c15b + d8576dc commit 8d6d90a
Show file tree
Hide file tree
Showing 9 changed files with 294 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.log
target/
.git/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/target
node_modules
config.json
sim.json
package-lock.json
activity-generator/releases/*
.DS_Store
Expand Down
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
LOG_LEVEL ?= info

build-docker:
chmod +x ./docker/build.sh && ./docker/build.sh

mount-volume:
chmod +x ./docker/setup-volume.sh && ./docker/setup-volume.sh "$(SIMFILE_PATH)"

help:
@echo "Makefile commands:"
@echo "build-docker Builds the Docker image."
@echo "mount-volume Mounts the specified volume."
@echo "run Runs the Docker container."
@echo "run-interactive Runs the Docker container in interactive mode."
@echo "stop Stops the Docker container."
@echo ""
@echo "Variables:"
@echo "SIMFILE_PATH Path to the sim.json file."
@echo "LOG_LEVEL Set the logging level (default: info) e.g. <make run LOG_LEVEL=debug>"
@echo "HELP Set to true to print the help message (default: false) e.g. <make run HELP=true>"
@echo "PRINT_BATCH_SIZE Set the batch size for printing the results e.g. <make run PRINT_BATCH_SIZE=100>"
@echo "TOTAL_TIME Set the total time for the simulation e.g. <make run TOTAL_TIME=1000>"

run-docker:
docker run -d --rm --name sim-ln --init -v simln-data:/data -e SIMFILE_PATH=/data/sim.json -e LOG_LEVEL=$(LOG_LEVEL) -e HELP=${HELP} -e PRINT_BATCH_SIZE=${PRINT_BATCH_SIZE} -e TOTAL_TIME=${TOTAL_TIME} sim-ln

run-interactive:
docker run --rm --name sim-ln --init -v simln-data:/data -e SIMFILE_PATH=/data/sim.json -it sim-ln

stop-docker:
docker stop sim-ln
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,6 @@ If you're looking to get started with local lightning development, we
recommend [polar](https://lightningpolar.com/). For larger deployments,
see the [Scaling Lightning](https://github.com/scaling-lightning/scaling-lightning)
project.

## Docker
If you want to run the cli in a containerized environment, see the docker set up docs [here](./docker/README.md)
34 changes: 34 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Use the rust image as the base image for the build stage
FROM rust:latest AS builder

# Receive architecture as an argument
ARG TARGET_ARCH

# Copy the source code
COPY . /tmp/sim-ln

# Install the dependencies required for building sim-ln
RUN apt-get update \
&& apt-get -y --no-install-recommends install protobuf-compiler musl-tools

RUN cd /tmp/sim-ln \
&& rustup target add ${TARGET_ARCH} \
&& rustup component add rustfmt \
&& RUSTFLAGS='-C target-feature=+crt-static' cargo build --locked --release --target=${TARGET_ARCH}

# Use a new stage with a smaller base image to reduce image size
FROM alpine:latest

ARG TARGET_ARCH

RUN apk update && apk upgrade

# Copy the sim-cli binaries from the build stage to the new stage
COPY --from=builder /tmp/sim-ln/target/${TARGET_ARCH}/release/sim-cli /usr/local/bin/

# Copy the entrypoint script to the container
COPY docker/entrypoint.sh /entrypoint.sh

RUN chmod +x entrypoint.sh

ENTRYPOINT [ "/entrypoint.sh" ]
121 changes: 121 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# sim-ln Docker Setup

This guide provides instructions on how to build, run, and manage the `sim-ln` Docker container using the provided Makefile.

## Prerequisites

- Docker installed on your machine.
- A `sim.json` file that contains your specific configuration.

## Building the Docker Image

To build the Docker image, execute:

```bash
make build-docker
```

This command will make the necessary preparations and build the Docker image.

## Mounting the Volume

To ensure that the Docker container can access the configuration and authentication credentials, we use Docker volumes. Before you can run the container, you need to set up the volume with the authentication credentials.

If you are running the nodes locally, we've provided a convenient script to set up the volume:

```bash
make mount-volume SIMFILE_PATH=/path/to/your/sim.json
```

Replace `/path/to/your/sim.json` with the actual path to your `sim.json` file.

The script will automatically copy your configuration, certificates, macaroons, and other authentication config to a Docker volume named simln-data.

*Note:* The path to your config must be an absolute path not relative e.g. "/Users/anonymous/bitcoin-dev-project/sim-ln/sim.json"

### For Remote Nodes

If you're running nodes on a remote machine, or if you have a more complex setup, you'll need to manually set up the Docker volume and adjust your sim.json:

1. Create a Docker volume named simln-data.
2. Copy your configuration, certificates, macaroons, etc., to the volume.
3. Adjust the paths in sim.json to point to the appropriate locations within the volume.

---

## Using Docker Host's Internal IP

Docker provides a special DNS name `host.docker.internal` that resolves to the host machine's IP address because we can't `localhost` or `127.0.0.1` for the IP address.

For instance, in your configuration:

```json
{
"LND": {
"id": "022579561f6f0ea86e330df2f9e7b2be3e0a53f8552f9d5293b80dfc1038f2f66d",
"address": "https://host.docker.internal:10002",
"macaroon": "/path/in/container/lnd/bob/data/chain/bitcoin/regtest/admin.macaroon",
"cert": "/path/in/container/lnd/bob/tls.cert"
}
}
```

In the above example, the `address` field uses `host.docker.internal` to refer to a service running on port `10002` on the host machine. This special DNS name ensures that your containerized application can reach out to services running on the host.

---

## Running the Docker Container

To run the `sim-ln` Docker container:

```bash
make run-docker
```

You can adjust the logging level by providing the `LOG_LEVEL` variable. The default value is `info`. Example:

```bash
make run LOG_LEVEL=debug
```

Other configurable variables include:

- `HELP`: Set to `true` to print the help message.
- `PRINT_BATCH_SIZE`: determines the number of payment results that will be written to disk at a time.
- `TOTAL_TIME`: the total runtime for the simulation expressed in seconds.

Example usage:

```bash
make run PRINT_BATCH_SIZE=100 TOTAL_TIME=5000
```

For an interactive session:

```bash
make run-interactive
```

## Stopping the Container

To stop the `sim-ln` Docker container, use:

```bash
make stop-docker
```

## Help

For a list of available Makefile commands and their descriptions, run:

```bash
make help
```

---

## Notes for Developers:

- When you use the `mount-volume` command, it sets up a Docker volume named `simln-data`. This volume contains your `sim.json` file and other necessary files, ensuring that the data is accessible inside the Docker container.
- For the node address config, docker provides a special DNS name `host.docker.internal` that resolves to the host machine's IP address because we can't `localhost` or `127.0.0.1` for the IP address.
- The paths to certificates, macaroons, etc., in your `sim.json` are automatically adjusted to point to their corresponding paths inside the Docker volume.
19 changes: 19 additions & 0 deletions docker/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

case $(uname -m) in
x86_64)
ARCH="amd64"
TARGET_ARCH="x86_64-unknown-linux-musl"
;;
arm64)
ARCH="arm64"
TARGET_ARCH="aarch64-unknown-linux-musl"
;;
*)
echo "Unsupported architecture"
exit 1
;;
esac

echo "Building for architecture: $TARGET_ARCH"
docker build -f docker/Dockerfile --build-arg TARGET_ARCH=$TARGET_ARCH -t sim-ln .
32 changes: 32 additions & 0 deletions docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

# Define the start command
START_COMMAND="/usr/local/bin/sim-cli $SIMFILE_PATH"

# Check for version arg
if [[ ! -z ${VERSION} ]]; then
START_COMMAND="$START_COMMAND --version"
fi

# Check for help arg
if [[ ! -z ${HELP} ]]; then
START_COMMAND="$START_COMMAND --help"
fi

# Check for log level arg
if [[ ! -z ${LOG_LEVEL} ]]; then
START_COMMAND="$START_COMMAND --log-level $LOG_LEVEL"
fi

# Check for total time arg
if [[ ! -z ${TOTAL_TIME} ]]; then
START_COMMAND="$START_COMMAND --total-time $TOTAL_TIME"
fi

# Check for print-batch-size arg
if [[ ! -z ${PRINT_BATCH_SIZE} ]]; then
START_COMMAND="$START_COMMAND --print-batch-size $PRINT_BATCH_SIZE"
fi

# start the container
exec $START_COMMAND
50 changes: 50 additions & 0 deletions docker/setup-volume.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/bin/bash

# Path to the sim.json on the host
SIMFILE_PATH_ON_HOST=$1

# Check if the sim.json path was provided
if [[ -z "$SIMFILE_PATH_ON_HOST" ]]; then
echo "Error: Path to sim.json must be provided as an argument."
exit 1
fi

# Check if jq is installed
if ! command -v jq &> /dev/null; then
echo "Error: jq is not installed. Please install jq to continue."
exit 1
fi

# Volume Config Preparation
VOLUME_NAME="simln-data"
STAGING_DIR="/tmp/sim-ln-volume"
mkdir -p $STAGING_DIR

# Copy sim.json to a temporary staging directory
cp $SIMFILE_PATH_ON_HOST $STAGING_DIR/sim.json

# Extracting Node Count
NODE_COUNT=$(cat $SIMFILE_PATH_ON_HOST | jq '.nodes | length')

# Loop Over Each Node
for (( i=0; i<$NODE_COUNT; i++ )); do
NODE_TYPE=$(cat $SIMFILE_PATH_ON_HOST | jq -r ".nodes[$i] | keys[0]") # Determine if it's LND or CLN.
NODE_ID=$(cat $SIMFILE_PATH_ON_HOST | jq -r ".nodes[$i].$NODE_TYPE.id") # Extract node ID for directory creation.
NODE_TLS_PATH_ON_HOST=$(cat $SIMFILE_PATH_ON_HOST | jq -r ".nodes[$i].$NODE_TYPE.cert") # TLS path
NODE_MACAROON_PATH_ON_HOST=$(cat $SIMFILE_PATH_ON_HOST | jq -r ".nodes[$i].$NODE_TYPE.macaroon") # Macaroon path

# Create staging directories for each node
mkdir -p $STAGING_DIR/lnd/$NODE_ID

# Copy files to staging directories
cp $NODE_TLS_PATH_ON_HOST $STAGING_DIR/lnd/$NODE_ID/tls.cert
cp $NODE_MACAROON_PATH_ON_HOST $STAGING_DIR/lnd/$NODE_ID/admin.macaroon

# Adjust the paths in the staging sim.json so we don't use the host path
sed -i '' 's|'$(dirname $NODE_TLS_PATH_ON_HOST)'/tls.cert|/data/lnd/'$NODE_ID'/tls.cert|' $STAGING_DIR/sim.json
sed -i '' 's|'$(dirname $NODE_MACAROON_PATH_ON_HOST)'/admin.macaroon|/data/lnd/'$NODE_ID'/admin.macaroon|' $STAGING_DIR/sim.json
done

# Create Docker volume and copy the data
docker volume create $VOLUME_NAME
docker run --rm -v $VOLUME_NAME:/data -v $STAGING_DIR:/staging alpine sh -c 'cp -r /staging/* /data/'

0 comments on commit 8d6d90a

Please sign in to comment.