Run Node using Docker
This guide will walk you through deploying an RPC node using the go-flare images on Docker Hub.
Prerequisites
- A machine meeting the minimum hardware requirements.
- Docker Engine
- jq
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.
-
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 usingid -u -n
(user) andid -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 LossThe 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 - Replace
-
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.
-
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.
-
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 -
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
-
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 -
Start the container:
- Flare Mainnet
- Flare Testnet Coston2
- Songbird Canary-Network
- Songbird Testnet Coston
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 -fdocker run -d --name coston2-observer \
-e NETWORK_ID="costwo" \
-e AUTOCONFIGURE_BOOTSTRAP="1" \
-e AUTOCONFIGURE_PUBLIC_IP="1" \
-e AUTOCONFIGURE_BOOTSTRAP_ENDPOINT="https://coston2-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 coston2-observer -fdocker run -d --name songbird-observer \
-e NETWORK_ID="songbird" \
-e AUTOCONFIGURE_BOOTSTRAP="1" \
-e AUTOCONFIGURE_PUBLIC_IP="1" \
-e AUTOCONFIGURE_BOOTSTRAP_ENDPOINT="https://songbird-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 songbird-observer -fdocker run -d --name coston-observer \
-e NETWORK_ID="coston" \
-e AUTOCONFIGURE_BOOTSTRAP="1" \
-e AUTOCONFIGURE_PUBLIC_IP="1" \
-e AUTOCONFIGURE_BOOTSTRAP_ENDPOINT="https://coston-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 coston-observer -f -
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 port9650
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.
-
Create the working directory and set the ownership.
sudo mkdir /opt/observer
sudo chown -R <user>:<group> /opt/observer -
Create the
docker-compose.yaml
file:- Flare Mainnet
- Flare Testnet Coston2
- Songbird Canary-Network
- Songbird Testnet Coston
/opt/observer/docker-compose.yamlservices:
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/opt/observer/docker-compose.yamlservices:
observer:
container_name: coston2-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=costwo
- AUTOCONFIGURE_BOOTSTRAP=1
- AUTOCONFIGURE_PUBLIC_IP=1
- AUTOCONFIGURE_BOOTSTRAP_ENDPOINT=https://coston2-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/opt/observer/docker-compose.yamlservices:
observer:
container_name: songbird-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=songbird
- AUTOCONFIGURE_BOOTSTRAP=1
- AUTOCONFIGURE_PUBLIC_IP=1
- AUTOCONFIGURE_BOOTSTRAP_ENDPOINT=https://songbird-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/opt/observer/docker-compose.yamlservices:
observer:
container_name: coston-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=coston
- AUTOCONFIGURE_BOOTSTRAP=1
- AUTOCONFIGURE_PUBLIC_IP=1
- AUTOCONFIGURE_BOOTSTRAP_ENDPOINT=https://coston-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 -
Run Docker Compose:
docker compose -f /opt/observer/docker-compose.yaml up -d
-
When the command completes, check the container is running and inspect that logs are being generated:
docker ps
docker compose logs -f -
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 Name | Default | Description |
---|---|---|
NETWORK_ID | costwo | The network ID to connect to |
HTTP_HOST | 0.0.0.0 | HTTP host binding address |
HTTP_PORT | 9650 | The listening port for the HTTP host |
STAKING_PORT | 9651 | The staking port for bootstrapping nodes |
PUBLIC_IP | (empty) | Public facing IP. Must be set if AUTOCONFIGURE_PUBLIC_IP=0 |
DB_DIR | /app/db | The database directory location |
DB_TYPE | leveldb | The 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/conf | Configuration folder where you should mount your configuration file |
LOG_DIR | /app/logs | Logging directory |
LOG_LEVEL | info | Logging verbosity level that is logged into the file |
AUTOCONFIGURE_PUBLIC_IP | 0 | Set to 1 to autoconfigure PUBLIC_IP , skipped if PUBLIC_IP is set |
AUTOCONFIGURE_BOOTSTRAP | 0 | Set to 1 to autoconfigure BOOTSTRAP_IPS and BOOTSTRAP_IDS |
AUTOCONFIGURE_BOOTSTRAP_ENDPOINT | https://coston2-bootstrap.flare.network/ext/info | Endpoint 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:
- Docker CLI
- Docker Compose
-
Find the latest stable tag from the go-flare Docker Hub tags page.
-
Stop and remove the old container:
docker stop <your_container_name> # e.g., flare-observer
docker rm <your_container_name> -
Update the
LATEST_TAG
to the new stable tag and run the samedocker run
command as previously detailed. Your data in/mnt/db
(or your chosen volume) will be preserved.
-
Find the latest stable tag from the go-flare Docker Hub tags page.
-
Stop the old container:
docker compose -f /opt/observer/docker-compose.yaml down
-
Update the
docker-compose.yaml
file with the new tag and start the new container:LATEST_TAG="vX.Y.Z" # <-- Replace with the actual latest tag e.g v1.10.0
yq -i ".services.observer.image = flarefoundation/go-flare:${LATEST_TAG}" /opt/observer/docker-compose.yaml
docker compose -f /opt/observer/docker-compose.yaml up -d
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.