Skip to main content

Run Node using Docker

This guide will walk you through deploying an RPC node using the go-flare images on Docker Hub.

Prerequisites

tip

To avoid using sudo each time you run the docker command, add your user to the Docker group after installation:

sudo usermod -a -G docker $USER

Log out and log back in or restart your system for the changes to take effect.

Configure the machine

Disk setup

This setup varies depending on your use case, but essentially you need to have a local directory with sufficient space for the blockchain data to be stored and persisted in. In this guide, there is an additional disk mounted at /mnt/db which is used to persist the blockchain data.

  1. After you have a machine set up and ready to go, find the additional disk, format it if necessary, and mount to a directory:

    • Replace <user>:<group> with the username and primary group of the user who will run the docker or docker compose commands. This is often your own username, which can be found using id -u -n (user) and id -g -n (group), or often simply ${USER}:${USER} It is recommended that this isn't the root user for security reasons.
    • Ensure you are replacing /dev/sdb with your actual device, since it could be different to the example.
    Data Loss

    The following mkfs.ext4 command will erase all data on the specified device (/dev/sdb in this example). Double-check the selected device and that it does not contain any important data before proceeding.

    lsblk
    #############################################
    # NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    # sda 8:0 0 10G 0 disk
    # ├─sda1 8:1 0 9.9G 0 part /
    # ├─sda14 8:14 0 3M 0 part
    # └─sda15 8:15 0 124M 0 part /boot/efi
    # sdb 8:16 0 300G 0 disk
    # ^-- Device identified as db disk via size
    #############################################
    sudo mkdir /mnt/db
    sudo chown -R <user>:<group> /mnt/db
    sudo mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb
    sudo mount /dev/sdb /mnt/db
  2. Confirm the new disk is mounted:

    lsblk
    #############################################
    # NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    # sda 8:0 0 10G 0 disk
    # ├─sda1 8:1 0 9.9G 0 part /
    # ├─sda14 8:14 0 3M 0 part
    # └─sda15 8:15 0 124M 0 part /boot/efi
    # sdb 8:16 0 300G 0 disk /mnt/db
    # ^-- Device now has mountpoint set to /mnt/db
    #############################################

    Look for your device name and mount point specified in the output to confirm the mount worked.

  3. Backup the original fstab file (to revert changes if needed) and update /etc/fstab to make sure the device is mounted when the system reboots:

    cp /etc/fstab /etc/fstab.backup
    fstab_entry="UUID=$(sudo blkid -o value -s UUID /dev/sdb) /mnt/db ext4 discard,defaults 0 2"
    echo "$fstab_entry" | sudo tee -a /etc/fstab

Configuration File and Logs Directory Setup

Once the disk setup is complete, you can define the configuration file and logs directory for the RPC node. These will be mounted from your local machine to the specified directories on your container.

Mounting the logs directory allows you to access the logs generated by the workload directly on your local machine. This saves you the effort of using docker logs and lets you inspect the files in your local directory instead.

  1. Create the local directories and change ownership to the same user you used to run the container:

    sudo mkdir -p /opt/flare/conf
    sudo mkdir /opt/flare/logs
    sudo chown -R <user>:<group> /opt/flare
  2. Create the configuration file:

    /opt/flare/conf/config.json
    {
    "snowman-api-enabled": false,
    "coreth-admin-api-enabled": false,
    "eth-apis": [
    "eth",
    "eth-filter",
    "net",
    "web3",
    "internal-eth",
    "internal-blockchain",
    "internal-transaction"
    ],
    "rpc-gas-cap": 50000000,
    "rpc-tx-fee-cap": 100,
    "pruning-enabled": true,
    "local-txs-enabled": false,
    "api-max-duration": 0,
    "api-max-blocks-per-request": 0,
    "allow-unfinalized-queries": false,
    "allow-unprotected-txs": false,
    "remote-tx-gossip-only-enabled": false,
    "log-level": "info"
    }

Run the node

This guide will show examples of running the node using both Docker CLI and Docker Compose.

Using Docker CLI

  1. Retrieve the tag from the latest stable release:

    # 1. Find the latest stable release tag from:
    # https://hub.docker.com/r/flarefoundation/go-flare/tags
    # 2. Set the tag name in the variable below (only use versioned tags):
    LATEST_TAG="vX.Y.Z" # <-- REPLACE vX.Y.Z WITH THE ACTUAL LATEST TAG e.g. v1.10.0
  2. Start the container:

    docker run -d --name flare-observer \
    -e NETWORK_ID="flare" \
    -e AUTOCONFIGURE_BOOTSTRAP="1" \
    -e AUTOCONFIGURE_PUBLIC_IP="1" \
    -e AUTOCONFIGURE_BOOTSTRAP_ENDPOINT="https://flare-bootstrap.flare.network/ext/info" \
    -v /mnt/db:/app/db -v /opt/flare/conf:/app/conf/C \
    -v /opt/flare/logs:/app/logs \
    -p 0.0.0.0:9650:9650 \
    -p 0.0.0.0:9651:9651 \
    flarefoundation/go-flare:${LATEST_TAG}

    Confirm your container is running and inspect that logs are printing:

    docker ps
    docker logs flare-observer -f
  3. Once you have confirmed that the container is running, use Ctrl+C to exit the following of logs and check your container's /ext/health endpoint. Only when the RPC node is fully synced will you see "healthy": true, but this otherwise confirms your container's HTTP port 9650 is accessible from your local machine.

    curl http://localhost:9650/ext/health | jq
Explanation of the CLI arguments.

Volumes:

  • -v /mnt/db:/app/db

    Mount the local database directory to the default database directory of the container.

  • -v /opt/flare/conf:/app/conf/C

    Mount the local configuration directory to the default location of config.json.

  • -v /opt/flare/logs:/app/logs

    Mount the local logs directory to the workloads default logs directory.

Ports:

  • -p 0.0.0.0:9650:9650

    Mapping the container's HTTP port to your local machine, enabling the querying of the containerized RPC node's HTTP port via your local machine's IP and port.

    !!! warning Only use binding 0.0.0.0 for port 9650 if you wish to publicly expose your containerized RPC node's endpoint from your machine's public IP address. If you require it to be publicly accessible for another application to use, ensure you set up a firewall rule to only allow port 9650 to be accessible via specific source IP addresses.

  • -p 0.0.0.0:9651:9651

    Mapping the container's peering port to your local machine so other peers can reach the node and allow it to gain peers on the network.

Environment Variables:

  • -e AUTOCONFIGURE_BOOTSTRAP="1"

    Retrieves the bootstrap endpoints Node-IP and Node-ID automatically.

  • -e NETWORK_ID="<network>"

    Sets the correct network ID from the provided options below:

    • coston
    • costwo
    • songbird
    • flare
  • -e AUTOCONFIGURE_PUBLIC_IP="1"

    Retrieves your local machine's public IP automatically.

  • -e AUTOCONFIGURE_BOOTSTRAP_ENDPOINT="<bootstrap_host>/ext/info"

    Defines the bootstrap endpoint used to initialize chain sync. These endpoints can be used to bootstrap your node for each chain:

    • https://flare-bootstrap.flare.network/ext/info
    • https://coston2-bootstrap.flare.network/ext/info
    • https://songbird-bootstrap.flare.network/ext/info
    • https://coston-bootstrap.flare.network/ext/info

Using Docker Compose

Docker Compose for this use case is a good way to simplify your setup of running the RPC node. Adding all necessary configurations into a single file that can be run with a simple command.

In this guide the docker-compose.yaml file is created in /opt/observer but the location is entirely up to you.

  1. Create the working directory and set the ownership.

    sudo mkdir /opt/observer
    sudo chown -R <user>:<group> /opt/observer
  2. Create the docker-compose.yaml file:

    /opt/observer/docker-compose.yaml
    services:
    observer:
    container_name: flare-observer
    # 1. Find the latest stable release tag from:
    # https://hub.docker.com/r/flarefoundation/go-flare/tags
    # 2. Set the tag name in the variable below (only use versioned tags):
    image: flarefoundation/go-flare:vX.Y.Z # <-- REPLACE vX.Y.Z WITH THE ACTUAL LATEST TAG e.g. v1.10.0
    restart: on-failure
    environment:
    - NETWORK_ID=flare
    - AUTOCONFIGURE_BOOTSTRAP=1
    - AUTOCONFIGURE_PUBLIC_IP=1
    - AUTOCONFIGURE_BOOTSTRAP_ENDPOINT=https://flare-bootstrap.flare.network/ext/info
    volumes:
    - /mnt/db:/app/db
    - /opt/flare/conf:/app/conf/C
    - /opt/flare/logs:/app/logs
    ports:
    - 0.0.0.0:9650:9650
    - 0.0.0.0:9651:9651
  3. Run Docker Compose:

    docker compose -f /opt/observer/docker-compose.yaml up -d
  4. When the command completes, check the container is running and inspect that logs are being generated:

    docker ps
    docker compose logs -f
  5. Once you have confirmed the container is running, use Ctrl+C to exit the following of logs and check your container's /ext/health endpoint. Only when the RPC node is fully synced will you see "healthy": true, but this otherwise confirms your container's HTTP port (9650) is accessible from your local machine.

    curl http://localhost:9650/ext/health | jq

Additional configuration

There are several environment variables to adjust your workload at runtime. The example Docker and Docker Compose guides above assumed some defaults and utilized built-in automation scripts for most of the configuration. Outlined below are all options available:

Variable NameDefaultDescription
NETWORK_IDcostwoThe network ID to connect to
HTTP_HOST0.0.0.0HTTP host binding address
HTTP_PORT9650The listening port for the HTTP host
STAKING_PORT9651The staking port for bootstrapping nodes
PUBLIC_IP(empty)Public facing IP. Must be set if AUTOCONFIGURE_PUBLIC_IP=0
DB_DIR/app/dbThe database directory location
DB_TYPEleveldbThe database type to be used
BOOTSTRAP_IPS(empty)A list of bootstrap server IPs
BOOTSTRAP_IDS(empty)A list of bootstrap server IDs
CHAIN_CONFIG_DIR/app/confConfiguration folder where you should mount your configuration file
LOG_DIR/app/logsLogging directory
LOG_LEVELinfoLogging verbosity level that is logged into the file
AUTOCONFIGURE_PUBLIC_IP0Set to 1 to autoconfigure PUBLIC_IP, skipped if PUBLIC_IP is set
AUTOCONFIGURE_BOOTSTRAP0Set to 1 to autoconfigure BOOTSTRAP_IPS and BOOTSTRAP_IDS
AUTOCONFIGURE_BOOTSTRAP_ENDPOINThttps://coston2-bootstrap.flare.network/ext/infoEndpoint used for bootstrapping when AUTOCONFIGURE_BOOTSTRAP=1
AUTOCONFIGURE_FALLBACK_ENDPOINTS(empty)Comma-divided fallback bootstrap endpoints if the primary endpoint fails
EXTRA_ARGUMENTS(empty)Extra arguments passed to flare binary

Update the node

To update your node to a newer go-flare version:

  1. Find the latest stable tag from the go-flare Docker Hub tags page.

  2. Stop and remove the old container:

    docker stop <your_container_name> # e.g., flare-observer
    docker rm <your_container_name>
  3. Update the LATEST_TAG to the new stable tag and run the same docker run command as previously detailed. Your data in /mnt/db (or your chosen volume) will be preserved.

Maintain the node

In some cases, your node might not work correctly or you might receive unusual messages that are difficult to troubleshoot. Use the following solutions to ensure your node stays healthy:

  • Ensure Adequate Peers: When your node has fewer than 16 peers, it will not work correctly. To retrieve the number of connected peers, run the following command and look for the line containing connectedPeers:

    curl http://127.0.0.1:9650/ext/health | jq

    To automate the process, use:

    curl -s http://127.0.0.1:9650/ext/health | jq -r ".checks.network.message.connectedPeers"
  • Check Disk Space: If your node does not sync after a long time and abruptly stops working, ensure the database location has sufficient disk space. Remember, the database size might change significantly during bootstrapping.

  • Resolve Connection Issues: If you receive unusual messages after making submissions or when transactions are reverted, your node might not be connected correctly. Ensure the database location has sufficient disk space, then restart the node.

  • Handle Bootstrap Errors: If you receive an error related to GetAcceptedFrontier during bootstrapping, your node was disconnected during the process. Restart the node if you see the following error:

    failed to send GetAcceptedFrontier(MtF8bVH241hetCQJgsKEdKyJBs8vhp1BC, 11111111111111111111111111111111LpoYY, NUMBER)
  • Restart Unhealthy Nodes: If your node syncs but remains unhealthy for no discernible reason, restart the node.