Since writing this post, Coda has rebranded to Mina Protocol. I’ve left the article in its original form but all references to Coda are equivalent to Mina.

Docker provides one of the simplest ways of getting a Coda node up and running while providing the benefits of container isolation. It also resolves issues around dependencies on unsupported systems and allows specifying restart policies should the daemon crash.

It is important to use the correct image for each testnet release. The tags for all releases are available on DockerHub. For testnet 3.2b this tag is 0.0.12-beta-feature-bump-genesis-timestamp-3e9b174. This image is updated for each testnet, so the image used in the below commands should be updated accordingly.

At its simplest, we can start a Coda node with the following command. We’ll build upon this basic command for other Coda specific functions such as block production and SNARK workers.

In the above command, you should replace <PEER_1> and <PEER_2> with the correct peer addresses that are made available.

The command will create a container named coda and output a container id, with the container running in the background (due to the -d or --detached option). The --restart always option means that if the container exits, it will automatically restart. There are two published ports (8302, 8303) to allow communication on the peer-to-peer network. To view the running container's status, run docker ps that should display output similar to the below. Checking the status column, it will indicate any potential issues, such as the container crash-looping.

To view the logs of the container, you can tail the log output using the command:

To interact with the Coda daemon, you can exec into the container to run the available commands. For example, running docker exec -it coda bash will open a terminal inside the container from where you can run any available coda commands, such as coda client status.

Alternatively, you can run from the command line non-interactively, e.g. docker exec coda coda client status. The format of this command is docker exec container_name <COMMAND TO RUN>.

Running a block producer

As a next step, let’s run a block producer. We’ll remove the current instance via docker rm -f coda to remove the running container and avoid container name and published port conflicts. To run a block producer, you will need the private key and corresponding password for the key that you wish to stake with.

While this private key may be located anywhere on your host system in the following example, the private key (generated via the Coda keygen tool) is in a subdirectory keys and named my-wallet. This key will be bind mounted into the container at /root/keys. We also pass an environment variable of CODA_PRIVKEY_PASS to set the password for the key non-interactively.

Ensure you are running the following command from the directory that contains the keys subdirectory or adjust the bind mount accordingly below, which needs to be an absolute path.

Once again, you will be returned a container id, and you can follow the logs to identify any potential issues. The following command should indicate a block producer is running with your public key:

Running a SNARK worker

Another advantage of running the Coda daemon in Docker is limiting the available resources to the container. These resource constraints are of particular use to SNARK workers that will, by default, use all available resources. By default, a container has no resource constraints. However, you can set limits to, for example, the memory available and the number of cpus to use via the --memory and --cpus options.

To run a SNARK worker in the same container you can add the following option to the previous docker run command :-run-snark-worker <PUBLIC_KEY>

It is not generally recommended to run a SNARK worker and a block producer on the same machine as it can affect block production. While workarounds exist to disable the SNARK worker at the time of block production, you could alternatively run multiple containers on a machine (adjusting published ports as necessary) with applicable resource constraints.

The following example limits the container running a SNARK worker to 4 CPUs and 8GB of RAM. To avoid port conflicts with the container running the block producer we have specified-external-port to use an unused port.

Accessing the GraphQL API

The GraphQL API is available to interact with the Coda daemon. You can read more about the API in this article.

By default, the GraphQL API is bound to localhost. To access it outside of the container, you will need to pass the -insecure-rest-server option allowing the API to listen on all interfaces and then publish this port outside of the container. Crucially, if you do this, you must block the port (3085 by default) from external users via a firewall on the host, as the API is unauthenticated, and anyone with access could gain access to your wallet.

Once this is running, on the host where Docker is running, visit localhost:3085/graphql. If you are using a VM, you can use SSH port forwarding to forward port 3085 on your development machine to the remote machine, e.g., ssh -L3085: user@remotehost.

GraphiQL running on localhost

Additional options

There are many other options available to customize the running daemon, and you should consult the documentation. You can optionally add these options to the docker command, such as -coinbase-receiver that will direct any coinbase payments to an address other than the block producer key, such as to a cold storage wallet.

Technical writer, data wrangler and (former) full stack dev

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store