diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml new file mode 100644 index 0000000000..77bcbfd53e --- /dev/null +++ b/docker/docker-compose.dev.yml @@ -0,0 +1,109 @@ +# +# 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-single + +networks: + hg-net: + driver: bridge + +volumes: + hg-pd-data: + hg-store-data: + +services: + pd: + build: + context: .. + dockerfile: hugegraph-pd/Dockerfile + image: hugegraph/pd:${HUGEGRAPH_VERSION:-latest} + 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: 20s + + store: + build: + context: .. + dockerfile: hugegraph-store/Dockerfile + image: hugegraph/store:${HUGEGRAPH_VERSION:-latest} + 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: 30s + + server: + build: + context: .. + dockerfile: hugegraph-server/Dockerfile-hstore + image: hugegraph/server:${HUGEGRAPH_VERSION:-latest} + container_name: hg-server + hostname: server + restart: unless-stopped + networks: [hg-net] + depends_on: + store: + condition: service_healthy + environment: + HG_SERVER_BACKEND: hstore + HG_SERVER_PD_PEERS: pd:8686 + ports: + - "8080:8080" + healthcheck: + test: ["CMD-SHELL", "curl -fsS http://localhost:8080/versions >/dev/null || exit 1"] + interval: 10s + timeout: 5s + retries: 30 + start_period: 60s diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 0c90c1e451..90a5dd5c74 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -15,44 +15,118 @@ # limitations under the License. # -version: "3" +name: hugegraph-single + +networks: + hg-net: + driver: bridge + +volumes: + hg-pd-data: + hg-store-data: services: + pd: - image: hugegraph/pd - container_name: pd + image: hugegraph/pd:${HUGEGRAPH_VERSION:-latest} + pull_policy: always + container_name: hg-pd hostname: pd - network_mode: host + restart: unless-stopped + networks: [hg-net] + + entrypoint: ["/hugegraph-pd/docker-entrypoint.sh"] + + 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 + - ../hugegraph-pd/hg-pd-dist/docker/docker-entrypoint.sh:/hugegraph-pd/docker-entrypoint.sh + healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8620"] + test: ["CMD-SHELL", "curl -fsS http://localhost:8620/ >/dev/null || exit 1"] interval: 10s timeout: 5s - retries: 3 + retries: 12 + start_period: 30s + store: - image: hugegraph/store - container_name: store + image: hugegraph/store:${HUGEGRAPH_VERSION:-latest} + pull_policy: always + container_name: hg-store hostname: store - network_mode: host + restart: unless-stopped + networks: [hg-net] + + entrypoint: ["/hugegraph-store/docker-entrypoint.sh"] + 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 + - ../hugegraph-store/hg-store-dist/docker/docker-entrypoint.sh:/hugegraph-store/docker-entrypoint.sh + healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8520"] + test: ["CMD-SHELL", "curl -fsS http://localhost:8520/v1/health >/dev/null || exit 1"] interval: 10s - timeout: 5s - retries: 3 + timeout: 10s + retries: 30 + start_period: 60s + server: - image: hugegraph/server - container_name: server + image: hugegraph/server:${HUGEGRAPH_VERSION:-latest} + pull_policy: always + container_name: hg-server hostname: server - network_mode: host + restart: unless-stopped + networks: [hg-net] + + entrypoint: ["/hugegraph-server/docker-entrypoint.sh"] + depends_on: store: condition: service_healthy + + environment: + HG_SERVER_BACKEND: hstore + HG_SERVER_PD_PEERS: pd:8686 + + ports: + - "8080:8080" + + volumes: + - ../hugegraph-server/hugegraph-dist/docker/docker-entrypoint.sh:/hugegraph-server/docker-entrypoint.sh + - ../hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-storage.sh:/hugegraph-server/bin/wait-storage.sh + - ../hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-partition.sh:/hugegraph-server/bin/wait-partition.sh + healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8080"] + test: ["CMD-SHELL", "curl -fsS http://localhost:8080/versions >/dev/null || exit 1"] interval: 10s timeout: 5s - retries: 3 + retries: 30 + start_period: 60s diff --git a/hugegraph-pd/hg-pd-dist/docker/docker-entrypoint.sh b/hugegraph-pd/hg-pd-dist/docker/docker-entrypoint.sh old mode 100644 new mode 100755 index fd894d5518..d1ae5c3c3a --- a/hugegraph-pd/hg-pd-dist/docker/docker-entrypoint.sh +++ b/hugegraph-pd/hg-pd-dist/docker/docker-entrypoint.sh @@ -15,8 +15,72 @@ # See the License for the specific language governing permissions and # limitations under the License. # +set -euo pipefail -# start hugegraph pd -./bin/start-hugegraph-pd.sh -j "$JAVA_OPTS" +log() { echo "[hugegraph-pd-entrypoint] $*"; } +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "ERROR: missing required env '${name}'" >&2; exit 2 + fi +} + +json_escape() { + local s="$1" + s=${s//\\/\\\\}; s=${s//\"/\\\"}; s=${s//$'\n'/} + printf "%s" "$s" +} + +migrate_env() { + local old_name="$1" new_name="$2" + + if [[ -n "${!old_name:-}" && -z "${!new_name:-}" ]]; then + log "WARN: deprecated env '${old_name}' detected; mapping to '${new_name}'" + export "${new_name}=${!old_name}" + fi +} + +migrate_env "GRPC_HOST" "HG_PD_GRPC_HOST" +migrate_env "RAFT_ADDRESS" "HG_PD_RAFT_ADDRESS" +migrate_env "RAFT_PEERS" "HG_PD_RAFT_PEERS_LIST" +migrate_env "PD_INITIAL_STORE_LIST" "HG_PD_INITIAL_STORE_LIST" + +# ── Required vars ───────────────────────────────────────────────────── +require_env "HG_PD_GRPC_HOST" +require_env "HG_PD_RAFT_ADDRESS" +require_env "HG_PD_RAFT_PEERS_LIST" +require_env "HG_PD_INITIAL_STORE_LIST" + +: "${HG_PD_GRPC_PORT:=8686}" +: "${HG_PD_REST_PORT:=8620}" +: "${HG_PD_DATA_PATH:=/hugegraph-pd/pd_data}" +: "${HG_PD_INITIAL_STORE_COUNT:=1}" + +SPRING_APPLICATION_JSON="$(cat <> "${file}" + fi +} + +migrate_env() { + local old_name="$1" new_name="$2" + + if [[ -n "${!old_name:-}" && -z "${!new_name:-}" ]]; then + log "WARN: deprecated env '${old_name}' detected; mapping to '${new_name}'" + export "${new_name}=${!old_name}" + fi +} + +migrate_env "BACKEND" "HG_SERVER_BACKEND" +migrate_env "PD_PEERS" "HG_SERVER_PD_PEERS" + +# ── Map env → properties file ───────────────────────────────────────── +[[ -n "${HG_SERVER_BACKEND:-}" ]] && set_prop "backend" "${HG_SERVER_BACKEND}" "${GRAPH_CONF}" +[[ -n "${HG_SERVER_PD_PEERS:-}" ]] && set_prop "pd.peers" "${HG_SERVER_PD_PEERS}" "${GRAPH_CONF}" + +# ── Build wait-storage env ───────────────────────────────────────────── +WAIT_ENV=() +[[ -n "${HG_SERVER_BACKEND:-}" ]] && WAIT_ENV+=("hugegraph.backend=${HG_SERVER_BACKEND}") +[[ -n "${HG_SERVER_PD_PEERS:-}" ]] && WAIT_ENV+=("hugegraph.pd.peers=${HG_SERVER_PD_PEERS}") + +# ── Init store (once) ───────────────────────────────────────────────── +if [[ ! -f "${DOCKER_FOLDER}/${INIT_FLAG_FILE}" ]]; then + if (( ${#WAIT_ENV[@]} > 0 )); then + env "${WAIT_ENV[@]}" ./bin/wait-storage.sh + else + ./bin/wait-storage.sh + fi + + if [[ -z "${PASSWORD:-}" ]]; then + log "init hugegraph with non-auth mode" ./bin/init-store.sh else - echo "init hugegraph with auth mode" + log "init hugegraph with auth mode" ./bin/enable-auth.sh - echo "$PASSWORD" | ./bin/init-store.sh + echo "${PASSWORD}" | ./bin/init-store.sh fi - # create a flag file to avoid re-init when restarting - touch ${DOCKER_FOLDER}/${INIT_FLAG_FILE} + touch "${DOCKER_FOLDER}/${INIT_FLAG_FILE}" else - echo "Hugegraph Initialization already done. Skipping re-init..." + log "HugeGraph initialization already done. Skipping re-init..." fi -# start hugegraph-server -# remove "-g zgc" now, which is only available on ARM-Mac with java > 13 -./bin/start-hugegraph.sh -j "$JAVA_OPTS" +./bin/start-hugegraph.sh -j "${JAVA_OPTS:-}" + +STORE_REST="${STORE_REST:-hg-store:8520}" +export STORE_REST + +# Post-startup cluster stabilization check +./bin/wait-partition.sh || log "WARN: partitions not assigned yet" tail -f /dev/null diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-partition.sh b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-partition.sh new file mode 100755 index 0000000000..d472a198cc --- /dev/null +++ b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-partition.sh @@ -0,0 +1,34 @@ +#!/bin/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 -euo pipefail + +: "${STORE_REST:?STORE_REST not set}" + +timeout "${WAIT_PARTITION_TIMEOUT_S:-60}s" bash -c ' +until curl -fsS "http://${STORE_REST}/v1/partitions" 2>/dev/null | \ + grep -q "\"partitionCount\":[1-9]" +do + echo "Waiting for partition assignment..." + sleep 5 +done +' + +echo "Partitions detected:" +URL="http://${STORE_REST}/v1/partitions" +echo "$URL" +curl -v "$URL" diff --git a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-storage.sh b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-storage.sh old mode 100644 new mode 100755 index 556e022478..d56c13ff8a --- a/hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-storage.sh +++ b/hugegraph-server/hugegraph-dist/src/assembly/static/bin/wait-storage.sh @@ -29,7 +29,7 @@ function abs_path() { BIN=$(abs_path) TOP="$(cd "$BIN"/../ && pwd)" GRAPH_CONF="$TOP/conf/graphs/hugegraph.properties" -WAIT_STORAGE_TIMEOUT_S=120 +WAIT_STORAGE_TIMEOUT_S=300 DETECT_STORAGE="$TOP/scripts/detect-storage.groovy" . "$BIN"/util.sh @@ -70,7 +70,34 @@ done < <(env | sort -r | awk -F= '{ st = index($0, "="); print $1 " " substr($0, # wait for storage if env | grep '^hugegraph\.' > /dev/null; then if [ -n "${WAIT_STORAGE_TIMEOUT_S:-}" ]; then - timeout "${WAIT_STORAGE_TIMEOUT_S}s" bash -c \ - "until bin/gremlin-console.sh -- -e $DETECT_STORAGE > /dev/null 2>&1; do echo \"Hugegraph server are waiting for storage backend...\"; sleep 5; done" + # Extract pd.peers from config or environment + PD_PEERS="${hugegraph_pd_peers:-}" + if [ -z "$PD_PEERS" ]; then + PD_PEERS=$(grep -E "^\s*pd\.peers\s*=" "$GRAPH_CONF" | sed 's/.*=\s*//' | tr -d ' ') + fi + + if [ -n "$PD_PEERS" ]; then + # Convert gRPC address to REST address (8686 -> 8620) + : "${HG_SERVER_PD_REST_ENDPOINT:=}" + + if [ -n "${HG_SERVER_PD_REST_ENDPOINT}" ]; then + PD_REST="${HG_SERVER_PD_REST_ENDPOINT}" + else + PD_REST=$(echo "$PD_PEERS" | sed 's/:8686/:8620/g' | cut -d',' -f1) + fi + echo "Waiting for PD REST endpoint at $PD_REST..." + + timeout "${WAIT_STORAGE_TIMEOUT_S}s" bash -c " + until curl -fsS http://${PD_REST}/v1/health >/dev/null 2>&1; do + echo 'Hugegraph server are waiting for storage backend...' + sleep 5 + done + echo 'PD is reachable, waiting extra 10s for store registration...' + sleep 10 + echo 'Storage backend is ready!' + " || echo "Warning: Timeout waiting for storage, proceeding anyway..." + else + echo "No pd.peers configured, skipping storage wait..." + fi fi fi diff --git a/hugegraph-store/hg-store-dist/docker/docker-entrypoint.sh b/hugegraph-store/hg-store-dist/docker/docker-entrypoint.sh old mode 100644 new mode 100755 index 5aa77621dc..1bdaaafc5a --- a/hugegraph-store/hg-store-dist/docker/docker-entrypoint.sh +++ b/hugegraph-store/hg-store-dist/docker/docker-entrypoint.sh @@ -15,8 +15,67 @@ # See the License for the specific language governing permissions and # limitations under the License. # +set -euo pipefail -# start hugegraph store -./bin/start-hugegraph-store.sh -j "$JAVA_OPTS" +log() { echo "[hugegraph-store-entrypoint] $*"; } +require_env() { + local name="$1" + if [[ -z "${!name:-}" ]]; then + echo "ERROR: missing required env '${name}'" >&2; exit 2 + fi +} + +json_escape() { + local s="$1" + s=${s//\\/\\\\}; s=${s//\"/\\\"}; s=${s//$'\n'/} + printf "%s" "$s" +} + +# ── Guard deprecated vars ───────────────────────────────────────────── +migrate_env() { + local old_name="$1" new_name="$2" + + if [[ -n "${!old_name:-}" && -z "${!new_name:-}" ]]; then + log "WARN: deprecated env '${old_name}' detected; mapping to '${new_name}'" + export "${new_name}=${!old_name}" + fi +} + +migrate_env "PD_ADDRESS" "HG_STORE_PD_ADDRESS" +migrate_env "GRPC_HOST" "HG_STORE_GRPC_HOST" +migrate_env "RAFT_ADDRESS" "HG_STORE_RAFT_ADDRESS" +# ── Required vars ───────────────────────────────────────────────────── +require_env "HG_STORE_PD_ADDRESS" +require_env "HG_STORE_GRPC_HOST" +require_env "HG_STORE_RAFT_ADDRESS" + +# ── Defaults ────────────────────────────────────────────────────────── +: "${HG_STORE_GRPC_PORT:=8500}" +: "${HG_STORE_REST_PORT:=8520}" +: "${HG_STORE_DATA_PATH:=/hugegraph-store/storage}" + +# ── Build SPRING_APPLICATION_JSON ───────────────────────────────────── +SPRING_APPLICATION_JSON="$(cat <