Skip to main content

How to start a cluster with Docker Compose

Guide

Start a 3-node Apache Ignite 3 or GridGain 9 cluster for development using Docker Compose.

ignite3gridgain9
Foundational|15 min|getting-started
Tested onApache Ignite 3.1.0GridGain 9.1.8

Prerequisites

  • Docker 20.10 or later
  • Docker Compose 2.23.1 or later (ships with Docker Desktop)
  • curl and jq for verifying cluster health
  • Ports 10300-10302 and 10800-10802 available on your machine
  • 12 GB of available RAM for three cluster nodes (4 GB minimum; see the memory note in Step 1)
  • GridGain 9 only: A license file from gridgain.com/tryfree (Community Edition or evaluation). Save the downloaded file as gridgain-license.json in your project directory alongside docker-compose.yml.

Overview

This guide walks you through starting a 3-node development cluster on your local machine with Docker Compose. By the end, you will have a running cluster that accepts client connections on ports 10800-10802 and exposes a REST management API on ports 10300-10302.

Both Apache Ignite 3 and GridGain 9 share the same distributed architecture and management interfaces. The Docker images, configuration paths, and license requirements differ between the two products, but the cluster lifecycle is the same: start nodes, initialize them into a cluster, then connect.

You have two tools for managing the cluster once the containers are running:

  • REST API (port 10300) accepts HTTP requests for cluster initialization, health checks, and configuration. It is available as soon as a node starts, even before the cluster is initialized. Use this when you want scriptable, automatable management.
  • CLI tool is an interactive command-line shell that communicates with the cluster through the REST API. It is bundled inside the server image, so you access it via docker exec on any running node. Use it for interactive sessions, SQL queries, or one-off administration. For a deeper walkthrough, see How to Work with the Ignite CLI.

Select your product version in the tabs below. Each step shows both management approaches where they differ.

Create a Docker Compose File

Create a directory for your project and add a file named docker-compose.yml with the following content.

docker-compose.yml
name: ignite3

x-ignite-def: &ignite-def
image: apacheignite/ignite:3.1.0
environment:
JVM_MAX_MEM: "4g"
JVM_MIN_MEM: "4g"
configs:
- source: node_config
target: /opt/ignite/etc/ignite-config.conf

services:
node1:
<<: *ignite-def
container_name: ignite3-node1
command: --node-name node1
ports:
- "10300:10300"
- "10800:10800"

node2:
<<: *ignite-def
container_name: ignite3-node2
command: --node-name node2
ports:
- "10301:10300"
- "10801:10800"
depends_on:
- node1

node3:
<<: *ignite-def
container_name: ignite3-node3
command: --node-name node3
ports:
- "10302:10300"
- "10802:10800"
depends_on:
- node1
- node2

configs:
node_config:
content: |
ignite {
network {
port: 3344
nodeFinder.netClusterNodes = ["node1:3344", "node2:3344", "node3:3344"]
}
}

The YAML anchor (x-ignite-def) keeps the node definitions consistent. Each node exposes two ports: 10300 for the REST management API and 10800 for client connections (JDBC, ODBC, and thin client drivers). The Ignite CLI is bundled inside the server image, so you access it via docker exec on any running node.

Port 3344 handles internal cluster communication between nodes. Docker's internal network routes this traffic, so you don't need to expose it to the host.

note

Reduce JVM_MAX_MEM and JVM_MIN_MEM to 1g if your machine has less than 16 GB of RAM. Each node will use approximately 1 GB instead of 4 GB. Performance will be adequate for development and tutorial workloads.

Start the Cluster

This command works for both Apache Ignite 3 and GridGain 9:

docker compose up -d

Expected output:

[+] Running 4/4
✔ Network ignite3_default Created
✔ Container ignite3-node1 Started
✔ Container ignite3-node2 Started
✔ Container ignite3-node3 Started

The nodes need a few seconds to discover each other over port 3344 and form a physical topology. Verify all three containers are running:

docker compose ps --format "table {{.Name}}\t{{.Image}}\t{{.Status}}"

Expected output:

NAME IMAGE STATUS
ignite3-node1 apacheignite/ignite:3.1.0 Up 30 seconds
ignite3-node2 apacheignite/ignite:3.1.0 Up 29 seconds
ignite3-node3 apacheignite/ignite:3.1.0 Up 28 seconds

Checkpoint: All three containers show Up status. If any container shows Restarting or Exited, see Troubleshooting.

Initialize the Cluster

At this point, the nodes are running and can see each other, but they are not yet a cluster. Initialization is a one-time step that elects a leader, designates which nodes store cluster metadata, and opens client connection ports (10800). Until you initialize, the REST API on port 10300 is the only way to interact with the nodes.

Choose your preferred management tool below. Both accomplish the same result.

Send the initialization request to any node's REST endpoint. The REST API is available on all three nodes (ports 10300, 10301, 10302), but you only need to send the init request once.

curl -X POST http://localhost:10300/management/v1/cluster/init \
-H "Content-Type: application/json" \
-d '{
"metaStorageNodes": ["node1", "node2", "node3"],
"cmgNodes": ["node1", "node2", "node3"],
"clusterName": "my-cluster"
}'

A successful initialization returns HTTP 200 with an empty response body.

Allow a few seconds for the nodes to elect a leader and synchronize metadata before verifying.

Checkpoint: Initialization completes without errors. If the command hangs or returns a connection error, wait 30-60 seconds for the nodes to finish starting, then retry.

Verify Cluster Health

Once the cluster is initialized, confirm that all three nodes joined successfully. This verification works the same way for both Apache Ignite 3 and GridGain 9.

curl -s http://localhost:10300/management/v1/cluster/state | jq .

Expected output:

{
"cmgNodes": ["node1", "node2", "node3"],
"msNodes": ["node1", "node2", "node3"],
"igniteVersion": "3.1.0",
"clusterTag": {
"clusterName": "my-cluster",
"clusterId": "..."
}
}

Both cmgNodes (cluster management group) and msNodes (metastorage nodes) should list all three nodes. The igniteVersion field reflects the product version.

Checkpoint: Both cmgNodes and msNodes list all three nodes, confirming the cluster is healthy and accepting client connections on port 10800.

Stopping and Restarting

All Docker Compose lifecycle commands work identically for both Apache Ignite 3 and GridGain 9.

Stop the cluster (preserves data):

docker compose stop

This stops the containers without removing them. Data, cluster state, and initialization all persist.

Restart a stopped cluster:

docker compose up -d

The nodes rejoin the existing cluster automatically. You do not need to re-initialize. Client connections on port 10800 become available once the nodes finish starting (typically 15-30 seconds). This same command also works after docker compose down to create a fresh cluster (which will require re-initialization).

Remove the cluster (destroys data):

docker compose down

This removes all containers and the default network, destroying all data. The next docker compose up -d starts a fresh cluster that requires re-initialization.

Remove the cluster and all volumes:

docker compose down -v

This also removes named volumes for a completely clean state.

Troubleshooting

These issues apply to both Apache Ignite 3 and GridGain 9 unless noted otherwise.

Port conflict on startup

docker compose up -d fails with Bind for 0.0.0.0:10300 failed: port is already allocated.

Another process is using one of the required ports. Identify it:

lsof -i :10300

Stop the conflicting process, or change the host port mapping in docker-compose.yml. For example, map to port 10400 instead:

ports:
- "10400:10300"

Adjust all subsequent commands to use the new port number.

Initialization timeout

The curl command to /management/v1/cluster/init hangs or returns connection refused.

The nodes are not ready yet. Check that all containers are running:

docker compose ps

If a container shows Restarting or Exited, check its logs:

docker compose logs node1

Wait for the REST API to become available (30-60 seconds after startup):

curl -sf http://localhost:10300/management/v1/node/state

When this returns a JSON response, the node is ready for initialization.

Fewer than 3 nodes in cluster state

/management/v1/cluster/state shows fewer than 3 nodes in cmgNodes or msNodes.

The cluster was initialized before all nodes discovered each other. In a development environment, the safest fix is to start over:

docker compose down
docker compose up -d

Wait 30-60 seconds for all nodes to discover each other, then re-initialize.

Client connection refused on port 10800

An application connecting to localhost:10800 gets Connection refused after the containers are running.

Client ports open only after cluster initialization. Verify the cluster is initialized:

curl -s http://localhost:10300/management/v1/cluster/state | jq .clusterTag.clusterName

If this returns null or an error, the cluster has not been initialized. Complete the Initialize the Cluster step above.

GridGain 9: License error during REST API initialization

GridGain 9 only. The REST API returns HTTP 400 with a message about a missing or invalid license.

Verify that gridgain-license.json exists in the same directory as docker-compose.yml:

ls -la gridgain-license.json

Verify the file contains valid JSON:

cat gridgain-license.json | jq .

The license field in the curl command must be a JSON-encoded string of the file contents, not the filename. Use LICENSE=$(jq -Rs . gridgain-license.json) to load the license into a variable as shown in the initialization step.

GridGain 9: License error during CLI initialization

GridGain 9 only. The CLI returns an error about a missing license when running cluster init.

Verify the license file was copied into the container:

docker exec gridgain9-node1 cat /opt/gridgain9cli/license.json | head -1

If the file is missing, copy it again:

docker cp gridgain-license.json gridgain9-node1:/opt/gridgain9cli/license.json

Use the --license=/opt/gridgain9cli/license.json flag with the cluster init command.

GridGain 9: "License for a private version is required"

GridGain 9 only. Cluster initialization or a join request fails with:

License violation detected: A license for a private version is required.
The provided license is only applicable for public versions and cannot
be used with a private version.

This error means your license type does not match your GridGain 9 build type. GridGain 9 has two release types:

  • Public covers the Community Edition (currently 9.1.8). A public (free) license only works with public builds.
  • Private covers Enterprise and Ultimate (currently 9.1.20). A private license works with any build, public or private.

Check which Docker image tag you are using in docker-compose.yml:

grep 'image:' docker-compose.yml

If you see a version newer than 9.1.8 (such as 9.1.20), you are running a private build that requires a private (paid) license. To fix this, either:

  1. Switch to the public build by changing the image tag to gridgain/gridgain9:9.1.8 in your docker-compose.yml, then restart the cluster with a clean state:
docker compose down -v
docker compose up -d
  1. Use a private license if you have an Enterprise or Ultimate subscription.

The same mismatch applies to Maven dependencies. If your pom.xml references a version newer than 9.1.8 (e.g., 9.1.20), Maven will fail to resolve it from the GridGain Nexus repository unless you have private repository access.

Your cluster is now accepting client connections on ports 10800-10802. You can connect with any Ignite thin client driver, JDBC (jdbc:ignite:thin://localhost:10800), or ODBC.