tree: 6bc1506c64cb33ba7b61ec8ce78849eb33b78ff4
  1. hbase/
  2. docker-compose-3pd-3store-3server.yml
  3. docker-compose.dev.yml
  4. docker-compose.yml
  5. hugegraph-hubble.properties
  6. README.md
docker/README.md

HugeGraph Docker Deployment

This directory contains Docker Compose files for running HugeGraph:

FileDescription
docker-compose.ymlPD, Store, Server, and Hubble using pre-built images
docker-compose.dev.ymlPD, Store, and Server built from source, plus Hubble
docker-compose-3pd-3store-3server.yml3-node distributed cluster (PD + Store + Server)

Prerequisites

  • Docker Engine 20.10+ (or Docker Desktop 4.x+)
  • Docker Compose v2 (included in Docker Desktop)
  • OpenSSL CLI (used to generate the initial administrator password)
  • Memory: Allocate at least 12 GB to Docker Desktop (Settings → Resources → Memory). The 3-node cluster runs 9 JVM processes (3 PD + 3 Store + 3 Server) which are memory-intensive. Insufficient memory causes OOM kills that appear as silent Raft failures.

[!IMPORTANT] The 12 GB minimum is for Docker Desktop. On Linux with native Docker, ensure the host has at least 12 GB of free memory.


Single-Node Setup

Two compose files run one PD, one Store, one Server, and one Hubble instance:

Create a Compose environment file once so every lifecycle command can resolve the required administrator password:

(
  set -eu
  cd docker
  if [ -e .env ]; then
    echo "docker/.env already exists; reusing it"
  else
    command -v openssl >/dev/null 2>&1
    admin_password="$(openssl rand -base64 12)"
    if [ "${#admin_password}" -ne 16 ]; then
      echo "Failed to generate a 16-character password" >&2
      exit 1
    fi
    install -m 600 /dev/null .env
    {
      printf "HUGEGRAPH_ADMIN_PASSWORD='%s'\n" "${admin_password}"
    } >> .env
    unset admin_password
  fi
  chmod 600 .env
  if ! env -u HUGEGRAPH_ADMIN_PASSWORD \
       docker compose -f docker-compose.yml config --quiet ||
     ! env -u HUGEGRAPH_ADMIN_PASSWORD \
       docker compose -f docker-compose.dev.yml config --quiet; then
    echo "docker/.env is incomplete; repair or move it, then retry" >&2
    exit 1
  fi
)

Compose automatically reads docker/.env for up, ps, stop, and down. The generated password is a 16-character, Compose-safe random value. The file is excluded from Git and Docker build contexts; keep its permissions restricted and source production credentials from your secret manager instead of committing them.

Option A: Quick Start (pre-built images)

Uses pre-built images from Docker Hub. Best for end users who want to run HugeGraph quickly. Set HUGEGRAPH_VERSION to the same published release for PD, Store, Server, and Hubble. The authenticated PD/Hubble integration is not present in 1.7.x; if no later compatible release is available, use Option B.

(
  cd docker
  HUGEGRAPH_VERSION='<compatible-release-after-1.7.x>' \
  docker compose up -d
)
  • Images: matching hugegraph/pd, hugegraph/store, hugegraph/server, and hugegraph/hubble tags from the selected compatible release
  • pull_policy: always — always pulls the specified image tag

Note: Do not use latest to claim a reproducible deployment. Pin a compatible release tag and keep it unchanged for later lifecycle commands.

  • PD healthcheck endpoint: /v1/health
  • Hubble is available at http://localhost:8088; sign in as admin with the required HUGEGRAPH_ADMIN_PASSWORD
  • Hubble binds to host loopback by default. Set HUBBLE_PUBLISH_HOST explicitly only behind an HTTPS reverse proxy and trusted network controls.
  • Hubble uses PD discovery and the Docker-network Server address
  • Server healthcheck endpoint: /versions

Option B: Development Build (build from source)

Builds images locally from source Dockerfiles. Best for developers who want to test local changes. Build the matching hugegraph-toolchain Hubble source as local/hugegraph-hubble:dev before starting this stack.

(
  cd docker
  HUBBLE_IMAGE=local/hugegraph-hubble:dev \
  HUBBLE_PULL_POLICY=never \
  docker compose -f docker-compose.dev.yml up -d
)
  • PD, Store, and Server images are built from this repository
  • Hubble uses HUBBLE_IMAGE because its source is in hugegraph-toolchain
  • Server entrypoint scripts are baked into the built image; Hubble mounts the Docker-local PD configuration
  • PD healthcheck endpoint: /v1/health
  • Otherwise identical env vars and structure to the quickstart file

Use the same release tag for Option A lifecycle commands:

(
  cd docker
  export HUGEGRAPH_VERSION='<same-compatible-release>'
  docker compose ps
  docker compose stop
  docker compose down
)

Use the development Compose file for every Option B lifecycle command:

(
  cd docker
  docker compose -f docker-compose.dev.yml ps
  docker compose -f docker-compose.dev.yml stop
  docker compose -f docker-compose.dev.yml down
)

Key Differences

docker-compose.yml (quickstart)docker-compose.dev.yml (dev build)
ImagesPull from Docker HubBuild from source
Who it's forEnd usersDevelopers
Server pull_policyalwaysbuild
Hubble pull_policyalwaysnever in the workflow above (missing in the Compose file by default)

Verify (both options):

curl http://localhost:8080/versions
curl -fsS http://localhost:8088/about

To validate local images without Compose replacing them with remote latest:

(
  cd docker
  HUGEGRAPH_SERVER_IMAGE=local/hugegraph-server:test \
  HUGEGRAPH_SERVER_PULL_POLICY=never \
  HUBBLE_IMAGE=local/hugegraph-hubble:test \
  HUBBLE_PULL_POLICY=never \
  docker compose up -d --wait
)

3-Node Cluster Quickstart

cd docker
HUGEGRAPH_VERSION=1.7.0 docker compose -f docker-compose-3pd-3store-3server.yml up -d

# To stop and remove all data volumes (clean restart)
docker compose -f docker-compose-3pd-3store-3server.yml down -v

Startup ordering is enforced via depends_on with condition: service_healthy:

  1. PD nodes start first and must pass healthchecks (/v1/health)
  2. Store nodes start after all PD nodes are healthy
  3. Server nodes start after all Store nodes are healthy

This ensures PD and Store are healthy before the server starts. The server entrypoint still performs a best-effort partition wait after launch, so partition assignment may take a little longer.

Verify the cluster is healthy:

# Check PD health
curl http://localhost:8620/v1/health

# Check Store health
curl http://localhost:8520/v1/health

# Check Server (Graph API)
curl http://localhost:8080/versions

# List registered stores via PD
curl http://localhost:8620/v1/stores

# List partitions
curl http://localhost:8620/v1/partitions

Environment Variable Reference

Configuration is injected via environment variables. The old docker/configs/application-pd*.yml and docker/configs/application-store*.yml files are no longer used.

PD Environment Variables

VariableRequiredDefaultMaps To (application.yml)Description
HG_PD_GRPC_HOSTYesgrpc.hostThis node's hostname/IP for gRPC
HG_PD_RAFT_ADDRESSYesraft.addressThis node's Raft address (e.g. pd0:8610)
HG_PD_RAFT_PEERS_LISTYesraft.peers-listAll PD peers (e.g. pd0:8610,pd1:8610,pd2:8610)
HG_PD_INITIAL_STORE_LISTYespd.initial-store-listExpected stores (e.g. store0:8500,store1:8500,store2:8500)
HG_PD_GRPC_PORTNo8686grpc.portgRPC server port
HG_PD_REST_PORTNo8620server.portREST API port
HG_PD_DATA_PATHNo/hugegraph-pd/pd_datapd.data-pathMetadata storage path
HG_PD_INITIAL_STORE_COUNTNo1pd.initial-store-countMin stores for cluster availability

Deprecated aliases (still work but log a warning):

DeprecatedUse Instead
GRPC_HOSTHG_PD_GRPC_HOST
RAFT_ADDRESSHG_PD_RAFT_ADDRESS
RAFT_PEERSHG_PD_RAFT_PEERS_LIST
PD_INITIAL_STORE_LISTHG_PD_INITIAL_STORE_LIST

Store Environment Variables

VariableRequiredDefaultMaps To (application.yml)Description
HG_STORE_PD_ADDRESSYespdserver.addressPD gRPC addresses (e.g. pd0:8686,pd1:8686,pd2:8686)
HG_STORE_GRPC_HOSTYesgrpc.hostThis node's hostname (e.g. store0)
HG_STORE_RAFT_ADDRESSYesraft.addressThis node's Raft address (e.g. store0:8510)
HG_STORE_GRPC_PORTNo8500grpc.portgRPC server port
HG_STORE_REST_PORTNo8520server.portREST API port
HG_STORE_DATA_PATHNo/hugegraph-store/storageapp.data-pathData storage path

Deprecated aliases (still work but log a warning):

DeprecatedUse Instead
PD_ADDRESSHG_STORE_PD_ADDRESS
GRPC_HOSTHG_STORE_GRPC_HOST
RAFT_ADDRESSHG_STORE_RAFT_ADDRESS

Server Environment Variables

VariableRequiredDefaultMaps ToDescription
HG_SERVER_BACKENDYesbackend in hugegraph.propertiesStorage backend (e.g. hstore)
HG_SERVER_PD_PEERSYespd.peersPD cluster addresses (e.g. pd0:8686,pd1:8686,pd2:8686)
HG_SERVER_CLUSTERNocluster in rest-server.propertiesPD discovery application name; single-node Compose uses hg to match Hubble
HG_SERVER_USE_PDNousePD in rest-server.propertiesEnables Server PD registration and discovery
HG_SERVER_REST_URLNorestserver.urlAddress registered with PD and used by clients
HG_SERVER_MIN_FREE_MEMORYNorestserver.min_free_memoryMinimum free-memory guard in MB; local Compose uses 0
HG_SERVER_AUTH_TOKEN_SECRETNogenerated in auth modeauth.token_secretShared JWT secret for REST and embedded Gremlin authentication; explicit values must be at least 32 bytes
STORE_RESTNoUsed by wait-partition.shStore REST endpoint for partition verification (e.g. store0:8520)
PASSWORDNoEnables auth and sets auth.admin_paInitial administrator password; disabled init-store does not read it from stdin, but the entrypoint still applies it to the PD bootstrap path
HG_SERVER_INIT_STORE_ENABLEDNotrueinit_store.enabled in rest-server.propertiesSet false in PD/HStore deployments so init-store skips local backend and admin initialization

The built-in authenticator with HG_SERVER_INIT_STORE_ENABLED=false requires usePD=true and an HStore-backed auth.graph_store, unless auth.remote_url delegates auth elsewhere. With init-store skipped, the server creates the built-in admin in PD metadata, and only an HStore auth graph uses the PD-backed auth manager that can read that account. init-store exits non-zero when the combination is unusable, rather than leaving a server nobody can log in to. A custom auth.authenticator is exempt because it manages its own identities.

docker/init_complete is written by init-store itself, and only after it has initialized. A skipped run therefore records nothing, whether it was disabled by the variable or by the property in a mounted rest-server.properties, so a later re-enable is still able to initialize. The marker only short-circuits re-initialization: init-store runs on every container start, and a disabled one performs the fail-closed check above first, so a marker left by an earlier release or an earlier enabled run cannot bypass it.

The entrypoint maps PASSWORD to auth.admin_pa before init-store runs. A disabled init-store does not read the password from standard input, but the PD startup path uses the explicit auth.admin_pa value when it first creates the administrator. Changing it later does not rotate an existing password.

The single-node Compose files also accept these deployment-level overrides:

VariableDefaultDescription
HUGEGRAPH_SERVER_IMAGEhugegraph/server:<version>Complete Server image reference
HUGEGRAPH_SERVER_PULL_POLICYalways (build for dev)Server pull policy
HUBBLE_IMAGEhugegraph/hubble:<version>Complete Hubble image reference
HUBBLE_PULL_POLICYalways (missing for dev)Hubble pull policy
HUBBLE_PUBLISH_HOST127.0.0.1Hubble host bind address; remote access requires an HTTPS reverse proxy
HUGEGRAPH_ADMIN_PASSWORDrequired (docker/.env)Initial admin password; no public default is provided
HUGEGRAPH_AUTH_TOKEN_SECRETgeneratedJWT signing secret; explicit values must be at least 32 bytes

When authentication is enabled and no token secret is supplied, the Server entrypoint generates a random secret and writes it to both authentication configurations. The value is reused on container restart while the container filesystem is preserved. To preserve tokens across container recreation, generate a compatible secret once and add it to the mode-600 docker/.env:

(
  set -euo pipefail
  cd docker
  secret_pattern='^[[:space:]]*(export[[:space:]]+)?HUGEGRAPH_AUTH_TOKEN_SECRET[[:space:]]*='
  secret_count="$(grep -Ec "${secret_pattern}" .env || true)"
  case "${secret_count}" in
    0)
      command -v openssl >/dev/null 2>&1
      token_secret="$(openssl rand -hex 32)"
      LC_ALL=C
      if (( ${#token_secret} != 64 )); then
        echo "Failed to generate a 64-character token secret" >&2
        exit 1
      fi
      printf "HUGEGRAPH_AUTH_TOKEN_SECRET='%s'\n" \
        "${token_secret}" >> .env
      unset token_secret
      echo "Generated HUGEGRAPH_AUTH_TOKEN_SECRET"
      ;;
    1)
      token_secret="$(
        sed -nE \
          "s/${secret_pattern}'([^']*)'[[:space:]]*$/\\2/p" .env
      )"
      LC_ALL=C
      if (( ${#token_secret} < 32 )); then
        echo "Existing token secret must use the documented single-quoted" \
             "format and contain at least 32 bytes; .env was not changed" >&2
        exit 1
      fi
      unset token_secret
      echo "HUGEGRAPH_AUTH_TOKEN_SECRET already exists; reusing it"
      ;;
    *)
      echo "Duplicate HUGEGRAPH_AUTH_TOKEN_SECRET entries; repair .env" >&2
      exit 1
      ;;
  esac
  chmod 600 .env
)

The entrypoint rejects shorter explicit values before changing either Server configuration file.

Deprecated aliases (still work but log a warning):

DeprecatedUse Instead
BACKENDHG_SERVER_BACKEND
PD_PEERSHG_SERVER_PD_PEERS

Port Reference

The table below reflects the published host ports in docker-compose-3pd-3store-3server.yml. The single-node Compose file publishes 8620, 8520, 8080, and Hubble 8088; Hubble defaults to host loopback.

ServiceContainer PortHost PortProtocolPurpose
pd086208620HTTPREST API
pd086868686gRPCPD gRPC
pd08610TCPRaft (internal only)
pd186208621HTTPREST API
pd186868687gRPCPD gRPC
pd286208622HTTPREST API
pd286868688gRPCPD gRPC
store085008500gRPCStore gRPC
store085108510TCPRaft
store085208520HTTPREST API
store185008501gRPCStore gRPC
store185108511TCPRaft
store185208521HTTPREST API
store285008502gRPCStore gRPC
store285108512TCPRaft
store285208522HTTPREST API
server080808080HTTPGraph API
server180808081HTTPGraph API
server280808082HTTPGraph API

Healthcheck Endpoints

ServiceEndpointExpected
PDGET /v1/health200 OK
StoreGET /v1/health200 OK
ServerGET /versions200 OK with version JSON
HubbleGET /about200 JSON with Hubble name and version

Troubleshooting

Containers Exiting or Restarting (OOM Kills)

Symptom: Containers exit with code 137, or restart loops. Raft logs show election timeouts.

Cause: Docker Desktop does not have enough memory. The 9 JVM processes require at least 12 GB.

Fix: Docker Desktop → Settings → Resources → Memory → set to 12 GB or higher. Restart Docker Desktop.

# Check if containers were OOM killed
docker inspect hg-pd0 | grep -i oom
docker stats --no-stream

Raft Leader Election Failure

Symptom: PD logs show repeated Leader election timeout. Store nodes cannot register.

Cause: PD nodes cannot reach each other on the Raft port (8610), or HG_PD_RAFT_PEERS_LIST is misconfigured.

Fix:

  1. Verify all PD containers are running: docker compose -f docker-compose-3pd-3store-3server.yml ps
  2. Check PD logs: docker logs hg-pd0
  3. Verify network connectivity: docker exec hg-pd0 ping pd1
  4. Ensure HG_PD_RAFT_PEERS_LIST is identical on all PD nodes

Partition Assignment Not Completing

Symptom: Server starts but graph operations fail. Store logs show partition not found.

Cause: PD has not finished assigning partitions to stores, or stores did not register successfully.

Fix:

  1. Check registered stores: curl http://localhost:8620/v1/stores
  2. Check partition status: curl http://localhost:8620/v1/partitions
  3. Wait for partition assignment (can take 1–3 minutes after all stores register)
  4. Check server logs for the wait-partition.sh script output: docker logs hg-server0

Connection Refused Errors

Symptom: Stores cannot connect to PD, or Server cannot connect to Store.

Cause: Services are using 127.0.0.1 instead of container hostnames, or the hg-net bridge network is misconfigured.

Fix: Ensure all HG_* env vars use container hostnames (pd0, store0, etc.), not 127.0.0.1 or localhost.