bitflicker64 commented on code in PR #3149:
URL: https://github.com/apache/hugegraph/pull/3149#discussion_r3892095050
##########
docker/docker-compose-3pd-3store-3server.yml:
##########
@@ -68,11 +81,9 @@ x-server-common: &server-common
store1: { condition: service_healthy }
store2: { condition: service_healthy }
environment:
- STORE_REST: store0:8520
- HG_SERVER_BACKEND: hstore
- HG_SERVER_PD_PEERS: pd0:8686,pd1:8686,pd2:8686
+ <<: *server-environment
healthcheck:
- test: ["CMD-SHELL", "curl -fsS http://localhost:8080/versions >/dev/null
|| exit 1"]
+ test: ["CMD-SHELL", "curl -fsS http://server0:8080/versions >/dev/null"]
Review Comment:
**These three per-server `healthcheck` overrides are new in this PR, and
rendering suggests they also drop the anchor timings.**
`<<: *server-common` merges shallowly, so a per-service `healthcheck:` key
replaces the whole map from the anchor rather than merging into it. Rendered on
this head:
```console
$ docker compose -f docker-compose-3pd-3store-3server.yml config --format
json \
| jq -c '.services.server0.healthcheck, .services.store0.healthcheck'
{"test":["CMD-SHELL","curl -fsS http://server0:8080/versions >/dev/null"]}
{"test":["CMD-SHELL","curl -fsS http://localhost:8520/v1/health >/dev/null
|| exit 1"],"timeout":"15s","interval":"15s","retries":40,"start_period":"2m0s"}
```
`store0` keeps its timings. `server0/1/2` keep only `test`, losing
`interval: 10s`, `timeout: 5s`, `retries: 30` and, most importantly,
`start_period: 60s`, so they fall back to engine defaults (30s interval, 3
retries, no start period). That marks a Server unhealthy roughly 90s after
container start, while the entrypoint still has `wait-storage`, `init-store`
and `start-hugegraph.sh -t 120` to get through, so `up -d --wait` on HA can
fail before the Server is ready. Before this PR all three inherited the anchor
timings, and HA is never started in CI, so nothing catches it today.
If you agree, the fix is a deletion: keep one healthcheck in
`x-server-common` and remove the overrides at 205-206, 216-217 and 227-228. The
anchor `test` on line 86 then needs to work for all three, which `hostname`
gives you:
```suggestion
test: ["CMD-SHELL", "curl -fsS http://$$(hostname):8080/versions
>/dev/null"]
```
`hostname:` is already set per service, `$$` unescapes to `$` in the
container exactly like the existing Hubble healthcheck, and I confirmed the
image has `/usr/bin/hostname` and that the container self-resolves that name.
Plain `localhost` would not work, since `restserver.url` is the Grizzly bind
address. Applied to a copy, all three Servers then render with the full timings.
Coupled edit: `assert_ha` lines 197-202 collapse from the three element
array comparison to one `all(...)`, also a net deletion. Note `config --format
json` re-escapes `$` as `$$`, so the expected string there is the literal `curl
-fsS http://$$(hostname):8080/versions >/dev/null`.
##########
docker/docker-compose-hstore.yml:
##########
@@ -0,0 +1,131 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: hugegraph-hstore
+
+networks:
+ hg-net:
+
+volumes:
+ pd-data:
+ store-data:
+ hubble-data:
+
+services:
+ pd:
+ image: hugegraph/pd:${HUGEGRAPH_VERSION:-latest}
+ pull_policy: ${HUGEGRAPH_PULL_POLICY:-missing}
+ restart: unless-stopped
+ networks: [hg-net]
+ environment:
+ HG_PD_GRPC_HOST: pd
+ HG_PD_GRPC_PORT: "8686"
+ HG_PD_REST_PORT: "8620"
+ HG_PD_RAFT_ADDRESS: pd:8610
+ HG_PD_RAFT_PEERS_LIST: pd:8610
+ HG_PD_INITIAL_STORE_LIST: store:8500
+ HG_PD_DATA_PATH: /hugegraph-pd/pd_data
+ ports:
+ - "8620:8620"
+ volumes:
+ - pd-data:/hugegraph-pd/pd_data
+ healthcheck:
+ test: ["CMD-SHELL", "curl -fsS http://localhost:8620/v1/health
>/dev/null"]
+ interval: 10s
+ timeout: 5s
+ retries: 12
+ start_period: 30s
+
+ store:
+ image: hugegraph/store:${HUGEGRAPH_VERSION:-latest}
+ pull_policy: ${HUGEGRAPH_PULL_POLICY:-missing}
+ restart: unless-stopped
+ networks: [hg-net]
+ depends_on:
+ pd:
+ condition: service_healthy
+ environment:
+ HG_STORE_PD_ADDRESS: pd:8686
+ HG_STORE_GRPC_HOST: store
+ HG_STORE_GRPC_PORT: "8500"
+ HG_STORE_REST_PORT: "8520"
+ HG_STORE_RAFT_ADDRESS: store:8510
+ HG_STORE_DATA_PATH: /hugegraph-store/storage
+ ports:
+ - "8520:8520"
+ volumes:
+ - store-data:/hugegraph-store/storage
+ healthcheck:
+ test: ["CMD-SHELL", "curl -fsS http://localhost:8520/v1/health
>/dev/null"]
+ interval: 10s
+ timeout: 10s
+ retries: 30
+ start_period: 60s
+
+ server:
+ image: hugegraph/server:${HUGEGRAPH_VERSION:-latest}
+ pull_policy: ${HUGEGRAPH_PULL_POLICY:-missing}
+ restart: unless-stopped
+ networks: [hg-net]
+ depends_on:
+ store:
+ condition: service_healthy
+ environment:
+ HG_SERVER_BACKEND: hstore
+ HG_SERVER_PD_PEERS: pd:8686
+ HG_SERVER_CLUSTER: hg
+ HG_SERVER_USE_PD: "true"
+ HG_SERVER_REST_URL: http://server:8080
+ HG_SERVER_MIN_FREE_MEMORY: "0"
+ HG_SERVER_INIT_STORE_ENABLED: "false"
+ HG_SERVER_AUTH_TOKEN_SECRET: ${HUGEGRAPH_AUTH_TOKEN_SECRET:-}
+ PASSWORD: ${HUGEGRAPH_ADMIN_PASSWORD:-}
+ ports:
+ - "8080:8080"
Review Comment:
**Should the Server REST port be loopback-gated the way Hubble is?**
Hubble gets `${HUBBLE_PUBLISH_HOST:-127.0.0.1}` on line 117, but Server
here, PD on line 43 and Store on line 69 all publish to `0.0.0.0` by default.
The README warns at some length about exposing Hubble and documents a supported
auth-off mode, and `assert_hubble` asserts `host_ip == "127.0.0.1"` for Hubble
and nothing for the others. The graph API is the actual data and auth boundary
though, so in auth-off mode this is an unauthenticated graph API on every
interface, reachable from the local network, while the UI in front of it is the
part that is locked down.
Since this file is new in the PR it seemed worth raising here rather than
later. The same shape exists in the HA file, but those port lines are
untouched, so that one is a follow-up. Would a
`${HUGEGRAPH_PUBLISH_HOST:-127.0.0.1}` prefix on the three ports, matching the
Hubble pattern you already have, be reasonable? It is one variable rather than
three if you would rather keep it minimal.
##########
docker/README.md:
##########
@@ -1,436 +1,362 @@
-# HugeGraph Docker Deployment
+# HugeGraph Docker Compose
-This directory contains Docker Compose files for running HugeGraph:
+## Users
-| File | Description |
-|------|-------------|
-| `docker-compose.yml` | PD, Store, Server, and Hubble using pre-built images |
-| `docker-compose.dev.yml` | PD, Store, and Server built from source, plus
Hubble |
-| `docker-compose-3pd-3store-3server.yml` | 3-node distributed cluster (PD +
Store + Server) |
+### Choose a topology
-## Prerequisites
+Run commands in this directory:
-- **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.
+```bash
+cd docker
+```
-> [!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.
----
+| Topology | Compose file | Services | When to use it |
+| --- | --- | --- | --- |
+| Standalone | `docker-compose.yml` | 1 RocksDB Server + 1 Hubble | Default;
start here |
+| Minimal HStore | `docker-compose-hstore.yml` | 1 PD + 1 Store + 1 Server + 1
Hubble | Distributed local development |
+| HA | `docker-compose-3pd-3store-3server.yml` | 3 PD + 3 Store + 3 Server + 1
Hubble | Reference and evaluation |
-## Single-Node Setup
+Standalone uses `hugegraph/hugegraph:${HUGEGRAPH_VERSION:-latest}`. The HStore
+topologies use the matching `hugegraph/pd`, `hugegraph/store`, and
+`hugegraph/server` tags. Hubble is selected independently with
+`${HUBBLE_IMAGE:-hugegraph/hubble:latest}`.
-Two compose files run one PD, one Store, one Server, and one Hubble instance:
+### Create the authentication environment
-Create a Compose environment file once so every lifecycle command can resolve
the required administrator password:
+Create `.env` once. Replace `replace-with-your-password` with an administrator
+password that you choose; the command generates and persists a random 32-byte
+JWT secret. For this simple single-quoted format, do not use a password that
+contains a single quote or newline.
```bash
(
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
+ command -v openssl >/dev/null
+ jwt_secret="$(openssl rand -hex 32)"
+ test "${#jwt_secret}" -eq 64
+ umask 077
+ test ! -e .env || {
+ echo ".env already exists; edit it instead of overwriting it" >&2
exit 1
- fi
+ }
+ printf "HUGEGRAPH_ADMIN_PASSWORD='%s'\nHUGEGRAPH_AUTH_TOKEN_SECRET='%s'\n" \
+ 'replace-with-your-password' "${jwt_secret}" > .env
)
```
-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.
+Do not commit `.env`. Keeping the same JWT secret preserves authentication
+tokens when containers are recreated. For authenticated topologies with
+multiple Server replicas, all replicas receive this same secret. The HA
+topology fails fast if authentication is enabled without this shared secret.
-### Option A: Quick Start (pre-built images)
+A non-empty `HUGEGRAPH_ADMIN_PASSWORD` enables Server authentication, and
+Hubble detects that mode automatically. Omitting the variable or setting it to
+an empty value disables authentication. Auth-off is only suitable for a
+trusted local environment; never expose it to a public or untrusted network.
+Hubble listens on host loopback by default. Set `HUBBLE_PUBLISH_HOST` only
+behind an HTTPS reverse proxy and trusted network controls.
-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.
+`HUGEGRAPH_ADMIN_PASSWORD` initializes the built-in `admin` account on its
+first authenticated startup. Changing `.env` does not rotate an existing
+administrator password; use the HugeGraph user API for credential changes.
+
+For the verification commands below, set the password in your current shell:
```bash
-(
- cd docker
- HUGEGRAPH_VERSION='<compatible-release-after-1.7.x>' \
- docker compose up -d
-)
+ADMIN_PASSWORD='the-same-password-used-in-.env'
```
-- 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`
+### Standalone
-### Option B: Development Build (build from source)
+This is the recommended quickstart.
-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.
+Start:
-The publishing pipeline uses [`docker/bake.hcl`](./bake.hcl) from the
repository root to compile the Java reactor once and build the PD, Store,
HStore Server, and standalone Server runtime images from that shared result.
+```bash
+docker compose -f docker-compose.yml up -d --wait
+```
-Run Bake commands from the repository root. Use `--print` to inspect the
resolved targets without building, or run the default group to build all four
amd64/arm64 images. Loading both platforms under the same local tags requires
Docker's containerd image store.
+Status:
```bash
-# Inspect the resolved build graph
-docker buildx bake --file docker/bake.hcl --print
+docker compose -f docker-compose.yml ps
+```
+
+Verify Server readiness, authentication, and Hubble:
-# Build the default multi-platform target group
-IMAGE_TAG=local docker buildx bake --file docker/bake.hcl
+```bash
+curl -fsS http://localhost:8080/versions
+test "$(curl -sS -o /dev/null -w '%{http_code}' \
+ http://localhost:8080/graphspaces/DEFAULT/graphs)" = 401
+test "$(curl -sS -u "admin:${ADMIN_PASSWORD}" -o /dev/null -w '%{http_code}' \
+ http://localhost:8080/graphspaces/DEFAULT/graphs)" = 200
+curl -fsS http://localhost:8088/about
```
-Local source changes are included because Bake uses the current repository
working tree as its build context. For routine development, override all
targets to the host architecture so the four images still share one Maven build
without requiring the multi-platform containerd image store.
+Open `http://localhost:8088` and sign in as `admin` with the password from
+`.env`.
+
+Stop containers while keeping them:
```bash
-# x86_64 host
-IMAGE_TAG=local docker buildx bake --file docker/bake.hcl --set
'*.platform=linux/amd64'
+docker compose -f docker-compose.yml stop
+```
-# ARM64 host
-IMAGE_TAG=local docker buildx bake --file docker/bake.hcl --set
'*.platform=linux/arm64'
+Remove containers and the network while keeping data:
+
+```bash
+docker compose -f docker-compose.yml down
```
-These local commands can read existing Registry caches but do not publish
images or write remote caches because `EXPORT_CACHE` defaults to `false`.
+Delete containers, the network, and all topology data:
```bash
-(
- cd docker
- HUBBLE_IMAGE=local/hugegraph-hubble:dev \
- HUBBLE_PULL_POLICY=never \
- docker compose -f docker-compose.dev.yml up -d
-)
+docker compose -f docker-compose.yml down -v
```
Review Comment:
**Do the lifecycle blocks need to be repeated per topology?**
This Status / Open Hubble / stop / down / `down -v` tail is byte identical
in the Standalone, Minimal HStore and HA sections once the `-f` filename is
normalised, and `down` versus `down -v` is restated a fourth time under Data
persistence. That is roughly 78 lines saying one thing three times.
Since each Compose file declares its own project `name`
(`hugegraph-standalone`, `hugegraph-hstore`, `hugegraph-3x3`), `-f <file>`
alone fully scopes `ps`, `stop`, `down` and `down -v`, so a single shared
Lifecycle subsection reading "use the same `-f` as your Start command" is exact
rather than approximate. All volumes in all three renders are named and non
external, so the data sentence is uniformly true too, and Hubble is
`127.0.0.1:8088` everywhere, so "Open Hubble" only needs saying once.
Worth keeping per topology: Start and Verify, since the ports genuinely
differ. Would you take that trade, or do you prefer each section to stay
copy-paste complete?
##########
docker/docker-compose.yml:
##########
@@ -14,117 +14,59 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-name: hugegraph-single
+
+name: hugegraph-standalone
networks:
hg-net:
- driver: bridge
volumes:
- hg-pd-data:
- hg-store-data:
+ server-data:
+ hubble-data:
services:
-
- pd:
- image: hugegraph/pd:${HUGEGRAPH_VERSION:-latest}
- pull_policy: always
- container_name: hg-pd
- hostname: pd
- restart: unless-stopped
- networks: [hg-net]
- environment:
- HG_PD_GRPC_HOST: pd
- HG_PD_GRPC_PORT: "8686"
- HG_PD_REST_PORT: "8620"
- HG_PD_RAFT_ADDRESS: pd:8610
- HG_PD_RAFT_PEERS_LIST: pd:8610
- HG_PD_INITIAL_STORE_LIST: store:8500
- HG_PD_DATA_PATH: /hugegraph-pd/pd_data
- ports:
- - "8620:8620"
- volumes:
- - hg-pd-data:/hugegraph-pd/pd_data
- healthcheck:
- test: ["CMD-SHELL", "curl -fsS http://localhost:8620/v1/health
>/dev/null || exit 1"]
- interval: 10s
- timeout: 5s
- retries: 12
- start_period: 30s
-
- store:
- image: hugegraph/store:${HUGEGRAPH_VERSION:-latest}
- pull_policy: always
- container_name: hg-store
- hostname: store
- restart: unless-stopped
- networks: [hg-net]
- depends_on:
- pd:
- condition: service_healthy
- environment:
- HG_STORE_PD_ADDRESS: pd:8686
- HG_STORE_GRPC_HOST: store
- HG_STORE_GRPC_PORT: "8500"
- HG_STORE_REST_PORT: "8520"
- HG_STORE_RAFT_ADDRESS: store:8510
- HG_STORE_DATA_PATH: /hugegraph-store/storage
- ports:
- - "8520:8520"
- volumes:
- - hg-store-data:/hugegraph-store/storage
- healthcheck:
- test: ["CMD-SHELL", "curl -fsS http://localhost:8520/v1/health
>/dev/null || exit 1"]
- interval: 10s
- timeout: 10s
- retries: 30
- start_period: 60s
-
server:
- image:
${HUGEGRAPH_SERVER_IMAGE:-hugegraph/server:${HUGEGRAPH_VERSION:-latest}}
- pull_policy: ${HUGEGRAPH_SERVER_PULL_POLICY:-always}
- container_name: hg-server
- hostname: server
+ image: hugegraph/hugegraph:${HUGEGRAPH_VERSION:-latest}
+ pull_policy: ${HUGEGRAPH_PULL_POLICY:-missing}
restart: unless-stopped
networks: [hg-net]
- depends_on:
- store:
- condition: service_healthy
environment:
- HG_SERVER_BACKEND: hstore
- HG_SERVER_PD_PEERS: pd:8686
- HG_SERVER_CLUSTER: hg
- HG_SERVER_USE_PD: "true"
- HG_SERVER_REST_URL: http://server:8080
- HG_SERVER_MIN_FREE_MEMORY: "0"
- HG_SERVER_INIT_STORE_ENABLED: "false"
+ PASSWORD: ${HUGEGRAPH_ADMIN_PASSWORD:-}
HG_SERVER_AUTH_TOKEN_SECRET: ${HUGEGRAPH_AUTH_TOKEN_SECRET:-}
- PASSWORD: ${HUGEGRAPH_ADMIN_PASSWORD:?Set a non-default admin password}
+ HG_SERVER_MIN_FREE_MEMORY: "0"
ports:
- "8080:8080"
+ volumes:
+ - server-data:/hugegraph-server/rocksdb-data
healthcheck:
- test: ["CMD-SHELL", "curl -fsS http://server:8080/versions >/dev/null ||
exit 1"]
+ test: ["CMD-SHELL", "curl -fsS http://localhost:8080/versions
>/dev/null"]
interval: 10s
timeout: 5s
retries: 30
start_period: 60s
hubble:
- image: ${HUBBLE_IMAGE:-hugegraph/hubble:${HUGEGRAPH_VERSION:-latest}}
- pull_policy: ${HUBBLE_PULL_POLICY:-always}
- container_name: hg-hubble
- hostname: hubble
+ image: ${HUBBLE_IMAGE:-hugegraph/hubble:latest}
+ pull_policy: ${HUBBLE_PULL_POLICY:-missing}
restart: unless-stopped
networks: [hg-net]
depends_on:
server:
condition: service_healthy
+ environment:
+ SPRING_DATASOURCE_URL:
jdbc:h2:file:/hubble/data/hubble;DB_CLOSE_ON_EXIT=FALSE
ports:
- "${HUBBLE_PUBLISH_HOST:-127.0.0.1}:8088:8088"
volumes:
- -
./hugegraph-hubble.properties:/hubble/conf/hugegraph-hubble.properties:ro
+ - hubble-data:/hubble/data
+ -
./conf/hubble/standalone.properties:/hubble/conf/hugegraph-hubble.properties:ro
healthcheck:
- test: ["CMD-SHELL", "body=$$(curl -fsS http://127.0.0.1:8088/about) &&
printf '%s' \"$$body\" | grep -q '\"status\":200' && printf '%s' \"$$body\" |
grep -q '\"name\":\"hugegraph-hubble\"'"]
+ test:
+ - CMD-SHELL
+ - >-
+ body=$$(curl -fsS http://localhost:8088/about) &&
+ printf '%s' "$$body" | grep -q '"status":200' &&
+ printf '%s' "$$body" | grep -q '"name":"hugegraph-hubble"'
Review Comment:
**Is the body capture plus double grep doing anything a one line pipeline
would not?**
This same 6 line block appears in all three Compose files. As far as I can
tell it collapses to:
```suggestion
test: ["CMD-SHELL", "curl -fsS http://localhost:8088/about | grep -q
'\"name\":\"hugegraph-hubble\"'"]
```
Gating looks equivalent: connection refused gives `grep` empty stdin and
exit 1, `curl -f` suppresses bodies on HTTP >= 400, and an error envelope has
no `"name"` field, so the same cases stay unhealthy. The `"status":200` grep is
belt and braces on a static info endpoint, and `test-compose.sh` already
asserts `.status == 200 and .data.name == "hugegraph-hubble"` against the live
endpoint during smoke, so that check is not lost.
Both versions need only `curl` and `grep`, and the one liner is 108 chars,
inside the `.editorconfig` 120 limit. Coupled edit: drop the
`contains("\"status\":200")` line from `assert_hubble`, otherwise `render`
fails. Applies identically at `docker-compose-hstore.yml:122-127` and
`docker-compose-3pd-3store-3server.yml:247-252`.
##########
docker/docker-compose-3pd-3store-3server.yml:
##########
@@ -58,6 +59,18 @@ x-store-common: &store-common
retries: 40
start_period: 120s
+x-server-environment: &server-environment
+ STORE_REST: store0:8520
+ HG_SERVER_BACKEND: hstore
+ HG_SERVER_PD_PEERS: pd0:8686,pd1:8686,pd2:8686
+ HG_SERVER_CLUSTER: hg
+ HG_SERVER_USE_PD: "true"
+ HG_SERVER_MIN_FREE_MEMORY: "0"
+ HG_SERVER_INIT_STORE_ENABLED: "false"
+ HG_SERVER_REQUIRE_AUTH_TOKEN_SECRET: "true"
+ HG_SERVER_AUTH_TOKEN_SECRET: ${HUGEGRAPH_AUTH_TOKEN_SECRET:-}
+ PASSWORD: ${HUGEGRAPH_ADMIN_PASSWORD:-}
Review Comment:
**Follow-up thought, not a request against this PR:** `pd0/1/2` and
`store0/1/2` further down could reuse this exact anchor pattern. They are
untouched by this diff, so this belongs in a separate issue if you think it is
worth doing at all.
Each `pd` repeats the same 6 env vars with only `HG_PD_GRPC_HOST` and
`HG_PD_RAFT_ADDRESS` differing, and each `store` repeats 4 with the same two
exceptions. An `x-pd-environment` and `x-store-environment` pair nets about 10
lines, 13 if the redundant `networks: [ hg-net ]` at lines 100, 118 and 136 go
too, since `x-pd-common` already provides them. I applied it to a copy:
`.services`, `.networks`, `.volumes` and `.name` hash identical, and
`test-compose.sh render` still passes.
##########
docker/README.md:
##########
@@ -1,436 +1,362 @@
-# HugeGraph Docker Deployment
+# HugeGraph Docker Compose
-This directory contains Docker Compose files for running HugeGraph:
+## Users
-| File | Description |
-|------|-------------|
-| `docker-compose.yml` | PD, Store, Server, and Hubble using pre-built images |
-| `docker-compose.dev.yml` | PD, Store, and Server built from source, plus
Hubble |
-| `docker-compose-3pd-3store-3server.yml` | 3-node distributed cluster (PD +
Store + Server) |
+### Choose a topology
-## Prerequisites
+Run commands in this directory:
-- **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.
+```bash
+cd docker
+```
-> [!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.
----
+| Topology | Compose file | Services | When to use it |
+| --- | --- | --- | --- |
+| Standalone | `docker-compose.yml` | 1 RocksDB Server + 1 Hubble | Default;
start here |
+| Minimal HStore | `docker-compose-hstore.yml` | 1 PD + 1 Store + 1 Server + 1
Hubble | Distributed local development |
+| HA | `docker-compose-3pd-3store-3server.yml` | 3 PD + 3 Store + 3 Server + 1
Hubble | Reference and evaluation |
-## Single-Node Setup
+Standalone uses `hugegraph/hugegraph:${HUGEGRAPH_VERSION:-latest}`. The HStore
+topologies use the matching `hugegraph/pd`, `hugegraph/store`, and
+`hugegraph/server` tags. Hubble is selected independently with
+`${HUBBLE_IMAGE:-hugegraph/hubble:latest}`.
-Two compose files run one PD, one Store, one Server, and one Hubble instance:
+### Create the authentication environment
-Create a Compose environment file once so every lifecycle command can resolve
the required administrator password:
+Create `.env` once. Replace `replace-with-your-password` with an administrator
+password that you choose; the command generates and persists a random 32-byte
+JWT secret. For this simple single-quoted format, do not use a password that
+contains a single quote or newline.
```bash
(
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
+ command -v openssl >/dev/null
+ jwt_secret="$(openssl rand -hex 32)"
+ test "${#jwt_secret}" -eq 64
Review Comment:
**Are lines 34 and 36 doing anything under `set -eu`?** Line 35 is the one
that matters.
- If `openssl` is missing or fails, `jwt_secret="$(openssl rand -hex 32)"`
already exits the subshell non-zero. I checked in bash, zsh, sh and dash with
`openssl` off `PATH`: exit 127, no `.env` written, and the shell prints a
command-not-found error, which is better diagnostics than the silent `set -e`
failure of the guard line.
- `openssl rand -hex 32` cannot exit 0 while printing anything other than 64
hex chars. An `openssl` old enough to lack `-hex` exits non-zero with empty
stdout, so the length test never runs on a bad value anyway.
The protections that matter are untouched: `umask 077` before the write, the
no-clobber guard, and the single quoted `printf`. The entrypoint's own `>= 32`
byte check at `docker-entrypoint.sh:95` still backstops the value.
Not a blocker, just two lines of ceremony in the one block every user copies.
##########
docker/test-compose.sh:
##########
@@ -0,0 +1,403 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -Eeuo pipefail
+
+DOCKER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+PASSWORD="ci-compose-password"
+SECRET="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
+VERSION="ci-version"
+RENDER_HUBBLE_IMAGE="example.invalid/hugegraph/hubble:ci"
+DATASOURCE="jdbc:h2:file:/hubble/data/hubble;DB_CLOSE_ON_EXIT=FALSE"
+CURL_TIMEOUTS=(--connect-timeout 5 --max-time 15)
+ACTIVE_PROJECT=""
+ACTIVE_FILES=()
+RENDER_DIR=""
+
+compose_auth() {
+ env HUGEGRAPH_VERSION="${VERSION}" \
+ HUBBLE_IMAGE="${RENDER_HUBBLE_IMAGE}" \
+ HUGEGRAPH_ADMIN_PASSWORD="${PASSWORD}" \
+ HUGEGRAPH_AUTH_TOKEN_SECRET="${SECRET}" \
+ docker compose "$@"
+}
+
+render() {
+ local output="$1"
+ shift
+ compose_auth "$@" config --format json > "${output}"
+}
+
+assert_file_property() {
+ local file="$1"
+ local property="$2"
+ grep -Fqx "${property}" "${file}"
+}
+
+assert_common() {
+ local rendered="$1"
+ local services="$2"
+ local volumes="$3"
+
+ jq -e \
+ --arg password "${PASSWORD}" \
+ --arg secret "${SECRET}" \
Review Comment:
**A correction I owe you here, rather than a request.**
I came in expecting to argue that most of these jq contracts are change
detectors that the smoke stage already proves behaviourally. I mutation-tested
that and it does not hold, so recording the result instead:
- Deleting the inner `<<: *server-environment` from `server0` collapses its
env to just `HG_SERVER_REST_URL`, silently dropping `PASSWORD` and the JWT
secret. Only `assert_common`'s per-`server*` assertion catches it, and HA is
never smoked.
- Hardcoding `image: hugegraph/server:latest` in the hstore file passes
smoke, because CI resolves `${HUGEGRAPH_VERSION:-latest}` to `latest` anyway.
So `VERSION="ci-version"` and `RENDER_HUBBLE_IMAGE` are the only proof that
interpolation still reaches each image field.
- Typing `server:` as `sever:` in the dev overlay still passes `config -q`
on the pair: the real service reverts to the base image while an orphan `sever`
gets `:dev`. Only `assert_dev_override` notices.
- Changing `pd.peers=pd:8686` to `pd:9999` passes a hostname derived check,
so the literal `assert_file_property` greps earn their keep on the port
dimension.
So no change requested here. The only part my redundancy argument survives
for is roughly 20 lines of assertion the smoke stage re-proves each run on the
two smoked topologies, and since `assert_common` is shared with HA and the dev
overlay, carving those out would mean splitting the helper, which adds code.
Not worth it.
One related note: `smoke-auth-off` looks worth keeping. It never runs in CI
so it reads like dead code at first, but the README documents it as a required
local check with a stated trust boundary reason, and it is the only
verification of the entrypoint's non-auth fork.
##########
docker/README.md:
##########
@@ -1,436 +1,362 @@
-# HugeGraph Docker Deployment
+# HugeGraph Docker Compose
-This directory contains Docker Compose files for running HugeGraph:
+## Users
-| File | Description |
-|------|-------------|
-| `docker-compose.yml` | PD, Store, Server, and Hubble using pre-built images |
-| `docker-compose.dev.yml` | PD, Store, and Server built from source, plus
Hubble |
-| `docker-compose-3pd-3store-3server.yml` | 3-node distributed cluster (PD +
Store + Server) |
+### Choose a topology
-## Prerequisites
+Run commands in this directory:
-- **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.
+```bash
+cd docker
+```
-> [!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.
----
+| Topology | Compose file | Services | When to use it |
+| --- | --- | --- | --- |
+| Standalone | `docker-compose.yml` | 1 RocksDB Server + 1 Hubble | Default;
start here |
+| Minimal HStore | `docker-compose-hstore.yml` | 1 PD + 1 Store + 1 Server + 1
Hubble | Distributed local development |
+| HA | `docker-compose-3pd-3store-3server.yml` | 3 PD + 3 Store + 3 Server + 1
Hubble | Reference and evaluation |
-## Single-Node Setup
+Standalone uses `hugegraph/hugegraph:${HUGEGRAPH_VERSION:-latest}`. The HStore
+topologies use the matching `hugegraph/pd`, `hugegraph/store`, and
+`hugegraph/server` tags. Hubble is selected independently with
+`${HUBBLE_IMAGE:-hugegraph/hubble:latest}`.
-Two compose files run one PD, one Store, one Server, and one Hubble instance:
+### Create the authentication environment
-Create a Compose environment file once so every lifecycle command can resolve
the required administrator password:
+Create `.env` once. Replace `replace-with-your-password` with an administrator
+password that you choose; the command generates and persists a random 32-byte
+JWT secret. For this simple single-quoted format, do not use a password that
+contains a single quote or newline.
```bash
(
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
+ command -v openssl >/dev/null
+ jwt_secret="$(openssl rand -hex 32)"
+ test "${#jwt_secret}" -eq 64
+ umask 077
+ test ! -e .env || {
+ echo ".env already exists; edit it instead of overwriting it" >&2
exit 1
- fi
+ }
+ printf "HUGEGRAPH_ADMIN_PASSWORD='%s'\nHUGEGRAPH_AUTH_TOKEN_SECRET='%s'\n" \
+ 'replace-with-your-password' "${jwt_secret}" > .env
)
```
-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.
+Do not commit `.env`. Keeping the same JWT secret preserves authentication
+tokens when containers are recreated. For authenticated topologies with
+multiple Server replicas, all replicas receive this same secret. The HA
+topology fails fast if authentication is enabled without this shared secret.
-### Option A: Quick Start (pre-built images)
+A non-empty `HUGEGRAPH_ADMIN_PASSWORD` enables Server authentication, and
+Hubble detects that mode automatically. Omitting the variable or setting it to
+an empty value disables authentication. Auth-off is only suitable for a
+trusted local environment; never expose it to a public or untrusted network.
+Hubble listens on host loopback by default. Set `HUBBLE_PUBLISH_HOST` only
+behind an HTTPS reverse proxy and trusted network controls.
-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.
+`HUGEGRAPH_ADMIN_PASSWORD` initializes the built-in `admin` account on its
+first authenticated startup. Changing `.env` does not rotate an existing
+administrator password; use the HugeGraph user API for credential changes.
+
+For the verification commands below, set the password in your current shell:
```bash
-(
- cd docker
- HUGEGRAPH_VERSION='<compatible-release-after-1.7.x>' \
- docker compose up -d
-)
+ADMIN_PASSWORD='the-same-password-used-in-.env'
```
-- 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`
+### Standalone
-### Option B: Development Build (build from source)
+This is the recommended quickstart.
-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.
+Start:
-The publishing pipeline uses [`docker/bake.hcl`](./bake.hcl) from the
repository root to compile the Java reactor once and build the PD, Store,
HStore Server, and standalone Server runtime images from that shared result.
+```bash
+docker compose -f docker-compose.yml up -d --wait
+```
-Run Bake commands from the repository root. Use `--print` to inspect the
resolved targets without building, or run the default group to build all four
amd64/arm64 images. Loading both platforms under the same local tags requires
Docker's containerd image store.
+Status:
```bash
-# Inspect the resolved build graph
-docker buildx bake --file docker/bake.hcl --print
+docker compose -f docker-compose.yml ps
+```
+
+Verify Server readiness, authentication, and Hubble:
-# Build the default multi-platform target group
-IMAGE_TAG=local docker buildx bake --file docker/bake.hcl
+```bash
+curl -fsS http://localhost:8080/versions
+test "$(curl -sS -o /dev/null -w '%{http_code}' \
+ http://localhost:8080/graphspaces/DEFAULT/graphs)" = 401
+test "$(curl -sS -u "admin:${ADMIN_PASSWORD}" -o /dev/null -w '%{http_code}' \
+ http://localhost:8080/graphspaces/DEFAULT/graphs)" = 200
+curl -fsS http://localhost:8088/about
```
-Local source changes are included because Bake uses the current repository
working tree as its build context. For routine development, override all
targets to the host architecture so the four images still share one Maven build
without requiring the multi-platform containerd image store.
+Open `http://localhost:8088` and sign in as `admin` with the password from
+`.env`.
+
+Stop containers while keeping them:
```bash
-# x86_64 host
-IMAGE_TAG=local docker buildx bake --file docker/bake.hcl --set
'*.platform=linux/amd64'
+docker compose -f docker-compose.yml stop
+```
-# ARM64 host
-IMAGE_TAG=local docker buildx bake --file docker/bake.hcl --set
'*.platform=linux/arm64'
+Remove containers and the network while keeping data:
+
+```bash
+docker compose -f docker-compose.yml down
```
-These local commands can read existing Registry caches but do not publish
images or write remote caches because `EXPORT_CACHE` defaults to `false`.
+Delete containers, the network, and all topology data:
```bash
-(
- cd docker
- HUBBLE_IMAGE=local/hugegraph-hubble:dev \
- HUBBLE_PULL_POLICY=never \
- docker compose -f docker-compose.dev.yml up -d
-)
+docker compose -f docker-compose.yml down -v
```
-- 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
+### Minimal HStore
-Use the same release tag for Option A lifecycle commands:
+Start:
```bash
-(
- cd docker
- export HUGEGRAPH_VERSION='<same-compatible-release>'
- docker compose ps
- docker compose stop
- docker compose down
-)
+docker compose -f docker-compose-hstore.yml up -d --wait
```
-Use the development Compose file for every Option B lifecycle command:
+Status:
```bash
-(
- 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
-)
+docker compose -f docker-compose-hstore.yml ps
```
-### Key Differences
-
-| | `docker-compose.yml` (quickstart) | `docker-compose.dev.yml` (dev build) |
-|---|---|---|
-| **Images** | Pull from Docker Hub | Build from source |
-| **Who it's for** | End users | Developers |
-| **Server pull_policy** | `always` | `build` |
-| **Hubble pull_policy** | `always` | `never` in the workflow above (`missing`
in the Compose file by default) |
+Verify PD, Store, Server authentication, and Hubble:
-**Verify** (both options):
```bash
-curl http://localhost:8080/versions
+curl -fsS http://localhost:8620/v1/health
+curl -fsS http://localhost:8520/v1/health
+curl -fsS http://localhost:8080/versions
+test "$(curl -sS -o /dev/null -w '%{http_code}' \
+ http://localhost:8080/graphspaces/DEFAULT/graphs)" = 401
+test "$(curl -sS -u "admin:${ADMIN_PASSWORD}" -o /dev/null -w '%{http_code}' \
+ http://localhost:8080/graphspaces/DEFAULT/graphs)" = 200
curl -fsS http://localhost:8088/about
```
-To validate local images without Compose replacing them with remote `latest`:
+Open `http://localhost:8088` and sign in as `admin` with the password from
+`.env`.
+
+Stop containers while keeping them:
```bash
-(
- 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
-)
+docker compose -f docker-compose-hstore.yml stop
```
----
+Remove containers and the network while keeping data:
+
+```bash
+docker compose -f docker-compose-hstore.yml down
+```
-## 3-Node Cluster Quickstart
+Delete containers, the network, and all topology data:
```bash
-cd docker
-HUGEGRAPH_VERSION=1.7.0 docker compose -f
docker-compose-3pd-3store-3server.yml up -d
+docker compose -f docker-compose-hstore.yml down -v
+```
-# To stop and remove all data volumes (clean restart)
-docker compose -f docker-compose-3pd-3store-3server.yml down -v
+### HA reference
+
+The HA topology is resource-intensive. Running it locally is not required on
+resource-constrained machines, but its Compose configuration must always render
+successfully. This PR validates HA by rendering and static review only; it does
+not start HA locally or in default CI.
+
+Start:
+
+```bash
+docker compose -f docker-compose-3pd-3store-3server.yml up -d --wait
```
-**Startup ordering** is enforced via `depends_on` with `condition:
service_healthy`:
+Status:
-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
+```bash
+docker compose -f docker-compose-3pd-3store-3server.yml ps
+```
-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 all published PD, Store, and Server endpoints, Server authentication,
+and Hubble:
+
+```bash
+for port in 8620 8621 8622; do
+ curl -fsS "http://localhost:${port}/v1/health"
+done
+for port in 8520 8521 8522; do
+ curl -fsS "http://localhost:${port}/v1/health"
+done
+for port in 8080 8081 8082; do
+ curl -fsS "http://localhost:${port}/versions"
+ test "$(curl -sS -o /dev/null -w '%{http_code}' \
+ "http://localhost:${port}/graphspaces/DEFAULT/graphs")" = 401
+ test "$(curl -sS -u "admin:${ADMIN_PASSWORD}" -o /dev/null \
+ -w '%{http_code}' \
+ "http://localhost:${port}/graphspaces/DEFAULT/graphs")" = 200
+done
+curl -fsS http://localhost:8088/about
+```
-**Verify the cluster is healthy**:
+Open `http://localhost:8088` and sign in as `admin` with the password from
+`.env`.
+
+Stop containers while keeping them:
```bash
-# Check PD health
-curl http://localhost:8620/v1/health
+docker compose -f docker-compose-3pd-3store-3server.yml stop
+```
-# Check Store health
-curl http://localhost:8520/v1/health
+Remove containers and the network while keeping data:
-# Check Server (Graph API)
-curl http://localhost:8080/versions
+```bash
+docker compose -f docker-compose-3pd-3store-3server.yml down
+```
-# List registered stores via PD
-curl http://localhost:8620/v1/stores
+Delete containers, the network, and all topology data:
-# List partitions
-curl http://localhost:8620/v1/partitions
+```bash
+docker compose -f docker-compose-3pd-3store-3server.yml down -v
```
----
-
-## 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
-
-| Variable | Required | Default | Maps To (`application.yml`) | Description |
-|----------|----------|---------|-----------------------------|-------------|
-| `HG_PD_GRPC_HOST` | Yes | — | `grpc.host` | This node's hostname/IP for gRPC
|
-| `HG_PD_RAFT_ADDRESS` | Yes | — | `raft.address` | This node's Raft address
(e.g. `pd0:8610`) |
-| `HG_PD_RAFT_PEERS_LIST` | Yes | — | `raft.peers-list` | All PD peers (e.g.
`pd0:8610,pd1:8610,pd2:8610`) |
-| `HG_PD_INITIAL_STORE_LIST` | Yes | — | `pd.initial-store-list` | Expected
stores (e.g. `store0:8500,store1:8500,store2:8500`) |
-| `HG_PD_GRPC_PORT` | No | `8686` | `grpc.port` | gRPC server port |
-| `HG_PD_REST_PORT` | No | `8620` | `server.port` | REST API port |
-| `HG_PD_DATA_PATH` | No | `/hugegraph-pd/pd_data` | `pd.data-path` | Metadata
storage path |
-| `HG_PD_INITIAL_STORE_COUNT` | No | `1` | `pd.initial-store-count` | Min
stores for cluster availability |
-
-**Deprecated aliases** (still work but log a warning):
-
-| Deprecated | Use Instead |
-|------------|-------------|
-| `GRPC_HOST` | `HG_PD_GRPC_HOST` |
-| `RAFT_ADDRESS` | `HG_PD_RAFT_ADDRESS` |
-| `RAFT_PEERS` | `HG_PD_RAFT_PEERS_LIST` |
-| `PD_INITIAL_STORE_LIST` | `HG_PD_INITIAL_STORE_LIST` |
-
-### Store Environment Variables
-
-| Variable | Required | Default | Maps To (`application.yml`) | Description |
-|----------|----------|---------|-----------------------------|-------------|
-| `HG_STORE_PD_ADDRESS` | Yes | — | `pdserver.address` | PD gRPC addresses
(e.g. `pd0:8686,pd1:8686,pd2:8686`) |
-| `HG_STORE_GRPC_HOST` | Yes | — | `grpc.host` | This node's hostname (e.g.
`store0`) |
-| `HG_STORE_RAFT_ADDRESS` | Yes | — | `raft.address` | This node's Raft
address (e.g. `store0:8510`) |
-| `HG_STORE_GRPC_PORT` | No | `8500` | `grpc.port` | gRPC server port |
-| `HG_STORE_REST_PORT` | No | `8520` | `server.port` | REST API port |
-| `HG_STORE_DATA_PATH` | No | `/hugegraph-store/storage` | `app.data-path` |
Data storage path |
-
-**Deprecated aliases** (still work but log a warning):
-
-| Deprecated | Use Instead |
-|------------|-------------|
-| `PD_ADDRESS` | `HG_STORE_PD_ADDRESS` |
-| `GRPC_HOST` | `HG_STORE_GRPC_HOST` |
-| `RAFT_ADDRESS` | `HG_STORE_RAFT_ADDRESS` |
-
-### Server Environment Variables
-
-| Variable | Required | Default | Maps To | Description |
-|----------|----------|---------|-----------------------------|-------------|
-| `HG_SERVER_BACKEND` | Yes | — | `backend` in `hugegraph.properties` |
Storage backend (e.g. `hstore`) |
-| `HG_SERVER_PD_PEERS` | Yes | — | `pd.peers` | PD cluster addresses (e.g.
`pd0:8686,pd1:8686,pd2:8686`) |
-| `HG_SERVER_CLUSTER` | No | — | `cluster` in `rest-server.properties` | PD
discovery application name; single-node Compose uses `hg` to match Hubble |
-| `HG_SERVER_USE_PD` | No | — | `usePD` in `rest-server.properties` | Enables
Server PD registration and discovery |
-| `HG_SERVER_REST_URL` | No | — | `restserver.url` | Address registered with
PD and used by clients |
-| `HG_SERVER_MIN_FREE_MEMORY` | No | — | `restserver.min_free_memory` |
Minimum free-memory guard in MB; local Compose uses `0` |
-| `HG_SERVER_AUTH_TOKEN_SECRET` | No | generated in auth mode |
`auth.token_secret` | Shared JWT secret for REST and embedded Gremlin
authentication; explicit values must be at least 32 bytes |
-| `STORE_REST` | No | — | Used by `wait-partition.sh` | Store REST endpoint
for partition verification (e.g. `store0:8520`) |
-| `PASSWORD` | No | — | Enables auth and sets `auth.admin_pa` | Initial
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_ENABLED` | No | `true` | `init_store.enabled` in
`rest-server.properties` | Set `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:
-
-| Variable | Default | Description |
-|----------|---------|-------------|
-| `HUGEGRAPH_SERVER_IMAGE` | `hugegraph/server:<version>` | Complete Server
image reference |
-| `HUGEGRAPH_SERVER_PULL_POLICY` | `always` (`build` for dev) | Server pull
policy |
-| `HUBBLE_IMAGE` | `hugegraph/hubble:<version>` | Complete Hubble image
reference |
-| `HUBBLE_PULL_POLICY` | `always` (`missing` for dev) | Hubble pull policy |
-| `HUBBLE_PUBLISH_HOST` | `127.0.0.1` | Hubble host bind address; remote
access requires an HTTPS reverse proxy |
-| `HUGEGRAPH_ADMIN_PASSWORD` | required (`docker/.env`) | Initial admin
password; no public default is provided |
-| `HUGEGRAPH_AUTH_TOKEN_SECRET` | generated | JWT 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`:
+### Select image versions
+
+Set a HugeGraph release for Server, PD, and Store without changing Hubble:
```bash
-(
- 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
-)
+HUGEGRAPH_VERSION=1.7.0 \
+docker compose -f docker-compose-hstore.yml up -d
+```
+
+Select Hubble independently:
+
+```bash
+HUBBLE_IMAGE=hugegraph/hubble:latest \
+docker compose -f docker-compose.yml up -d
```
-The entrypoint rejects shorter explicit values before changing either Server
configuration file.
+The Hubble `latest` image is expected to work with HugeGraph Server 1.7 and
+Server `latest`; compatibility with versions older than 1.7 is not promised.
+Pin immutable image references when reproducibility is required.
-**Deprecated aliases** (still work but log a warning):
+### Data persistence
-| Deprecated | Use Instead |
-|------------|-------------|
-| `BACKEND` | `HG_SERVER_BACKEND` |
-| `PD_PEERS` | `HG_SERVER_PD_PEERS` |
+Each topology creates its own normal Compose network and named volumes. No
+network or volume needs to be created in advance.
----
+Standalone stores RocksDB data at `/hugegraph-server/rocksdb-data`. The HStore
+topologies keep PD and Store data in topology-local volumes. Hubble uses
+`jdbc:h2:file:/hubble/data/hubble;DB_CLOSE_ON_EXIT=FALSE` and stores uploaded
+files under `/hubble/data/upload-files`.
-## Port Reference
+`docker compose down` keeps named-volume data. `docker compose down -v`
+intentionally deletes it.
-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.
+## Developers
-| Service | Container Port | Host Port | Protocol | Purpose |
-|---------|---------------|-----------|----------|---------|
-| pd0 | 8620 | 8620 | HTTP | REST API |
-| pd0 | 8686 | 8686 | gRPC | PD gRPC |
-| pd0 | 8610 | — | TCP | Raft (internal only) |
-| pd1 | 8620 | 8621 | HTTP | REST API |
-| pd1 | 8686 | 8687 | gRPC | PD gRPC |
-| pd2 | 8620 | 8622 | HTTP | REST API |
-| pd2 | 8686 | 8688 | gRPC | PD gRPC |
-| store0 | 8500 | 8500 | gRPC | Store gRPC |
-| store0 | 8510 | 8510 | TCP | Raft |
-| store0 | 8520 | 8520 | HTTP | REST API |
-| store1 | 8500 | 8501 | gRPC | Store gRPC |
-| store1 | 8510 | 8511 | TCP | Raft |
-| store1 | 8520 | 8521 | HTTP | REST API |
-| store2 | 8500 | 8502 | gRPC | Store gRPC |
-| store2 | 8510 | 8512 | TCP | Raft |
-| store2 | 8520 | 8522 | HTTP | REST API |
-| server0 | 8080 | 8080 | HTTP | Graph API |
-| server1 | 8080 | 8081 | HTTP | Graph API |
-| server2 | 8080 | 8082 | HTTP | Graph API |
+### Images and Compose files
----
+| Image | Build file |
+| --- | --- |
+| `hugegraph/hugegraph` (standalone RocksDB Server) |
`hugegraph-server/Dockerfile` |
+| `hugegraph/server` (HStore Server) | `hugegraph-server/Dockerfile-hstore` |
+| `hugegraph/pd` | `hugegraph-pd/Dockerfile` |
+| `hugegraph/store` | `hugegraph-store/Dockerfile` |
-## Healthcheck Endpoints
+Hubble is built from the separate HugeGraph Toolchain repository and is
+selected here with `HUBBLE_IMAGE`.
-| Service | Endpoint | Expected |
-|---------|----------|----------|
-| PD | `GET /v1/health` | `200 OK` |
-| Store | `GET /v1/health` | `200 OK` |
-| Server | `GET /versions` | `200 OK` with version JSON |
-| Hubble | `GET /about` | `200` JSON with Hubble name and version |
+The Compose mapping is intentionally small:
----
+- `docker-compose.yml` is the standalone user default.
+- `docker-compose-hstore.yml` is the minimal 1 PD + 1 Store + 1 Server base.
+- `docker-compose-3pd-3store-3server.yml` is the HA reference.
+- `docker-compose.dev.yml` is a thin source-build override for the minimal
+ HStore topology. It does not duplicate runtime services, networks, volumes,
+ health checks, or Hubble.
-## Troubleshooting
+Build and start the minimal topology from local source:
-### Containers Exiting or Restarting (OOM Kills)
+```bash
+docker compose \
+ -f docker-compose-hstore.yml \
+ -f docker-compose.dev.yml \
+ up -d --build --wait
+```
-**Symptom**: Containers exit with code 137, or restart loops. Raft logs show
election timeouts.
+Use both files for every later lifecycle command, for example:
-**Cause**: Docker Desktop does not have enough memory. The 9 JVM processes
require at least 12 GB.
+```bash
+docker compose \
+ -f docker-compose-hstore.yml \
+ -f docker-compose.dev.yml \
+ down
+```
-**Fix**: Docker Desktop → Settings → Resources → Memory → set to **12 GB** or
higher. Restart Docker Desktop.
+The development overlay builds `hugegraph/pd:dev`, `hugegraph/store:dev`, and
+`hugegraph/server:dev`. To reuse those local images and a locally built Hubble
+without pulling replacements:
```bash
-# Check if containers were OOM killed
-docker inspect hg-pd0 | grep -i oom
-docker stats --no-stream
+HUGEGRAPH_VERSION=dev \
+HUGEGRAPH_PULL_POLICY=never \
+HUBBLE_IMAGE=local/hugegraph-hubble:test \
+HUBBLE_PULL_POLICY=never \
+docker compose -f docker-compose-hstore.yml up -d --wait
```
-### Raft Leader Election Failure
+### Hubble configuration
+
+The three small files under `conf/hubble/` contain only topology-specific
+discovery settings and container paths:
-**Symptom**: PD logs show repeated `Leader election timeout`. Store nodes
cannot register.
+- `conf/hubble/standalone.properties` uses direct Server mode.
+- `conf/hubble/hstore.properties` uses one PD and one Store REST target.
+- `conf/hubble/hstore-ha.properties` uses all three PD peers and all three
+ allowed Store REST targets.
-**Cause**: PD nodes cannot reach each other on the Raft port (8610), or
`HG_PD_RAFT_PEERS_LIST` is misconfigured.
+Hubble detects Server authentication through the Server API. Do not add an
+`auth.enabled` property or duplicate auth-on/auth-off configurations.
-**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
+### Render and smoke checks
-### Partition Assignment Not Completing
+Render every topology with auth-on inputs before submitting a change:
-**Symptom**: Server starts but graph operations fail. Store logs show
`partition not found`.
+```bash
+for file in \
+ docker-compose.yml \
+ docker-compose-hstore.yml \
+ docker-compose-3pd-3store-3server.yml
+do
+ docker compose -f "${file}" config --quiet
+done
+docker compose \
+ -f docker-compose-hstore.yml \
+ -f docker-compose.dev.yml \
+ config --quiet
Review Comment:
**Can this loop just be `bash test-compose.sh render`?**
`run_render` in the same PR renders these exact four file combinations, plus
the dev overlay on its own, with pinned auth-on env and the jq contracts on
top. It is a strict superset of this block, and it is what CI runs, so the two
cannot drift.
One thing I noticed while checking: in a clean checkout this loop does not
do what the lead-in says. Every Compose file uses `:-` empty defaults for
`HUGEGRAPH_ADMIN_PASSWORD` and `HUGEGRAPH_AUTH_TOKEN_SECRET`, so with no `.env`
present it exits 0 having rendered auth-off, despite "Render every topology
with auth-on inputs". With a user created `.env` it is auth-on. The script pins
its inputs through OS env, which takes precedence over `.env`, so it is
deterministic either way.
```suggestion
bash test-compose.sh render
```
`test-compose.sh smoke` a few lines below already needs `jq`, so this adds
no new dependency for anyone following this section. The three line description
of what smoke covers could shrink the same way.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]