From ab1eeb7ddad1e8b7d503685128dc7d27ac843f65 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Thu, 27 Aug 2026 15:04:36 +0800 Subject: [PATCH 01/35] build(docker): align Dockerfiles with tron-docker - migrate amd64 and arm64 images to Ubuntu 24.04 - align JDK installation, package dependencies, and tcmalloc settings - use the canonical config source and restore image metadata labels - improve package cache cleanup and build reproducibility --- docker/Dockerfile | 89 +++++++++++++++++++++++++++-------------- docker/arm64/Dockerfile | 60 +++++++++++++++++---------- 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 2732f5a55ed..743c77bf54e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,44 +1,71 @@ -FROM tronprotocol/centos7:0.2 +FROM ubuntu:24.04 +ARG VERSION="dev" +ENV NO_PROXY_CACHE="-o Acquire::BrokenProxy=true -o Acquire::http::No-Cache=true -o Acquire::http::Pipeline-Depth=0" ENV TMP_DIR="/tron-build" -ENV JDK_TAR="jdk-8u202-linux-x64.tar.gz" -ENV JDK_DIR="jdk1.8.0_202" -ENV JDK_MD5="0029351f7a946f6c05b582100c7d45b7" +ENV OPENJDK8_URL="https://api.adoptium.net/v3/binary/latest/8/ga/linux/x64/jdk/hotspot/normal/eclipse" +ENV ADOPTIUM_SIGNING_FINGERPRINT="3B04D753C9050D9A5D343F39843C48A565F8F04B" +ENV JDK_DIR="/usr/local/openjdk-8" ENV BASE_DIR="/java-tron" - -RUN set -o errexit -o nounset \ - && yum -y install git wget \ - && wget -P /usr/local https://github.com/frekele/oracle-java/releases/download/8u202-b08/$JDK_TAR \ - && echo "$JDK_MD5 /usr/local/$JDK_TAR" | md5sum -c \ - && tar -zxf /usr/local/$JDK_TAR -C /usr/local\ - && rm /usr/local/$JDK_TAR \ - && export JAVA_HOME=/usr/local/$JDK_DIR \ - && export CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar \ - && export PATH=$PATH:$JAVA_HOME/bin \ - && echo "git clone" \ - && mkdir -p $TMP_DIR \ - && cd $TMP_DIR \ - && git clone https://github.com/tronprotocol/java-tron.git \ - && cd java-tron \ - && git checkout master \ - && ./gradlew build -x test \ - && cd build/distributions \ - && 7za x -y java-tron-1.0.0.zip \ - && mv java-tron-1.0.0 $BASE_DIR \ - && rm -rf $TMP_DIR \ - && rm -rf ~/.gradle \ - && mv $JAVA_HOME/jre /usr/local \ - && rm -rf $JAVA_HOME \ - && yum clean all - -RUN wget -P $BASE_DIR/config https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf +# Update and install dependencies without using any cache +RUN apt-get update $NO_PROXY_CACHE && \ + apt-get --quiet --yes install git wget 7zip curl jq libtcmalloc-minimal4 gnupg dirmngr ca-certificates && \ + cd /usr/local \ + && FETCH_URL="$(curl -fsS -w "%{redirect_url}" -o /dev/null "$OPENJDK8_URL")" \ + && JDK_TAR="$(curl -fsSL -w "%{filename_effective}" -O "$FETCH_URL")" \ + && curl -fsSLo "$JDK_TAR.sig" "$FETCH_URL.sig" \ + && GNUPGHOME="$(mktemp -d)" \ + && export GNUPGHOME \ + && gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys "$ADOPTIUM_SIGNING_FINGERPRINT" \ + && gpg --batch --verify "$JDK_TAR.sig" "$JDK_TAR" \ + && rm -rf "$GNUPGHOME" "$JDK_TAR.sig" \ + && mkdir -p "$JDK_DIR" \ + && tar -zxf "$JDK_TAR" -C "$JDK_DIR" --strip-components=1 \ + && rm "$JDK_TAR" \ + && export JAVA_HOME=$JDK_DIR \ + && export CLASSPATH=$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar \ + && export PATH=$PATH:$JAVA_HOME/bin \ + && echo "git clone" \ + && mkdir -p $TMP_DIR \ + && cd $TMP_DIR \ + && git clone https://github.com/tronprotocol/java-tron.git \ + && cd java-tron \ + && git checkout master \ + && ./gradlew clean build -x test -x check --no-daemon \ + && cd build/distributions \ + && 7z x -y java-tron-1.0.0.zip \ + && mv java-tron-1.0.0 $BASE_DIR \ + && rm -rf $TMP_DIR \ + && rm -rf ~/.gradle \ + && mv $JDK_DIR/jre /usr/local \ + && rm -rf $JDK_DIR \ + && wget -O $BASE_DIR/config.conf https://raw.githubusercontent.com/tronprotocol/java-tron/master/framework/src/main/resources/config.conf \ + # Clean apt cache + && apt-get clean \ + && rm -rf /var/cache/apt/archives/* /var/cache/apt/archives/partial/* \ + && rm -rf /var/lib/apt/lists/* ENV JAVA_HOME="/usr/local/jre" ENV PATH=$PATH:$JAVA_HOME/bin +ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4" +ENV TCMALLOC_RELEASE_RATE=10 COPY docker-entrypoint.sh $BASE_DIR/bin WORKDIR $BASE_DIR ENTRYPOINT ["./bin/docker-entrypoint.sh"] + +# Build-time metadata as defined at http://label-schema.org +ARG BUILD_DATE +ARG VCS_REF +LABEL org.label-schema.build-date=$BUILD_DATE \ + org.label-schema.name="Java-TRON" \ + org.label-schema.description="TRON protocol" \ + org.label-schema.url="https://tron.network/" \ + org.label-schema.vcs-ref=$VCS_REF \ + org.label-schema.vcs-url="https://github.com/tronprotocol/java-tron.git" \ + org.label-schema.vendor="TRON protocol" \ + org.label-schema.version=$VERSION \ + org.label-schema.schema-version="1.0" diff --git a/docker/arm64/Dockerfile b/docker/arm64/Dockerfile index 6435faf7ead..1da2e75331b 100644 --- a/docker/arm64/Dockerfile +++ b/docker/arm64/Dockerfile @@ -1,33 +1,51 @@ -FROM arm64v8/eclipse-temurin:17 +FROM ubuntu:24.04 +ARG VERSION="dev" +ENV NO_PROXY_CACHE="-o Acquire::BrokenProxy=true -o Acquire::http::No-Cache=true -o Acquire::http::Pipeline-Depth=0" ENV TMP_DIR="/tron-build" ENV BASE_DIR="/java-tron" -RUN set -o errexit -o nounset \ - && apt-get update \ - && apt-get -y install git p7zip-full wget libtcmalloc-minimal4 \ - && echo "git clone" \ - && mkdir -p $TMP_DIR \ - && cd $TMP_DIR \ - && git clone https://github.com/tronprotocol/java-tron.git \ - && cd java-tron \ - && git checkout master \ - && ./gradlew clean build -x test -x check --no-daemon \ - && cd build/distributions \ - && 7za x -y java-tron-1.0.0.zip \ - && mv java-tron-1.0.0 $BASE_DIR \ - && rm -rf $TMP_DIR \ - && rm -rf ~/.gradle \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/* +# Update and install dependencies without using any cache +RUN apt-get update $NO_PROXY_CACHE \ + && apt-get --quiet --yes install git wget 7zip curl jq libtcmalloc-minimal4 openjdk-17-jre-headless=17* \ + && echo "git clone" \ + && mkdir -p $TMP_DIR \ + && cd $TMP_DIR \ + && git clone https://github.com/tronprotocol/java-tron.git \ + && cd java-tron \ + && git checkout master \ + && ./gradlew clean build -x test -x check --no-daemon \ + && cd build/distributions \ + && 7z x -y java-tron-1.0.0.zip \ + && mv java-tron-1.0.0 $BASE_DIR \ + && rm -rf $TMP_DIR \ + && rm -rf ~/.gradle \ + && wget -4 -O $BASE_DIR/config.conf https://raw.githubusercontent.com/tronprotocol/java-tron/master/framework/src/main/resources/config.conf \ + # Clean apt cache + && apt-get clean \ + && rm -rf /var/cache/apt/archives/* /var/cache/apt/archives/partial/* \ + && rm -rf /var/lib/apt/lists/* +ENV JAVA_HOME="/usr/lib/jvm/java-17-openjdk-arm64" +ENV PATH=$PATH:$JAVA_HOME/bin ENV LD_PRELOAD="/usr/lib/aarch64-linux-gnu/libtcmalloc_minimal.so.4" ENV TCMALLOC_RELEASE_RATE=10 -RUN wget -P $BASE_DIR/config https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/main_net_config.conf - COPY docker-entrypoint.sh $BASE_DIR/bin WORKDIR $BASE_DIR -ENTRYPOINT ["./bin/docker-entrypoint.sh"] \ No newline at end of file +ENTRYPOINT ["./bin/docker-entrypoint.sh"] + +# Build-time metadata as defined at http://label-schema.org +ARG BUILD_DATE +ARG VCS_REF +LABEL org.label-schema.build-date=$BUILD_DATE \ + org.label-schema.name="Java-TRON" \ + org.label-schema.description="TRON protocol" \ + org.label-schema.url="https://tron.network/" \ + org.label-schema.vcs-ref=$VCS_REF \ + org.label-schema.vcs-url="https://github.com/tronprotocol/java-tron.git" \ + org.label-schema.vendor="TRON protocol" \ + org.label-schema.version=$VERSION \ + org.label-schema.schema-version="1.0" From d421894c89f80e5a96c34739be1f76432b77b934 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 10:53:34 +0800 Subject: [PATCH 02/35] build(docker): reuse config from cloned source Copy config.conf from the checked-out repository into the distribution and remove the redundant wget dependency and download step. --- docker/Dockerfile | 4 ++-- docker/arm64/Dockerfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 743c77bf54e..7ceecb4cc68 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -10,7 +10,7 @@ ENV BASE_DIR="/java-tron" # Update and install dependencies without using any cache RUN apt-get update $NO_PROXY_CACHE && \ - apt-get --quiet --yes install git wget 7zip curl jq libtcmalloc-minimal4 gnupg dirmngr ca-certificates && \ + apt-get --quiet --yes install git 7zip curl jq libtcmalloc-minimal4 gnupg dirmngr ca-certificates && \ cd /usr/local \ && FETCH_URL="$(curl -fsS -w "%{redirect_url}" -o /dev/null "$OPENJDK8_URL")" \ && JDK_TAR="$(curl -fsSL -w "%{filename_effective}" -O "$FETCH_URL")" \ @@ -35,12 +35,12 @@ RUN apt-get update $NO_PROXY_CACHE && \ && ./gradlew clean build -x test -x check --no-daemon \ && cd build/distributions \ && 7z x -y java-tron-1.0.0.zip \ + && cp $TMP_DIR/java-tron/framework/src/main/resources/config.conf java-tron-1.0.0/config.conf \ && mv java-tron-1.0.0 $BASE_DIR \ && rm -rf $TMP_DIR \ && rm -rf ~/.gradle \ && mv $JDK_DIR/jre /usr/local \ && rm -rf $JDK_DIR \ - && wget -O $BASE_DIR/config.conf https://raw.githubusercontent.com/tronprotocol/java-tron/master/framework/src/main/resources/config.conf \ # Clean apt cache && apt-get clean \ && rm -rf /var/cache/apt/archives/* /var/cache/apt/archives/partial/* \ diff --git a/docker/arm64/Dockerfile b/docker/arm64/Dockerfile index 1da2e75331b..9ba81a87cfe 100644 --- a/docker/arm64/Dockerfile +++ b/docker/arm64/Dockerfile @@ -7,7 +7,7 @@ ENV BASE_DIR="/java-tron" # Update and install dependencies without using any cache RUN apt-get update $NO_PROXY_CACHE \ - && apt-get --quiet --yes install git wget 7zip curl jq libtcmalloc-minimal4 openjdk-17-jre-headless=17* \ + && apt-get --quiet --yes install git 7zip curl jq libtcmalloc-minimal4 openjdk-17-jre-headless=17* \ && echo "git clone" \ && mkdir -p $TMP_DIR \ && cd $TMP_DIR \ @@ -17,10 +17,10 @@ RUN apt-get update $NO_PROXY_CACHE \ && ./gradlew clean build -x test -x check --no-daemon \ && cd build/distributions \ && 7z x -y java-tron-1.0.0.zip \ + && cp $TMP_DIR/java-tron/framework/src/main/resources/config.conf java-tron-1.0.0/config.conf \ && mv java-tron-1.0.0 $BASE_DIR \ && rm -rf $TMP_DIR \ && rm -rf ~/.gradle \ - && wget -4 -O $BASE_DIR/config.conf https://raw.githubusercontent.com/tronprotocol/java-tron/master/framework/src/main/resources/config.conf \ # Clean apt cache && apt-get clean \ && rm -rf /var/cache/apt/archives/* /var/cache/apt/archives/partial/* \ From 2f87531a94b5f1a33cb5b1667ab11962443e9100 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 14:54:06 +0800 Subject: [PATCH 03/35] fix(docker): refine network configuration handling - use the image-bundled configuration for mainnet - remove unsupported Nile testnet handling - download the private network configuration only when missing - preserve local private configuration unless an update is requested - fail fast when configuration downloads fail - document the updated network and configuration behavior --- docker/docker.md | 55 ++++++++++++-------- docker/docker.sh | 128 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 122 insertions(+), 61 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index 79aa6b08e2d..6ba7fe81323 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -18,7 +18,7 @@ $ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker/d ### Pull the mirror image Get the `tronprotocol/java-tron` image from the DockerHub, this image contains the full JDK environment and the host network configuration file, using the script for simple docker operations. ```shell -$ sh docker.sh --pull +$ bash docker.sh --pull ``` ### Run the service @@ -30,46 +30,63 @@ Before running the java-tron service, make sure some ports on your local machine #### Full node on the main network ```shell -$ sh docker.sh --run --net main +$ bash docker.sh --run ``` -or you can use `-p` to customize the port mapping, more custom parameters, please refer to [Options](#Options) +The mainnet configuration is bundled in the image at `/java-tron/config.conf` and comes from the +same java-tron revision used to build the image. `--net main` remains available as an explicit form. + +You can use `-p` to customize the port mapping. For more custom parameters, see +[Options](#Options). ```shell -$ sh docker.sh --run --net main -p 8080:8090 -p 40051:50051 +$ bash docker.sh --run --net main -p 8080:8090 -p 40051:50051 ``` -#### Full node on the nile test network +#### Full node on the private network +You can also run a private network with the configuration maintained by `tron-deployment`. +If `config/private_net_config.conf` does not exist in the current directory, the script downloads +it automatically. An existing local configuration is reused so that local changes are preserved. ```shell -$ sh docker.sh --run --net test +$ bash docker.sh --run --net private ``` -#### Full node on the private network -you can also build your own private-net and will download a configuration file from the network for your private network, which will be stored in your local `config` directory. +To replace an existing local copy with the latest maintained configuration, explicitly request an +update. This overwrites `config/private_net_config.conf`. + ```shell -$ sh docker.sh --run --net private +$ bash docker.sh --run --net private --update-config true ``` + #### Configuration -The script will automatically download and use the corresponding configuration file from the github repository according to the `--net` parameter. if you don't want to update the configuration file every time you start the service, please add a startup parameter. +Mainnet uses the configuration bundled in the image and never downloads another configuration. +The `private` network option uses `config/private_net_config.conf` from the current directory, +downloading it from `tron-deployment` only when it is missing or an update is explicitly requested. + +Nile is intentionally not supported by this script because it may require features that are not +yet available on the mainnet source revision. Follow the Nile-specific build instructions in the +project README instead. + +Alternatively, mount a configuration into the container and select it with `-c`: ```shell -$ sh docker.sh --run --update-config false +$ bash docker.sh --run \ + -v /absolute/path/custom.conf:/java-tron/custom.conf:ro \ + -c /java-tron/custom.conf ``` -Or use the `-c` parameter to specify your own configuration file, which will not automatically download a new configuration file from github repository. - ### View logs If you want to see the logs of the java-tron service, please use the `--log` parameter ```shell -$ sh docker.sh --log | grep 'PushBlock' +$ bash docker.sh --log | grep 'PushBlock' ``` ### Stop the service If you want to stop the container of java-tron, you can execute ```shell -$ sh docker.sh --stop +$ bash docker.sh --stop ``` ## Build Image @@ -88,7 +105,7 @@ DOCKER_TARGET="1.0" then execute the build: ```shell -$ sh docker.sh --build +$ bash docker.sh --build ``` ## Options @@ -104,7 +121,5 @@ Parameters for all functions: * **`-p`** publish a container's port to the host, format:`-p hostPort:containerPort` * **`-c`** specify other java-tron configuration file in the container * **`-v`** bind mount a volume for the container,format: `-v host-src:container-dest`, the `host-src` is an absolute path -* **`--net`** select the network, you can join the main-net, test-net -* **`--update-config`** update configuration file, default true - - +* **`--net`** select `main` or `private`; a missing private configuration is downloaded automatically +* **`--update-config`** set to `true` with `--net private` to replace the local private configuration diff --git a/docker/docker.sh b/docker/docker.sh index bf4961f0620..ea8d1d82633 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -32,17 +32,12 @@ DOCKER_RPC_PORT=50051 DOCKER_LISTEN_PORT=18888 VOLUME=`pwd` -CONFIG="$VOLUME/config" +CONFIG_DIR="$VOLUME/config" OUTPUT_DIRECTORY="$VOLUME/output-directory" -CONFIG_PATH="/java-tron/config/" -CONFIG_FILE="main_net_config.conf" -MAIN_NET_CONFIG_FILE="main_net_config.conf" -TEST_NET_CONFIG_FILE="test_net_config.conf" +BUNDLED_CONFIG_FILE="$BASE_DIR/config.conf" PRIVATE_NET_CONFIG_FILE="private_net_config.conf" - -# update the configuration file, if true, the configuration file will be fetched from the network every time you start -UPDATE_CONFIG=true +PRIVATE_NET_CONFIG_URL="https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$PRIVATE_NET_CONFIG_FILE" LOG_FILE="/logs/tron.log" @@ -67,25 +62,53 @@ docker_image() { image=$image_name } -download_config() { - mkdir -p config - if test curl; then - curl -o config/$CONFIG_FILE -LO https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE -s - elif test wget; then - wget -P -q config/ https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE +download_private_config() { + local config_file=$1 + local temp_file + + if ! mkdir -p "$CONFIG_DIR"; then + echo "run: failed to create configuration directory: $CONFIG_DIR" + return 1 fi -} + if ! temp_file=$(mktemp "$CONFIG_DIR/.private_net_config.conf.XXXXXX"); then + echo "run: failed to create a temporary configuration file" + return 1 + fi -check_download_config() { - if [[ ! -d 'config' || ! -f "config/$CONFIG_FILE" ]]; then - mkdir -p config - if test curl; then - curl -o config/$CONFIG_FILE -LO https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE -s - elif test wget; then - wget -P -q config/ https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$CONFIG_FILE + if command -v curl >/dev/null 2>&1; then + if ! curl --fail --silent --show-error --location \ + --output "$temp_file" "$PRIVATE_NET_CONFIG_URL"; then + rm -f "$temp_file" + echo "run: failed to download private network configuration" + return 1 fi + elif command -v wget >/dev/null 2>&1; then + if ! wget --quiet --output-document="$temp_file" "$PRIVATE_NET_CONFIG_URL"; then + rm -f "$temp_file" + echo "run: failed to download private network configuration" + return 1 + fi + else + rm -f "$temp_file" + echo "run: curl or wget is required to download the private network configuration" + return 1 + fi + + if [[ ! -s "$temp_file" ]]; then + rm -f "$temp_file" + echo "run: downloaded private network configuration is empty" + return 1 + fi + + chmod 644 "$temp_file" + if ! mv -f "$temp_file" "$config_file"; then + rm -f "$temp_file" + echo "run: failed to save private network configuration: $config_file" + return 1 fi + + echo "private network configuration saved to $config_file" } run() { @@ -106,6 +129,10 @@ run() { volume="" parameter="" tron_parameter="" + network="main" + network_config="" + custom_config=false + update_config=false if [ $# -gt 0 ]; then while [ -n "$1" ]; do case "$1" in @@ -119,21 +146,19 @@ run() { ;; -c) tron_parameter="$tron_parameter -c $2" - UPDATE_CONFIG=false + custom_config=true shift 2 ;; --net) - if [[ "$2" = "main" ]]; then - CONFIG_FILE=$MAIN_NET_CONFIG_FILE - elif [[ "$2" = "test" ]]; then - CONFIG_FILE=$TEST_NET_CONFIG_FILE - elif [[ "$2" = "private" ]]; then - CONFIG_FILE=$PRIVATE_NET_CONFIG_FILE - fi + network=$2 shift 2 ;; --update-config) - UPDATE_CONFIG=$2 + if [[ "$2" != "true" && "$2" != "false" ]]; then + echo "run: --update-config expects true or false" + exit 1 + fi + update_config=$2 shift 2 ;; *) @@ -142,12 +167,37 @@ run() { ;; esac done - if [ $UPDATE_CONFIG = true ]; then - download_config + + if [[ "$network" = "private" ]]; then + network_config="$CONFIG_DIR/$PRIVATE_NET_CONFIG_FILE" + elif [[ "$network" != "main" ]]; then + echo "run: unsupported network '$network'; expected main or private" + exit 1 + fi + + if [[ "$custom_config" = true && -n "$network_config" ]]; then + echo "run: -c cannot be combined with --net private" + exit 1 fi - if [ -z "$volume" ]; then - volume=" -v $CONFIG:/java-tron/config -v $OUTPUT_DIRECTORY:/java-tron/output-directory" + if [[ "$update_config" = true && "$network" != "private" ]]; then + echo "run: --update-config true is only supported with --net private" + exit 1 + fi + + if [[ -n "$network_config" ]]; then + if [[ "$update_config" = true ]]; then + echo "updating private network configuration from tron-deployment" + download_private_config "$network_config" || exit 1 + elif [[ ! -f "$network_config" ]]; then + echo "private network configuration not found; downloading it from tron-deployment" + download_private_config "$network_config" || exit 1 + fi + volume="$volume -v $network_config:$BUNDLED_CONFIG_FILE:ro" + fi + + if [[ "$volume" != *":/java-tron/output-directory"* ]]; then + volume=" -v $OUTPUT_DIRECTORY:/java-tron/output-directory$volume" fi if [ -z "$parameter" ]; then @@ -155,7 +205,7 @@ run() { fi if [ -z "$tron_parameter" ]; then - tron_parameter=" -c $CONFIG_PATH$CONFIG_FILE" + tron_parameter=" -c $BUNDLED_CONFIG_FILE" fi # Using custom parameters @@ -166,19 +216,15 @@ run() { "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ $tron_parameter else - if [ $UPDATE_CONFIG = true ]; then - download_config - fi # Default parameters docker run -d -it --name "$DOCKER_REPOSITORY-$DOCKER_IMAGES" \ - -v $CONFIG:/java-tron/config \ -v $OUTPUT_DIRECTORY:/java-tron/output-directory \ -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT \ -p $HOST_RPC_PORT:$DOCKER_RPC_PORT \ -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT \ --restart always \ "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ - -c "$CONFIG_PATH$CONFIG_FILE" + -c "$BUNDLED_CONFIG_FILE" fi } From cb1db22cad0bc2db7531ba2baf3a70d9f26745e5 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 16:18:20 +0800 Subject: [PATCH 04/35] fix(docker): make helper builds context-independent Resolve build files relative to docker.sh and automatically select the architecture-specific Dockerfile. Preserve standalone builds by downloading required files into a temporary context, failing on invalid downloads, and cleaning up after completion. Document automatic and explicit architecture selection. --- docker/docker.md | 15 ++++++- docker/docker.sh | 115 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 110 insertions(+), 20 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index 6ba7fe81323..1dbe1d3daf3 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -108,11 +108,24 @@ then execute the build: $ bash docker.sh --build ``` +The script detects the Docker daemon architecture by default. You can also select the target +architecture explicitly: + +```shell +$ bash docker.sh --build amd64 +$ bash docker.sh --build arm64 +``` + +When the script is used from a java-tron checkout, the Dockerfile and build context are resolved +relative to `docker.sh`, regardless of the current working directory. If only `docker.sh` was +downloaded, the required architecture-specific Dockerfile and entrypoint are downloaded into a +temporary build context and removed after the build. + ## Options Parameters for all functions: -* **`--build`** building a local mirror image +* **`--build [amd64|arm64]`** building a local mirror image, optionally for the specified architecture * **`--pull`** download a docker mirror from **DockerHub** * **`--run`** run the docker mirror * **`--log`** exporting the java-tron run log on the container diff --git a/docker/docker.sh b/docker/docker.sh index ea8d1d82633..2c0848ef053 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -17,6 +17,7 @@ # ############################################################################## +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" BASE_DIR="/java-tron" DOCKER_REPOSITORY="tronprotocol" DOCKER_IMAGES="java-tron" @@ -41,9 +42,7 @@ PRIVATE_NET_CONFIG_URL="https://raw.githubusercontent.com/tronprotocol/tron-depl LOG_FILE="/logs/tron.log" -JAVA_TRON_REPOSITORY="https://raw.githubusercontent.com/tronprotocol/java-tron/develop/" -DOCKER_FILE="Dockerfile" -ENDPOINT_SHELL="docker-entrypoint.sh" +JAVA_TRON_DOCKER_URL="https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker" if test docker; then docker -v @@ -62,6 +61,32 @@ docker_image() { image=$image_name } +download_build_file() { + local source_url=$1 + local destination=$2 + + if command -v curl >/dev/null 2>&1; then + if ! curl --fail --silent --show-error --location \ + --output "$destination" "$source_url"; then + echo "build: failed to download: $source_url" >&2 + return 1 + fi + elif command -v wget >/dev/null 2>&1; then + if ! wget --quiet --output-document="$destination" "$source_url"; then + echo "build: failed to download: $source_url" >&2 + return 1 + fi + else + echo "build: curl or wget is required to download build files" >&2 + return 1 + fi + + if [[ ! -s "$destination" ]]; then + echo "build: downloaded file is empty: $source_url" >&2 + return 1 + fi +} + download_private_config() { local config_file=$1 local temp_file @@ -229,23 +254,75 @@ run() { } build() { - echo 'docker build' - if [ ! -f "Dockerfile" ]; then - echo 'warning: Dockerfile not exists.' - if test curl; then - DOWNLOAD_CMD="curl -LJO " - elif test wget; then - DOWNLOAD_CMD="wget " - else - echo "Dockerfile cannot be downloaded, you need to install 'curl' or 'wget'!" - exit + local arch="${1:-}" + local platform + local dockerfile_path + local dockerfile_source + local build_context="$SCRIPT_DIR" + local temporary_context="" + local build_status + + if [[ $# -gt 1 ]]; then + echo "build: expected at most one architecture argument" >&2 + return 1 + fi + + if [[ -z "$arch" ]]; then + if ! arch=$(docker info --format '{{.Architecture}}'); then + echo "build: failed to determine the Docker daemon architecture" >&2 + return 1 + fi + fi + + case "$arch" in + amd64 | x86_64) + platform="linux/amd64" + dockerfile_path="$SCRIPT_DIR/Dockerfile" + dockerfile_source="$JAVA_TRON_DOCKER_URL/Dockerfile" + ;; + arm64 | aarch64) + platform="linux/arm64" + dockerfile_path="$SCRIPT_DIR/arm64/Dockerfile" + dockerfile_source="$JAVA_TRON_DOCKER_URL/arm64/Dockerfile" + ;; + *) + echo "build: unsupported architecture: $arch" >&2 + return 1 + ;; + esac + + if [[ ! -f "$dockerfile_path" || ! -f "$SCRIPT_DIR/docker-entrypoint.sh" ]]; then + if ! temporary_context=$(mktemp -d "${TMPDIR:-/tmp}/java-tron-docker.XXXXXX"); then + echo "build: failed to create a temporary build context" >&2 + return 1 + fi + + build_context="$temporary_context" + dockerfile_path="$temporary_context/Dockerfile" + + echo "build files not found next to docker.sh; downloading a temporary build context" + if ! download_build_file "$dockerfile_source" "$dockerfile_path" \ + || ! download_build_file "$JAVA_TRON_DOCKER_URL/docker-entrypoint.sh" \ + "$temporary_context/docker-entrypoint.sh"; then + rm -rf "$temporary_context" + return 1 fi - # download Dockerfile - `$DOWNLOAD_CMD "$JAVA_TRON_REPOSITORY$DOCKER_FILE"` - `$DOWNLOAD_CMD "$JAVA_TRON_REPOSITORY$ENDPOINT_SHELL"` - chmod u+rwx $ENDPOINT_SHELL + chmod 755 "$temporary_context/docker-entrypoint.sh" fi - docker build -t "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" . + + echo "docker build --platform $platform --file $dockerfile_path" + docker build \ + --platform "$platform" \ + --file "$dockerfile_path" \ + --tag "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ + "$build_context" + build_status=$? + + if [[ -n "$temporary_context" ]]; then + rm -rf "$temporary_context" + fi + + return "$build_status" } pull() { @@ -315,7 +392,7 @@ case "$1" in exit ;; --build) - build ${@: 2} + build "${@:2}" exit ;; --run) From f659d388ca83fa03eb46f9598582b3f07b373381 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 16:41:52 +0800 Subject: [PATCH 05/35] fix(docker): validate daemon and target exact resources Fail fast when the Docker client or daemon is unavailable and propagate command failures through the helper script. Replace fuzzy container and image list parsing with exact inspect calls using the configured container name and complete image reference. Return non-zero status for invalid arguments, missing containers, and cancelled image pulls. --- docker/docker.sh | 132 +++++++++++++++++++++++------------------------ 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/docker/docker.sh b/docker/docker.sh index 2c0848ef053..fa34a9a8fe3 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -23,6 +23,8 @@ DOCKER_REPOSITORY="tronprotocol" DOCKER_IMAGES="java-tron" # latest or version DOCKER_TARGET="latest" +CONTAINER_NAME="$DOCKER_REPOSITORY-$DOCKER_IMAGES" +IMAGE_REFERENCE="$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" HOST_HTTP_PORT=8090 HOST_RPC_PORT=50051 @@ -44,21 +46,22 @@ LOG_FILE="/logs/tron.log" JAVA_TRON_DOCKER_URL="https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker" -if test docker; then - docker -v -else - echo "warning: docker must be installed, please install docker first." - exit +if ! command -v docker >/dev/null 2>&1; then + echo "docker is required but was not found" >&2 + exit 1 fi -docker_ps() { - containerID=`docker ps -a | grep "$DOCKER_REPOSITORY-$DOCKER_IMAGES" | awk '{print $1}'` - cid=$containerID +if ! docker info >/dev/null 2>&1; then + echo "unable to connect to the Docker daemon" >&2 + exit 1 +fi + +docker_container_exists() { + docker container inspect "$CONTAINER_NAME" >/dev/null 2>&1 } -docker_image() { - image_name=`docker images |grep "$DOCKER_REPOSITORY/$DOCKER_IMAGES" |awk {'print $1'}| awk 'NR==1'` - image=$image_name +docker_image_exists() { + docker image inspect "$IMAGE_REFERENCE" >/dev/null 2>&1 } download_build_file() { @@ -137,17 +140,15 @@ download_private_config() { } run() { - docker_image - - if [ ! $image ] ; then + if ! docker_image_exists; then echo 'warning: no java-tron mirror image, do you need to get the mirror image?[y/n]' read need if [[ $need == 'y' || $need == 'yes' ]]; then - pull + pull || return $? else echo "warning: no mirror image found, go ahead and download a mirror." - exit + exit 1 fi fi @@ -188,7 +189,7 @@ run() { ;; *) echo "run: arg $1 is not a valid parameter" - exit + exit 1 ;; esac done @@ -234,21 +235,21 @@ run() { fi # Using custom parameters - docker run -d -it --name "$DOCKER_REPOSITORY-$DOCKER_IMAGES" \ + docker run -d -it --name "$CONTAINER_NAME" \ $volume \ $parameter \ --restart always \ - "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ + "$IMAGE_REFERENCE" \ $tron_parameter else # Default parameters - docker run -d -it --name "$DOCKER_REPOSITORY-$DOCKER_IMAGES" \ + docker run -d -it --name "$CONTAINER_NAME" \ -v $OUTPUT_DIRECTORY:/java-tron/output-directory \ -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT \ -p $HOST_RPC_PORT:$DOCKER_RPC_PORT \ -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT \ --restart always \ - "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ + "$IMAGE_REFERENCE" \ -c "$BUNDLED_CONFIG_FILE" fi } @@ -314,7 +315,7 @@ build() { docker build \ --platform "$platform" \ --file "$dockerfile_path" \ - --tag "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" \ + --tag "$IMAGE_REFERENCE" \ "$build_context" build_status=$? @@ -326,89 +327,88 @@ build() { } pull() { - echo "docker pull $DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" - docker pull "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" + echo "docker pull $IMAGE_REFERENCE" + docker pull "$IMAGE_REFERENCE" } start() { - docker_ps - if [ $cid ]; then - echo "containerID: $cid" - echo "docker stop $cid" - docker start $cid + if docker_container_exists; then + echo "container: $CONTAINER_NAME" + echo "docker start $CONTAINER_NAME" + docker start "$CONTAINER_NAME" || return $? docker ps else - echo "container not running!" + echo "container not found: $CONTAINER_NAME" >&2 + return 1 fi } stop() { - docker_ps - if [ $cid ]; then - echo "containerID: $cid" - echo "docker stop $cid" - docker stop $cid + if docker_container_exists; then + echo "container: $CONTAINER_NAME" + echo "docker stop $CONTAINER_NAME" + docker stop "$CONTAINER_NAME" || return $? docker ps else - echo "container not running!" + echo "container not found: $CONTAINER_NAME" >&2 + return 1 fi } rm_container() { - stop - if [ $cid ]; then - echo "containerID: $cid" - echo "docker rm $cid" - docker rm $cid - docker_ps - else - echo "image not exists!" + if ! docker_container_exists; then + echo "container not found: $CONTAINER_NAME" >&2 + return 1 fi + + echo "container: $CONTAINER_NAME" + echo "docker stop $CONTAINER_NAME" + docker stop "$CONTAINER_NAME" || return $? + echo "docker rm $CONTAINER_NAME" + docker rm "$CONTAINER_NAME" } log() { - docker_ps - - if [ $cid ]; then - echo "containerID: $cid" - docker exec -it $cid tail -100f $BASE_DIR/$LOG_FILE + if docker_container_exists; then + echo "container: $CONTAINER_NAME" + docker exec -it "$CONTAINER_NAME" tail -100f "$BASE_DIR/$LOG_FILE" else - echo "container not exists!" + echo "container not found: $CONTAINER_NAME" >&2 + return 1 fi - } case "$1" in --pull) - pull ${@: 2} - exit + pull "${@:2}" + exit $? ;; --start) - start ${@: 2} - exit + start "${@:2}" + exit $? ;; --stop) - stop ${@: 2} - exit + stop "${@:2}" + exit $? ;; --build) build "${@:2}" - exit + exit $? ;; --run) - run ${@: 2} - exit + run "${@:2}" + exit $? ;; --rm) - rm_container ${@: 2} - exit + rm_container "${@:2}" + exit $? ;; --log) - log ${@: 2} - exit + log "${@:2}" + exit $? ;; *) - echo "arg: $1 is not a valid parameter" - exit + echo "arg: $1 is not a valid parameter" >&2 + exit 1 ;; esac From cb004bf7dead3f98b7d85c099f1a78e56272a4b4 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 16:58:54 +0800 Subject: [PATCH 06/35] fix(docker): publish P2P port over UDP Publish port 18888 over both TCP and UDP in the default container configuration. Document that custom port mappings replace all defaults and update the example to preserve both P2P protocols. --- docker/docker.md | 11 ++++++++--- docker/docker.sh | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index 1dbe1d3daf3..c9ba5ab3de4 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -35,11 +35,16 @@ $ bash docker.sh --run The mainnet configuration is bundled in the image at `/java-tron/config.conf` and comes from the same java-tron revision used to build the image. `--net main` remains available as an explicit form. -You can use `-p` to customize the port mapping. For more custom parameters, see +You can use `-p` to customize the port mapping. Supplying any custom `-p` replaces the complete +default port set, so include both TCP and UDP mappings for P2P. For more custom parameters, see [Options](#Options). ```shell -$ bash docker.sh --run --net main -p 8080:8090 -p 40051:50051 +$ bash docker.sh --run --net main \ + -p 8080:8090 \ + -p 40051:50051 \ + -p 18888:18888 \ + -p 18888:18888/udp ``` #### Full node on the private network @@ -131,7 +136,7 @@ Parameters for all functions: * **`--log`** exporting the java-tron run log on the container * **`--stop`** stopping a running container * **`--rm`** remove container,only deletes the container, not the image -* **`-p`** publish a container's port to the host, format:`-p hostPort:containerPort` +* **`-p`** publish a container's port to the host, format: `-p hostPort:containerPort[/protocol]`; custom mappings replace all defaults * **`-c`** specify other java-tron configuration file in the container * **`-v`** bind mount a volume for the container,format: `-v host-src:container-dest`, the `host-src` is an absolute path * **`--net`** select `main` or `private`; a missing private configuration is downloaded automatically diff --git a/docker/docker.sh b/docker/docker.sh index fa34a9a8fe3..b26ce2e2642 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -227,7 +227,7 @@ run() { fi if [ -z "$parameter" ]; then - parameter=" -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT -p $HOST_RPC_PORT:$DOCKER_RPC_PORT -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT" + parameter=" -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT -p $HOST_RPC_PORT:$DOCKER_RPC_PORT -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp" fi if [ -z "$tron_parameter" ]; then @@ -248,6 +248,7 @@ run() { -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT \ -p $HOST_RPC_PORT:$DOCKER_RPC_PORT \ -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT \ + -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp \ --restart always \ "$IMAGE_REFERENCE" \ -c "$BUNDLED_CONFIG_FILE" From 3c2fed068e885b7b543558d1513c4fa32002944d Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 17:05:10 +0800 Subject: [PATCH 07/35] fix(docker): handle run arguments safely Build volume, port, and java-tron options with Bash arrays to preserve spaces and wildcard characters. Validate required option values and share one quoted docker run path for default and custom configurations. --- docker/docker.sh | 200 ++++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 91 deletions(-) diff --git a/docker/docker.sh b/docker/docker.sh index b26ce2e2642..174deebfd55 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -139,7 +139,27 @@ download_private_config() { echo "private network configuration saved to $config_file" } +require_run_option_value() { + local option=$1 + + if [[ $# -lt 2 || -z "$2" ]]; then + echo "run: $option requires a value" >&2 + return 1 + fi +} + run() { + local -a volume_args=() + local -a port_args=() + local -a tron_args=() + local network="main" + local network_config="" + local custom_config=false + local update_config=false + local has_output_volume=false + local mount + local index + if ! docker_image_exists; then echo 'warning: no java-tron mirror image, do you need to get the mirror image?[y/n]' read need @@ -152,107 +172,105 @@ run() { fi fi - volume="" - parameter="" - tron_parameter="" - network="main" - network_config="" - custom_config=false - update_config=false - if [ $# -gt 0 ]; then - while [ -n "$1" ]; do - case "$1" in - -v) - volume="$volume -v $2" - shift 2 - ;; - -p) - parameter="$parameter -p $2" - shift 2 - ;; - -c) - tron_parameter="$tron_parameter -c $2" - custom_config=true - shift 2 - ;; - --net) - network=$2 - shift 2 - ;; - --update-config) - if [[ "$2" != "true" && "$2" != "false" ]]; then - echo "run: --update-config expects true or false" - exit 1 - fi - update_config=$2 - shift 2 - ;; - *) - echo "run: arg $1 is not a valid parameter" - exit 1 - ;; - esac - done - - if [[ "$network" = "private" ]]; then - network_config="$CONFIG_DIR/$PRIVATE_NET_CONFIG_FILE" - elif [[ "$network" != "main" ]]; then - echo "run: unsupported network '$network'; expected main or private" - exit 1 - fi + while [[ $# -gt 0 ]]; do + case "$1" in + -v) + require_run_option_value "$@" || return 1 + volume_args+=(-v "$2") + shift 2 + ;; + -p) + require_run_option_value "$@" || return 1 + port_args+=(-p "$2") + shift 2 + ;; + -c) + require_run_option_value "$@" || return 1 + tron_args+=(-c "$2") + custom_config=true + shift 2 + ;; + --net) + require_run_option_value "$@" || return 1 + network=$2 + shift 2 + ;; + --update-config) + require_run_option_value "$@" || return 1 + if [[ "$2" != "true" && "$2" != "false" ]]; then + echo "run: --update-config expects true or false" >&2 + return 1 + fi + update_config=$2 + shift 2 + ;; + *) + echo "run: arg $1 is not a valid parameter" >&2 + return 1 + ;; + esac + done + + if [[ "$network" = "private" ]]; then + network_config="$CONFIG_DIR/$PRIVATE_NET_CONFIG_FILE" + elif [[ "$network" != "main" ]]; then + echo "run: unsupported network '$network'; expected main or private" >&2 + return 1 + fi - if [[ "$custom_config" = true && -n "$network_config" ]]; then - echo "run: -c cannot be combined with --net private" - exit 1 - fi + if [[ "$custom_config" = true && -n "$network_config" ]]; then + echo "run: -c cannot be combined with --net private" >&2 + return 1 + fi - if [[ "$update_config" = true && "$network" != "private" ]]; then - echo "run: --update-config true is only supported with --net private" - exit 1 - fi + if [[ "$update_config" = true && "$network" != "private" ]]; then + echo "run: --update-config true is only supported with --net private" >&2 + return 1 + fi - if [[ -n "$network_config" ]]; then - if [[ "$update_config" = true ]]; then - echo "updating private network configuration from tron-deployment" - download_private_config "$network_config" || exit 1 - elif [[ ! -f "$network_config" ]]; then - echo "private network configuration not found; downloading it from tron-deployment" - download_private_config "$network_config" || exit 1 - fi - volume="$volume -v $network_config:$BUNDLED_CONFIG_FILE:ro" + if [[ -n "$network_config" ]]; then + if [[ "$update_config" = true ]]; then + echo "updating private network configuration from tron-deployment" + download_private_config "$network_config" || return 1 + elif [[ ! -f "$network_config" ]]; then + echo "private network configuration not found; downloading it from tron-deployment" + download_private_config "$network_config" || return 1 fi + volume_args+=(-v "$network_config:$BUNDLED_CONFIG_FILE:ro") + fi - if [[ "$volume" != *":/java-tron/output-directory"* ]]; then - volume=" -v $OUTPUT_DIRECTORY:/java-tron/output-directory$volume" + for ((index = 1; index < ${#volume_args[@]}; index += 2)); do + mount=${volume_args[$index]} + if [[ "$mount" == *":/java-tron/output-directory" \ + || "$mount" == *":/java-tron/output-directory:"* ]]; then + has_output_volume=true + break fi + done - if [ -z "$parameter" ]; then - parameter=" -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT -p $HOST_RPC_PORT:$DOCKER_RPC_PORT -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp" - fi + if [[ "$has_output_volume" = false ]]; then + volume_args=(-v "$OUTPUT_DIRECTORY:/java-tron/output-directory" "${volume_args[@]}") + fi - if [ -z "$tron_parameter" ]; then - tron_parameter=" -c $BUNDLED_CONFIG_FILE" - fi + if [[ ${#port_args[@]} -eq 0 ]]; then + port_args=( + -p "$HOST_HTTP_PORT:$DOCKER_HTTP_PORT" + -p "$HOST_RPC_PORT:$DOCKER_RPC_PORT" + -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT" + -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp" + ) + fi - # Using custom parameters - docker run -d -it --name "$CONTAINER_NAME" \ - $volume \ - $parameter \ - --restart always \ - "$IMAGE_REFERENCE" \ - $tron_parameter - else - # Default parameters - docker run -d -it --name "$CONTAINER_NAME" \ - -v $OUTPUT_DIRECTORY:/java-tron/output-directory \ - -p $HOST_HTTP_PORT:$DOCKER_HTTP_PORT \ - -p $HOST_RPC_PORT:$DOCKER_RPC_PORT \ - -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT \ - -p $HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp \ - --restart always \ - "$IMAGE_REFERENCE" \ - -c "$BUNDLED_CONFIG_FILE" + if [[ ${#tron_args[@]} -eq 0 ]]; then + tron_args=(-c "$BUNDLED_CONFIG_FILE") fi + + docker run -d -it --name "$CONTAINER_NAME" \ + "${volume_args[@]}" \ + "${port_args[@]}" \ + --restart always \ + "$IMAGE_REFERENCE" \ + "${tron_args[@]}" } build() { From 3e96becaec7a53421269d879c8b4ba3171d509ed Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 17:17:46 +0800 Subject: [PATCH 08/35] refactor(docker): invoke FullNode directly Remove the unused entrypoint wrapper and command.txt side effect. Configure both images to launch FullNode directly and simplify standalone builds to download only the selected Dockerfile. --- docker/Dockerfile | 4 +--- docker/arm64/Dockerfile | 4 +--- docker/docker-entrypoint.sh | 6 ------ docker/docker.sh | 7 ++----- 4 files changed, 4 insertions(+), 17 deletions(-) delete mode 100755 docker/docker-entrypoint.sh diff --git a/docker/Dockerfile b/docker/Dockerfile index 7ceecb4cc68..2f7915e7032 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -51,11 +51,9 @@ ENV PATH=$PATH:$JAVA_HOME/bin ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4" ENV TCMALLOC_RELEASE_RATE=10 -COPY docker-entrypoint.sh $BASE_DIR/bin - WORKDIR $BASE_DIR -ENTRYPOINT ["./bin/docker-entrypoint.sh"] +ENTRYPOINT ["./bin/FullNode"] # Build-time metadata as defined at http://label-schema.org ARG BUILD_DATE diff --git a/docker/arm64/Dockerfile b/docker/arm64/Dockerfile index 9ba81a87cfe..8b4601223b6 100644 --- a/docker/arm64/Dockerfile +++ b/docker/arm64/Dockerfile @@ -31,11 +31,9 @@ ENV PATH=$PATH:$JAVA_HOME/bin ENV LD_PRELOAD="/usr/lib/aarch64-linux-gnu/libtcmalloc_minimal.so.4" ENV TCMALLOC_RELEASE_RATE=10 -COPY docker-entrypoint.sh $BASE_DIR/bin - WORKDIR $BASE_DIR -ENTRYPOINT ["./bin/docker-entrypoint.sh"] +ENTRYPOINT ["./bin/FullNode"] # Build-time metadata as defined at http://label-schema.org ARG BUILD_DATE diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh deleted file mode 100755 index d3c5d4c65c8..00000000000 --- a/docker/docker-entrypoint.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -eo pipefail -shopt -s nullglob - -echo "./bin/FullNode $@" > command.txt -exec "./bin/FullNode" "$@" \ No newline at end of file diff --git a/docker/docker.sh b/docker/docker.sh index 174deebfd55..f66d791700b 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -311,7 +311,7 @@ build() { ;; esac - if [[ ! -f "$dockerfile_path" || ! -f "$SCRIPT_DIR/docker-entrypoint.sh" ]]; then + if [[ ! -f "$dockerfile_path" ]]; then if ! temporary_context=$(mktemp -d "${TMPDIR:-/tmp}/java-tron-docker.XXXXXX"); then echo "build: failed to create a temporary build context" >&2 return 1 @@ -321,13 +321,10 @@ build() { dockerfile_path="$temporary_context/Dockerfile" echo "build files not found next to docker.sh; downloading a temporary build context" - if ! download_build_file "$dockerfile_source" "$dockerfile_path" \ - || ! download_build_file "$JAVA_TRON_DOCKER_URL/docker-entrypoint.sh" \ - "$temporary_context/docker-entrypoint.sh"; then + if ! download_build_file "$dockerfile_source" "$dockerfile_path"; then rm -rf "$temporary_context" return 1 fi - chmod 755 "$temporary_context/docker-entrypoint.sh" fi echo "docker build --platform $platform --file $dockerfile_path" From 59b6464dea51aee9724a4ad39f6c1f771e97e6bf Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 17:31:40 +0800 Subject: [PATCH 09/35] docs(docker): align guide with runtime behavior Document the JRE-based images, standalone Dockerfile download, and the start command. Normalize the container log path to avoid a double slash. --- docker/docker.md | 8 +++++--- docker/docker.sh | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index c9ba5ab3de4..8e4db9b7536 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -16,7 +16,8 @@ $ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker/d ``` ### Pull the mirror image -Get the `tronprotocol/java-tron` image from the DockerHub, this image contains the full JDK environment and the host network configuration file, using the script for simple docker operations. +Get the `tronprotocol/java-tron` image from Docker Hub. The image contains a Java runtime +environment and the mainnet configuration file, and the script provides common Docker operations. ```shell $ bash docker.sh --pull ``` @@ -123,8 +124,8 @@ $ bash docker.sh --build arm64 When the script is used from a java-tron checkout, the Dockerfile and build context are resolved relative to `docker.sh`, regardless of the current working directory. If only `docker.sh` was -downloaded, the required architecture-specific Dockerfile and entrypoint are downloaded into a -temporary build context and removed after the build. +downloaded, the required architecture-specific Dockerfile is downloaded into a temporary build +context and removed after the build. ## Options @@ -133,6 +134,7 @@ Parameters for all functions: * **`--build [amd64|arm64]`** building a local mirror image, optionally for the specified architecture * **`--pull`** download a docker mirror from **DockerHub** * **`--run`** run the docker mirror +* **`--start`** start the existing java-tron container * **`--log`** exporting the java-tron run log on the container * **`--stop`** stopping a running container * **`--rm`** remove container,only deletes the container, not the image diff --git a/docker/docker.sh b/docker/docker.sh index f66d791700b..ac7b438b7e8 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -42,7 +42,7 @@ BUNDLED_CONFIG_FILE="$BASE_DIR/config.conf" PRIVATE_NET_CONFIG_FILE="private_net_config.conf" PRIVATE_NET_CONFIG_URL="https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$PRIVATE_NET_CONFIG_FILE" -LOG_FILE="/logs/tron.log" +LOG_FILE="$BASE_DIR/logs/tron.log" JAVA_TRON_DOCKER_URL="https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker" @@ -387,7 +387,7 @@ rm_container() { log() { if docker_container_exists; then echo "container: $CONTAINER_NAME" - docker exec -it "$CONTAINER_NAME" tail -100f "$BASE_DIR/$LOG_FILE" + docker exec -it "$CONTAINER_NAME" tail -100f "$LOG_FILE" else echo "container not found: $CONTAINER_NAME" >&2 return 1 From 5b7b447c81fe895ea82b5c843b9b411a3dc87b34 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 21:48:01 +0800 Subject: [PATCH 10/35] docs(docker): refresh build and port guidance Use the architecture-aware build helper in the quickstart guide and publish the P2P port over both TCP and UDP. Clarify that docker.sh publishes default ports and remove the obsolete entrypoint ignore rule. --- .dockerignore | 2 -- docker/docker.md | 3 ++- quickstart.md | 19 +++++++++++++------ 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.dockerignore b/.dockerignore index d171944d877..57c53d50a15 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1 @@ ./* -!docker-entrypoint.sh - diff --git a/docker/docker.md b/docker/docker.md index 8e4db9b7536..b338e047eb1 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -23,7 +23,8 @@ $ bash docker.sh --pull ``` ### Run the service -Before running the java-tron service, make sure some ports on your local machine are open,the image has the following ports automatically exposed: +Before running the java-tron service, make sure the required ports are available on the host. +By default, `docker.sh --run` publishes the following container ports to the host: - `8090`: used by the HTTP based JSON API - `50051`: used by the GRPC based API - `18888`: TCP and UDP, used by the P2P protocol running the network diff --git a/quickstart.md b/quickstart.md index b3eeb7b7713..006c5028894 100644 --- a/quickstart.md +++ b/quickstart.md @@ -28,10 +28,10 @@ cd java-tron #### Build the docker image -Use the command below to navigate to the docker directory and start the build: +From the repository root, use the helper script to detect the Docker daemon architecture and select +the matching Dockerfile: ``` -cd docker -docker build -t tronprotocol/java-tron . +bash docker/docker.sh --build ``` #### Using the official Docker images @@ -45,14 +45,21 @@ docker pull tronprotocol/java-tron You can run the command below to start the java-tron: ``` -docker run -it -d -p 8090:8090 -p 18888:18888 -p 50051:50051 --restart always tronprotocol/java-tron +docker run -it -d \ + -p 8090:8090 \ + -p 18888:18888 \ + -p 18888:18888/udp \ + -p 50051:50051 \ + --restart always \ + tronprotocol/java-tron ``` The `-p` flag defines the ports that the container needs to be mapped on the host machine. By default the container will start and join in the mainnet using the built-in configuration file, you can specify other configuration file by mounting a directory and using the flag `-c`. This image also supports customizing some startup parameters,here is an example for running a FullNode as an SR in production env: ``` -docker run -it -d -p 8080:8080 -p 8090:8090 -p 18888:18888 -p 50051:50051 \ +docker run -it -d -p 8080:8080 -p 8090:8090 \ + -p 18888:18888 -p 18888:18888/udp -p 50051:50051 \ -v /Users/quan/tron/docker/conf:/java-tron/conf \ -v /Users/quan/tron/docker/datadir:/java-tron/data \ tronprotocol/java-tron \ @@ -61,7 +68,7 @@ docker run -it -d -p 8080:8080 -p 8090:8090 -p 18888:18888 -p 50051:50051 \ -d /java-tron/data \ -w ``` -Note: The directory `/Users/tron/docker/conf` must contain the file `config-localtest.conf`. The jvm parameters must be enclosed in double quotes and braces. +Note: The directory `/Users/quan/tron/docker/conf` must contain the file `config-localtest.conf`. The jvm parameters must be enclosed in double quotes and braces. ## Quickstart for using docker-tron-quickstart From 191d6e8c58638e03563755fd36cc1d7df11a013a Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 21:57:50 +0800 Subject: [PATCH 11/35] docs(docker): use helper script in quickstart Guide official FullNode users through docker.sh for image builds, pulls, startup, logs, and shutdown. Remove the obsolete SR example that referenced a deleted test configuration and user-specific paths. --- quickstart.md | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/quickstart.md b/quickstart.md index 006c5028894..74d787a6b76 100644 --- a/quickstart.md +++ b/quickstart.md @@ -16,7 +16,10 @@ Please download and install the latest Docker from Docker official website: ## Quickstart based on official tools -### Build the docker image from source +The official `docker.sh` helper manages image builds, pulls, container startup, ports, +configuration, logs, and lifecycle operations. + +### Build the Docker image from source #### Clone the java-tron repo @@ -26,7 +29,7 @@ git clone https://github.com/tronprotocol/java-tron.git cd java-tron ``` -#### Build the docker image +#### Build the Docker image From the repository root, use the helper script to detect the Docker daemon architecture and select the matching Dockerfile: @@ -34,41 +37,33 @@ the matching Dockerfile: bash docker/docker.sh --build ``` -#### Using the official Docker images +#### Use the official Docker image -Download the official docker image from the Dockerhub with below command if you'd like to use the official images: +Alternatively, pull the official image from Docker Hub: ``` -docker pull tronprotocol/java-tron +bash docker/docker.sh --pull ``` -### Run the container +### Run a FullNode -You can run the command below to start the java-tron: +Start a mainnet FullNode with the bundled configuration and default HTTP, gRPC, and P2P port +mappings: ``` -docker run -it -d \ - -p 8090:8090 \ - -p 18888:18888 \ - -p 18888:18888/udp \ - -p 50051:50051 \ - --restart always \ - tronprotocol/java-tron +bash docker/docker.sh --run ``` -The `-p` flag defines the ports that the container needs to be mapped on the host machine. By default the container will start and join in the mainnet -using the built-in configuration file, you can specify other configuration file by mounting a directory and using the flag `-c`. -This image also supports customizing some startup parameters,here is an example for running a FullNode as an SR in production env: +View its logs with the same helper: +``` +bash docker/docker.sh --log ``` -docker run -it -d -p 8080:8080 -p 8090:8090 \ - -p 18888:18888 -p 18888:18888/udp -p 50051:50051 \ - -v /Users/quan/tron/docker/conf:/java-tron/conf \ - -v /Users/quan/tron/docker/datadir:/java-tron/data \ - tronprotocol/java-tron \ - -jvm "{-Xmx10g -Xms10g}" \ - -c /java-tron/conf/config-localtest.conf \ - -d /java-tron/data \ - -w + +Stop the container when needed: ``` -Note: The directory `/Users/quan/tron/docker/conf` must contain the file `config-localtest.conf`. The jvm parameters must be enclosed in double quotes and braces. +bash docker/docker.sh --stop +``` + +For private networks, custom configuration files, custom port mappings, architecture selection, +and other lifecycle commands, see the [Docker Shell Guide](docker/docker.md). ## Quickstart for using docker-tron-quickstart From 803e5ff3e63e8642a6b9e2996ddaed8e4807715b Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 22:36:07 +0800 Subject: [PATCH 12/35] docs(quickstart): replace legacy Docker quickstart - replace docker-tron-quickstart with the maintained TRE workflow - document the official tron-docker multi-node private network setup - refresh Docker installation links and add development security guidance --- quickstart.md | 230 ++++++++++++++------------------------------------ 1 file changed, 63 insertions(+), 167 deletions(-) diff --git a/quickstart.md b/quickstart.md index 74d787a6b76..298a7264fd7 100644 --- a/quickstart.md +++ b/quickstart.md @@ -2,224 +2,120 @@ ## Introduction -This guide provides two ways for TRON quickstart: -- Set up a FullNode using the official tools: providing a wealth of configurable parameters to startup a FullNode -- Set up a complete private network for Tron development using a third-party tool: [docker-tron-quickstart](https://github.com/TRON-US/docker-tron-quickstart) +This guide covers three common ways to get started with TRON: + +- Run a mainnet FullNode with the official java-tron Docker helper. +- Start an isolated local development chain with + [TRON Runtime Environment (TRE)](https://hub.docker.com/r/tronbox/tre). +- Deploy a multi-node private network with the official + [tron-docker](https://github.com/tronprotocol/tron-docker/tree/main/private_net) configuration. ## Dependencies -### Docker +Install the latest Docker release for your platform: -Please download and install the latest Docker from Docker official website: -* Docker Installation for [Mac](https://docs.docker.com/docker-for-mac/install/) -* Docker Installation for [Windows](https://docs.docker.com/docker-for-windows/install/) +- [macOS](https://docs.docker.com/desktop/setup/install/mac-install/) +- [Windows](https://docs.docker.com/desktop/setup/install/windows-install/) +- [Linux](https://docs.docker.com/engine/install/) -## Quickstart based on official tools +## Run a mainnet FullNode The official `docker.sh` helper manages image builds, pulls, container startup, ports, configuration, logs, and lifecycle operations. ### Build the Docker image from source -#### Clone the java-tron repo +Clone the java-tron repository and enter its directory: -Clone the java-tron repo from github and enter the directory `java-tron`: -``` +```shell git clone https://github.com/tronprotocol/java-tron.git cd java-tron ``` -#### Build the Docker image +From the repository root, build the image. The helper detects the Docker daemon architecture and +selects the matching Dockerfile: -From the repository root, use the helper script to detect the Docker daemon architecture and select -the matching Dockerfile: -``` +```shell bash docker/docker.sh --build ``` -#### Use the official Docker image +### Use the official Docker image Alternatively, pull the official image from Docker Hub: -``` + +```shell bash docker/docker.sh --pull ``` -### Run a FullNode +### Start and manage the FullNode Start a mainnet FullNode with the bundled configuration and default HTTP, gRPC, and P2P port mappings: -``` + +```shell bash docker/docker.sh --run ``` -View its logs with the same helper: -``` +View its logs: + +```shell bash docker/docker.sh --log ``` -Stop the container when needed: -``` +Stop the container: + +```shell bash docker/docker.sh --stop ``` For private networks, custom configuration files, custom port mappings, architecture selection, and other lifecycle commands, see the [Docker Shell Guide](docker/docker.md). -## Quickstart for using docker-tron-quickstart +## Start a local development chain with TRE -The image exposes a Full Node and Event Server. Through TRON Quickstart, users can deploy DApps, smart contracts, and interact with the TronWeb library. +[TRE](https://hub.docker.com/r/tronbox/tre) is the maintained successor for local smart-contract +and DApp development. It provides a single-container development chain with funded test accounts, +automatic block production, and commonly used HTTP and event APIs on port `9090`. -> Note: `docker-tron-quickstart` is a community-maintained tool. Check its repository for the latest status: [Quickstart](https://github.com/TRON-US/docker-tron-quickstart) +Pull and run the current stable image: -### Node.JS Console - Node.JS is used to interact with the Full and Solidity Nodes via Tron-Web. - [Node.JS](https://nodejs.org/en/) Console Download - -### Clone TRON Quickstart ```shell -git clone https://github.com/TRON-US/docker-tron-quickstart.git -``` +docker pull tronbox/tre +docker run --rm \ + --name tron \ + -p 127.0.0.1:9090:9090 \ + -e useDefaultPrivateKey=true \ + tronbox/tre +``` -### Pull the image using docker: -```shell -docker pull trontools/quickstart -``` +Check that the environment is ready: -## Setup TRON Quickstart -### TRON Quickstart Run -Run the "docker run" command to launch TRON Quickstart. TRON Quickstart exposes port 9090 for Full Node and Event Server. ```shell -docker run -it \ - -p 9090:9090 \ - --rm \ - --name tron \ - trontools/quickstart -``` -Notice: the option --rm automatically removes the container after it exits. This is very important because the container cannot be restarted, it MUST be run from scratch to correctly configure the environment. - -### Testing - -If everything goes well, your terminal console output will look like following : -
- -Run Console Output - - - [PM2] Spawning PM2 daemon with pm2_home=/root/.pm2 - [PM2] PM2 Successfully daemonized - [PM2][WARN] Applications eventron not running, starting... - [PM2] App [eventron] launched (1 instances) - ┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐ - │ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem │ user │ watching │ - ├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤ - │ eventron │ 0 │ N/A │ fork │ 60 │ online │ 0 │ 0s │ 0% │ 25.4 MB │ root │ disabled │ - └──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘ - Use `pm2 show ` to get more details about an app - Start the http proxy for dApps... - [HPM] Proxy created: / -> http://127.0.0.1:18191 - [HPM] Proxy created: / -> http://127.0.0.1:18190 - [HPM] Proxy created: / -> http://127.0.0.1:8060 - - Tron Quickstart listening on http://127.0.0.1:9090 - - - - ADMIN /admin/accounts-generation - Sleeping for 1 second...Waiting when nodes are ready to generate 10 accounts... - (1) Waiting for sync... - Slept. - ... - Loading the accounts and waiting for the node to mine the transactions... - (1) Waiting for receipts... - Sending 10000 TRX to TSjfWSWcKCrJ1DbgMZSCbSqNK8DsEfqM9p - Sending 10000 TRX to THpWnj3dBQ5FrqW1KMVXXYSbHPtcBKeUJY - Sending 10000 TRX to TWFTHaKdeHWi3oPoaBokyZFfA7q1iiiAAb - Sending 10000 TRX to TFDGQo6f6dm9ikoV4Rc9NyTxMD5NNiSFJD - Sending 10000 TRX to TDZZNigWitFp5aE6j2j8YcycF7DVjtogBu - Sending 10000 TRX to TT8NRMcwdS9P3X9pvPC8JWi3x2zjwxZuhs - Sending 10000 TRX to TBBJw6Bk7w2NSZeqmzfUPnsn6CwDJAXTv8 - Sending 10000 TRX to TVcgSLpT97mvoiyv5ChyhQ6hWbjYLWdCVB - Sending 10000 TRX to TYjQd4xrLZQGYMdLJqsTCuXVGapPqUp9ZX - Sending 10000 TRX to THCw6hPZpFcLCWDcsZg3W77rXZ9rJQPncD - Sleeping for 3 seconds... Slept. - (2) Waiting for receipts... - Sleeping for 3 seconds... Slept. - (3) Waiting for receipts... - Sleeping for 3 seconds... Slept. - (4) Waiting for receipts... - Sleeping for 3 seconds... Slept. - (5) Waiting for receipts... - Sleeping for 3 seconds... Slept. - (6) Waiting for receipts... - Sleeping for 3 seconds... Slept. - (7) Waiting for receipts... - Done. - - Available Accounts - ================== - - (0) TSjfWSWcKCrJ1DbgMZSCbSqNK8DsEfqM9p (10000 TRX) - (1) THpWnj3dBQ5FrqW1KMVXXYSbHPtcBKeUJY (10000 TRX) - (2) TWFTHaKdeHWi3oPoaBokyZFfA7q1iiiAAb (10000 TRX) - (3) TFDGQo6f6dm9ikoV4Rc9NyTxMD5NNiSFJD (10000 TRX) - (4) TDZZNigWitFp5aE6j2j8YcycF7DVjtogBu (10000 TRX) - (5) TT8NRMcwdS9P3X9pvPC8JWi3x2zjwxZuhs (10000 TRX) - (6) TBBJw6Bk7w2NSZeqmzfUPnsn6CwDJAXTv8 (10000 TRX) - (7) TVcgSLpT97mvoiyv5ChyhQ6hWbjYLWdCVB (10000 TRX) - (8) TYjQd4xrLZQGYMdLJqsTCuXVGapPqUp9ZX (10000 TRX) - (9) THCw6hPZpFcLCWDcsZg3W77rXZ9rJQPncD (10000 TRX) - -
- - -### web browser ### -1. open your web browser -2. enter : http://127.0.0.1:9090/ -3. there will be a response JSON data: - -``` - {"Welcome to":"TronGrid v2.2.8"} +curl -fsS http://127.0.0.1:9090/healthcheck ``` -## Docker Commands -Here are some useful docker commands, which will help you manage the TRON Quickstart Docker container on your machine. +The default image tag follows the current stable release. Pin a versioned tag or image digest in +CI when reproducible builds are required. See the +[TronBox documentation](https://tronbox.io/docs/quickstart) for contract development and deployment +workflows. -**To list all active containers on your machine, run:** -```shell -docker container ps -``` -**Output:** -```shell -docker container ps +> **Warning:** TRE is intended only for isolated development and testing. The default private key, +> funded accounts, and administrative APIs are not secure. Keep port `9090` bound to localhost and +> never expose this environment to production or an untrusted network. -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -513078dc7816 tron "./quickstart v2.0.0" About an hour ago Up About an hour 0.0.0.0:9090->9090/tcp, 0.0.0.0:18190->18190/tcp tron -``` -**To kill an active container, run:** -```shell -docker container kill 513078dc7816 // use your container ID -``` +## Deploy a multi-node private network -### How to check the logs of the FullNode ### -``` - docker exec -it tron tail -f /tron/FullNode/logs/tron.log +Use the official `tron-docker/private_net` setup when testing P2P communication, consensus, node +operations, or workflows that require more than one java-tron process: + +```shell +git clone https://github.com/tronprotocol/tron-docker.git +cd tron-docker/private_net +docker compose up -d ``` -
- -Output: something like following - - ``` - number=204 - parentId=00000000000000cb0985978b3c780e4219dc51e4329beecabe7b71f99d269985 - witness address=41928c9af0651632157ef27a2cf17ca72c575a4d21 - generated by myself=true - generate time=2019-12-09 18:33:33.0 - txs are empty - ] - 18:33:33.008 INFO [Thread-5] [DB](Manager.java:1095) pushBlock block number:204, cost/txs:1/0 - 18:33:33.008 INFO [Thread-5] [witness](WitnessService.java:283) Produce block successfully, blockNumber:204, abSlot[525305471], blockId:00000000000000ccc37f1f5c2ceb574d14c490e3d0b86909855646f9384ba666, transactionSize:0, blockTime:2019-12-09T18:33:33.000Z, parentBlockId:00000000000000cb0985978b3c780e4219dc51e4329beecabe7b71f99d269985 - 18:33:33.008 INFO [Thread-5] [net](AdvService.java:156) Ready to broadcast block Num:204,ID:00000000000000ccc37f1f5c2ceb574d14c490e3d0b86909855646f9384ba666 - ........ etc - ``` -
+This setup starts a block-producing SR node and a regular FullNode. Its bundled genesis accounts, +keys, and configuration are suitable for local testing only. Review and replace them before using +the setup in a shared or security-sensitive environment. See the +[private network documentation](https://github.com/tronprotocol/tron-docker/tree/main/private_net) +for configuration and additional nodes. From 17afddd109e587dbf5df74e7ba760deeb2949143 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 23:39:29 +0800 Subject: [PATCH 13/35] docs(quickstart): expand Mainnet Docker guidance - replace the helper-led workflow with a flexible docker run example - add persistent data and log volumes with secure API port bindings - document architecture-specific JVM memory baselines - add FullNode and SR hardware, snapshot, and tuning requirements --- quickstart.md | 100 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 76 insertions(+), 24 deletions(-) diff --git a/quickstart.md b/quickstart.md index 298a7264fd7..29fb4075aa4 100644 --- a/quickstart.md +++ b/quickstart.md @@ -4,7 +4,7 @@ This guide covers three common ways to get started with TRON: -- Run a mainnet FullNode with the official java-tron Docker helper. +- Run a mainnet FullNode with the official java-tron Docker image. - Start an isolated local development chain with [TRON Runtime Environment (TRE)](https://hub.docker.com/r/tronbox/tre). - Deploy a multi-node private network with the official @@ -20,56 +20,108 @@ Install the latest Docker release for your platform: ## Run a mainnet FullNode -The official `docker.sh` helper manages image builds, pulls, container startup, ports, -configuration, logs, and lifecycle operations. - -### Build the Docker image from source - -Clone the java-tron repository and enter its directory: +Pull the official image from Docker Hub: ```shell -git clone https://github.com/tronprotocol/java-tron.git -cd java-tron +docker pull tronprotocol/java-tron:latest ``` -From the repository root, build the image. The helper detects the Docker daemon architecture and -selects the matching Dockerfile: +Create host directories for the blockchain database and application logs: ```shell -bash docker/docker.sh --build +mkdir -p output-directory logs ``` -### Use the official Docker image +Set JVM memory options for the architecture used by the Docker image. Run one of the following +commands: -Alternatively, pull the official image from Docker Hub: +```shell +# amd64 / JDK 8 +JAVA_TRON_JVM_OPTIONS="-Xms9G -Xmx12G -XX:MaxDirectMemorySize=1G" +``` ```shell -bash docker/docker.sh --pull +# ARM64 / JDK 17 +JAVA_TRON_JVM_OPTIONS="-Xmx9G -XX:MaxDirectMemorySize=1G" ``` -### Start and manage the FullNode +These baseline values follow the official guidance for a host with 16 GB of memory. For hosts with +32 GB or more, size the heap using the official [JVM tuning guide][jvm-guide] and leave sufficient +memory for direct buffers, native allocations, the operating system, and the database page cache. -Start a mainnet FullNode with the bundled configuration and default HTTP, gRPC, and P2P port -mappings: +Start the FullNode with the mainnet configuration bundled in the image: ```shell -bash docker/docker.sh --run +docker run -d \ + --name java-tron \ + --restart unless-stopped \ + -v "$(pwd)/output-directory:/java-tron/output-directory" \ + -v "$(pwd)/logs:/java-tron/logs" \ + -p 127.0.0.1:8090:8090 \ + -p 127.0.0.1:50051:50051 \ + -p 18888:18888 \ + -p 18888:18888/udp \ + tronprotocol/java-tron:latest \ + -jvm "{$JAVA_TRON_JVM_OPTIONS}" \ + -c /java-tron/config.conf ``` -View its logs: +The HTTP and gRPC APIs are bound to localhost by default, while the TCP and UDP P2P ports are +available to the network. Change the API bindings only when remote access is required, and protect +them with appropriate network controls. Pin a versioned image tag or digest for long-running or +reproducible deployments. The image also loads architecture-specific GC options from +`bin/java-tron.vmoptions`; do not copy JDK 8 GC options to an ARM64/JDK 17 deployment. + +View the FullNode log: ```shell -bash docker/docker.sh --log +docker exec -it java-tron tail -100f /java-tron/logs/tron.log ``` Stop the container: ```shell -bash docker/docker.sh --stop +docker stop java-tron ``` -For private networks, custom configuration files, custom port mappings, architecture selection, -and other lifecycle commands, see the [Docker Shell Guide](docker/docker.md). +The optional `docker.sh` helper provides shorter commands for image builds, private network +configuration, common port mappings, and lifecycle operations. See the +[Docker Shell Guide](docker/docker.md) for details. + +### Mainnet and SR requirements + +A Mainnet FullNode requires production-grade CPU, memory, SSD capacity, and network bandwidth. The +current official deployment requirements are: + +| Deployment | CPU | Memory | High-performance SSD | Network bandwidth | +| --- | ---: | ---: | ---: | ---: | +| Minimum FullNode | 8 cores | 16 GB | 3 TB | 100 Mbps | +| Recommended FullNode | 16 cores | 32 GB | 3.5 TB or more | 100 Mbps | +| Block-producing SR | 32 cores | 64 GB | 3.5 TB or more | 100 Mbps | + +The example above stores the database under `$(pwd)/output-directory`. Before starting it, ensure +that the current filesystem has sufficient high-performance SSD capacity, or replace the host side +of the volume mapping with a dedicated data disk. A new node otherwise synchronizes the full chain; +use a compatible [data snapshot][snapshot-guide] to reduce the initial synchronization time. +[Lite FullNode][lite-guide] deployments have different storage requirements and require the +corresponding Lite data and configuration. + +Review the official [java-tron deployment guide][deployment-guide] and +[JVM tuning guide][jvm-guide] before choosing JVM values, storage layout, snapshots, monitoring, +and upgrade procedures. + +Do not convert the quick-start container into a production Super Representative merely by adding +`--witness`. An SR requires stronger hardware, protected block-signing keys, an SR-specific +configuration, monitoring, backup, and operational failover. Follow the official +[block-production deployment guide][block-production-guide] and review the +[Super Representative requirements][sr-guide] before enabling block production. + +[deployment-guide]: https://tronprotocol.github.io/documentation-en/using_javatron/installing_javatron/ +[jvm-guide]: https://tronprotocol.github.io/documentation-en/using_javatron/installing_javatron/#jvm-parameter-optimization-for-mainnet-fullnode-deployment +[snapshot-guide]: https://tronprotocol.github.io/documentation-en/using_javatron/installing_javatron/#speeding-up-node-data-synchronization +[lite-guide]: https://tronprotocol.github.io/documentation-en/using_javatron/litefullnode/ +[block-production-guide]: https://tronprotocol.github.io/documentation-en/using_javatron/installing_javatron/#starting-a-block-production-node +[sr-guide]: https://tronprotocol.github.io/documentation-en/mechanism-algorithm/sr/ ## Start a local development chain with TRE From 891e64bc5d00d9cf9251aacd7982387f7840739c Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Fri, 28 Aug 2026 23:43:13 +0800 Subject: [PATCH 14/35] docs(docker): normalize guide formatting - use consistent paragraph, list, and heading spacing - improve docker helper descriptions and option wording - preserve existing quickstart commands and deployment guidance --- docker/docker.md | 103 ++++++++++++++++++++++------------------------- quickstart.md | 67 ++++++++---------------------- 2 files changed, 65 insertions(+), 105 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index b338e047eb1..fdbc162762e 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -1,32 +1,33 @@ # Docker Shell Guide -java-tron support containerized processes, we maintain a Docker image with latest version build from our master branch on DockerHub. To simplify the use of Docker and common docker commands, we also provide a shell script to help you better manage container services,this guide describes how to use the script tool. - +java-tron supports containerized processes. We maintain a Docker image built from the latest version of the `master` branch on Docker Hub. The `docker.sh` helper simplifies common image and container lifecycle operations. ## Prerequisites -Requires a docker to be installed on the system. Docker version >=20.10.12. - +Install Docker 20.10.12 or later before using the helper. ## Quick Start -Shell can be obtained from the java-tron project or independently, you can get the script from [here](https://github.com/tronprotocol/java-tron/blob/develop/docker/docker.sh) or download via the wget: +Obtain the helper from the java-tron repository, or download it independently: + ```shell $ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker/docker.sh ``` ### Pull the mirror image -Get the `tronprotocol/java-tron` image from Docker Hub. The image contains a Java runtime -environment and the mainnet configuration file, and the script provides common Docker operations. + +Get the `tronprotocol/java-tron` image from Docker Hub. The image contains a Java runtime environment and the mainnet configuration file. + ```shell $ bash docker.sh --pull ``` ### Run the service -Before running the java-tron service, make sure the required ports are available on the host. -By default, `docker.sh --run` publishes the following container ports to the host: -- `8090`: used by the HTTP based JSON API -- `50051`: used by the GRPC based API + +Before running java-tron, make sure the required ports are available on the host. By default, `docker.sh --run` publishes the following container ports: + +- `8090`: used by the HTTP-based JSON API +- `50051`: used by the gRPC-based API - `18888`: TCP and UDP, used by the P2P protocol running the network #### Full node on the main network @@ -34,12 +35,10 @@ By default, `docker.sh --run` publishes the following container ports to the hos ```shell $ bash docker.sh --run ``` -The mainnet configuration is bundled in the image at `/java-tron/config.conf` and comes from the -same java-tron revision used to build the image. `--net main` remains available as an explicit form. -You can use `-p` to customize the port mapping. Supplying any custom `-p` replaces the complete -default port set, so include both TCP and UDP mappings for P2P. For more custom parameters, see -[Options](#Options). +The mainnet configuration is bundled in the image at `/java-tron/config.conf` and comes from the same java-tron revision used to build the image. `--net main` remains available as an explicit form. + +Use `-p` to customize the port mapping. Supplying any custom `-p` replaces the complete default port set, so include both TCP and UDP mappings for P2P. For more parameters, see [Options](#options). ```shell $ bash docker.sh --run --net main \ @@ -50,28 +49,24 @@ $ bash docker.sh --run --net main \ ``` #### Full node on the private network -You can also run a private network with the configuration maintained by `tron-deployment`. -If `config/private_net_config.conf` does not exist in the current directory, the script downloads -it automatically. An existing local configuration is reused so that local changes are preserved. + +You can also run a private network with the configuration maintained by `tron-deployment`. If `config/private_net_config.conf` does not exist in the current directory, the script downloads it automatically. An existing local configuration is reused so that local changes are preserved. + ```shell $ bash docker.sh --run --net private ``` -To replace an existing local copy with the latest maintained configuration, explicitly request an -update. This overwrites `config/private_net_config.conf`. +To replace an existing local copy with the latest maintained configuration, explicitly request an update. This overwrites `config/private_net_config.conf`. ```shell $ bash docker.sh --run --net private --update-config true ``` #### Configuration -Mainnet uses the configuration bundled in the image and never downloads another configuration. -The `private` network option uses `config/private_net_config.conf` from the current directory, -downloading it from `tron-deployment` only when it is missing or an update is explicitly requested. -Nile is intentionally not supported by this script because it may require features that are not -yet available on the mainnet source revision. Follow the Nile-specific build instructions in the -project README instead. +Mainnet uses the configuration bundled in the image and never downloads another configuration. The `private` network option uses `config/private_net_config.conf` from the current directory, downloading it from `tron-deployment` only when it is missing or an update is explicitly requested. + +Nile is intentionally not supported by this script because it may require features that are not yet available on the mainnet source revision. Follow the Nile-specific build instructions in the project README instead. Alternatively, mount a configuration into the container and select it with `-c`: @@ -81,16 +76,17 @@ $ bash docker.sh --run \ -c /java-tron/custom.conf ``` - ### View logs -If you want to see the logs of the java-tron service, please use the `--log` parameter + +Use `--log` to follow the java-tron service log: ```shell $ bash docker.sh --log | grep 'PushBlock' ``` + ### Stop the service -If you want to stop the container of java-tron, you can execute +Use `--stop` to stop the java-tron container: ```shell $ bash docker.sh --stop @@ -98,10 +94,11 @@ $ bash docker.sh --stop ## Build Image -If you do not want to use the default official image, you can also compile your own local image, first you need to change some parameters in the shell script to specify your own mirror info. -`DOCKER_REPOSITORY` is your repository name -`DOCKER_IMAGES` is the image name -`DOCKER_TARGET` is the version number, here is an example: +To build an image with a custom name, change these variables in `docker.sh`: + +- `DOCKER_REPOSITORY`: repository name +- `DOCKER_IMAGES`: image name +- `DOCKER_TARGET`: image tag ```shell DOCKER_REPOSITORY="your_repository" @@ -109,38 +106,34 @@ DOCKER_IMAGES="java-tron" DOCKER_TARGET="1.0" ``` -then execute the build: +Then build the image: ```shell $ bash docker.sh --build ``` -The script detects the Docker daemon architecture by default. You can also select the target -architecture explicitly: +The script detects the Docker daemon architecture by default. You can also select the target architecture explicitly: ```shell $ bash docker.sh --build amd64 $ bash docker.sh --build arm64 ``` -When the script is used from a java-tron checkout, the Dockerfile and build context are resolved -relative to `docker.sh`, regardless of the current working directory. If only `docker.sh` was -downloaded, the required architecture-specific Dockerfile is downloaded into a temporary build -context and removed after the build. +When the script is used from a java-tron checkout, the Dockerfile and build context are resolved relative to `docker.sh`, regardless of the current working directory. If only `docker.sh` was downloaded, the required architecture-specific Dockerfile is downloaded into a temporary build context and removed after the build. ## Options -Parameters for all functions: - -* **`--build [amd64|arm64]`** building a local mirror image, optionally for the specified architecture -* **`--pull`** download a docker mirror from **DockerHub** -* **`--run`** run the docker mirror -* **`--start`** start the existing java-tron container -* **`--log`** exporting the java-tron run log on the container -* **`--stop`** stopping a running container -* **`--rm`** remove container,only deletes the container, not the image -* **`-p`** publish a container's port to the host, format: `-p hostPort:containerPort[/protocol]`; custom mappings replace all defaults -* **`-c`** specify other java-tron configuration file in the container -* **`-v`** bind mount a volume for the container,format: `-v host-src:container-dest`, the `host-src` is an absolute path -* **`--net`** select `main` or `private`; a missing private configuration is downloaded automatically -* **`--update-config`** set to `true` with `--net private` to replace the local private configuration +Parameters for all functions: + +- **`--build [amd64|arm64]`**: build a local image, optionally for the specified architecture +- **`--pull`**: download an image from Docker Hub +- **`--run`**: run the image +- **`--start`**: start the existing java-tron container +- **`--log`**: follow the java-tron log in the container +- **`--stop`**: stop the running container +- **`--rm`**: remove the container without removing the image +- **`-p`**: publish a container port using `-p hostPort:containerPort[/protocol]`; custom mappings replace all defaults +- **`-c`**: specify another java-tron configuration file in the container +- **`-v`**: bind mount a volume using `-v host-src:container-dest`; `host-src` must be an absolute path +- **`--net`**: select `main` or `private`; a missing private configuration is downloaded automatically +- **`--update-config`**: set to `true` with `--net private` to replace the local private configuration diff --git a/quickstart.md b/quickstart.md index 29fb4075aa4..335d957b06e 100644 --- a/quickstart.md +++ b/quickstart.md @@ -5,10 +5,8 @@ This guide covers three common ways to get started with TRON: - Run a mainnet FullNode with the official java-tron Docker image. -- Start an isolated local development chain with - [TRON Runtime Environment (TRE)](https://hub.docker.com/r/tronbox/tre). -- Deploy a multi-node private network with the official - [tron-docker](https://github.com/tronprotocol/tron-docker/tree/main/private_net) configuration. +- Start an isolated local development chain with [TRON Runtime Environment (TRE)](https://hub.docker.com/r/tronbox/tre). +- Deploy a multi-node private network with the official [tron-docker](https://github.com/tronprotocol/tron-docker/tree/main/private_net) configuration. ## Dependencies @@ -32,8 +30,7 @@ Create host directories for the blockchain database and application logs: mkdir -p output-directory logs ``` -Set JVM memory options for the architecture used by the Docker image. Run one of the following -commands: +Set JVM memory options for the architecture used by the Docker image. Run one of the following commands: ```shell # amd64 / JDK 8 @@ -45,9 +42,7 @@ JAVA_TRON_JVM_OPTIONS="-Xms9G -Xmx12G -XX:MaxDirectMemorySize=1G" JAVA_TRON_JVM_OPTIONS="-Xmx9G -XX:MaxDirectMemorySize=1G" ``` -These baseline values follow the official guidance for a host with 16 GB of memory. For hosts with -32 GB or more, size the heap using the official [JVM tuning guide][jvm-guide] and leave sufficient -memory for direct buffers, native allocations, the operating system, and the database page cache. +These baseline values follow the official guidance for a host with 16 GB of memory. For hosts with 32 GB or more, size the heap using the official [JVM tuning guide][jvm-guide] and leave sufficient memory for direct buffers, native allocations, the operating system, and the database page cache. Start the FullNode with the mainnet configuration bundled in the image: @@ -66,11 +61,7 @@ docker run -d \ -c /java-tron/config.conf ``` -The HTTP and gRPC APIs are bound to localhost by default, while the TCP and UDP P2P ports are -available to the network. Change the API bindings only when remote access is required, and protect -them with appropriate network controls. Pin a versioned image tag or digest for long-running or -reproducible deployments. The image also loads architecture-specific GC options from -`bin/java-tron.vmoptions`; do not copy JDK 8 GC options to an ARM64/JDK 17 deployment. +The HTTP and gRPC APIs are bound to localhost by default, while the TCP and UDP P2P ports are available to the network. Change the API bindings only when remote access is required, and protect them with appropriate network controls. Pin a versioned image tag or digest for long-running or reproducible deployments. The image also loads architecture-specific GC options from `bin/java-tron.vmoptions`; do not copy JDK 8 GC options to an ARM64/JDK 17 deployment. View the FullNode log: @@ -84,14 +75,11 @@ Stop the container: docker stop java-tron ``` -The optional `docker.sh` helper provides shorter commands for image builds, private network -configuration, common port mappings, and lifecycle operations. See the -[Docker Shell Guide](docker/docker.md) for details. +The optional `docker.sh` helper provides shorter commands for image builds, private network configuration, common port mappings, and lifecycle operations. See the [Docker Shell Guide](docker/docker.md) for details. ### Mainnet and SR requirements -A Mainnet FullNode requires production-grade CPU, memory, SSD capacity, and network bandwidth. The -current official deployment requirements are: +A Mainnet FullNode requires production-grade CPU, memory, SSD capacity, and network bandwidth. The current official deployment requirements are: | Deployment | CPU | Memory | High-performance SSD | Network bandwidth | | --- | ---: | ---: | ---: | ---: | @@ -99,22 +87,13 @@ current official deployment requirements are: | Recommended FullNode | 16 cores | 32 GB | 3.5 TB or more | 100 Mbps | | Block-producing SR | 32 cores | 64 GB | 3.5 TB or more | 100 Mbps | -The example above stores the database under `$(pwd)/output-directory`. Before starting it, ensure -that the current filesystem has sufficient high-performance SSD capacity, or replace the host side -of the volume mapping with a dedicated data disk. A new node otherwise synchronizes the full chain; -use a compatible [data snapshot][snapshot-guide] to reduce the initial synchronization time. -[Lite FullNode][lite-guide] deployments have different storage requirements and require the -corresponding Lite data and configuration. +The example above stores the database under `$(pwd)/output-directory`. Before starting it, ensure that the current filesystem has sufficient high-performance SSD capacity, or replace the host side of the volume mapping with a dedicated data disk. -Review the official [java-tron deployment guide][deployment-guide] and -[JVM tuning guide][jvm-guide] before choosing JVM values, storage layout, snapshots, monitoring, -and upgrade procedures. +A new node otherwise synchronizes the full chain; use a compatible [data snapshot][snapshot-guide] to reduce the initial synchronization time. [Lite FullNode][lite-guide] deployments have different storage requirements and require the corresponding Lite data and configuration. -Do not convert the quick-start container into a production Super Representative merely by adding -`--witness`. An SR requires stronger hardware, protected block-signing keys, an SR-specific -configuration, monitoring, backup, and operational failover. Follow the official -[block-production deployment guide][block-production-guide] and review the -[Super Representative requirements][sr-guide] before enabling block production. +Review the official [java-tron deployment guide][deployment-guide] and [JVM tuning guide][jvm-guide] before choosing JVM values, storage layout, snapshots, monitoring, and upgrade procedures. + +Do not convert the quick-start container into a production Super Representative merely by adding `--witness`. An SR requires stronger hardware, protected block-signing keys, an SR-specific configuration, monitoring, backup, and operational failover. Follow the official [block-production deployment guide][block-production-guide] and review the [Super Representative requirements][sr-guide] before enabling block production. [deployment-guide]: https://tronprotocol.github.io/documentation-en/using_javatron/installing_javatron/ [jvm-guide]: https://tronprotocol.github.io/documentation-en/using_javatron/installing_javatron/#jvm-parameter-optimization-for-mainnet-fullnode-deployment @@ -125,9 +104,7 @@ configuration, monitoring, backup, and operational failover. Follow the official ## Start a local development chain with TRE -[TRE](https://hub.docker.com/r/tronbox/tre) is the maintained successor for local smart-contract -and DApp development. It provides a single-container development chain with funded test accounts, -automatic block production, and commonly used HTTP and event APIs on port `9090`. +[TRE](https://hub.docker.com/r/tronbox/tre) is the maintained successor for local smart-contract and DApp development. It provides a single-container development chain with funded test accounts, automatic block production, and commonly used HTTP and event APIs on port `9090`. Pull and run the current stable image: @@ -146,19 +123,13 @@ Check that the environment is ready: curl -fsS http://127.0.0.1:9090/healthcheck ``` -The default image tag follows the current stable release. Pin a versioned tag or image digest in -CI when reproducible builds are required. See the -[TronBox documentation](https://tronbox.io/docs/quickstart) for contract development and deployment -workflows. +The default image tag follows the current stable release. Pin a versioned tag or image digest in CI when reproducible builds are required. See the [TronBox documentation](https://tronbox.io/docs/quickstart) for contract development and deployment workflows. -> **Warning:** TRE is intended only for isolated development and testing. The default private key, -> funded accounts, and administrative APIs are not secure. Keep port `9090` bound to localhost and -> never expose this environment to production or an untrusted network. +> **Warning:** TRE is intended only for isolated development and testing. The default private key, funded accounts, and administrative APIs are not secure. Keep port `9090` bound to localhost and never expose this environment to production or an untrusted network. ## Deploy a multi-node private network -Use the official `tron-docker/private_net` setup when testing P2P communication, consensus, node -operations, or workflows that require more than one java-tron process: +Use the official `tron-docker/private_net` setup when testing P2P communication, consensus, node operations, or workflows that require more than one java-tron process: ```shell git clone https://github.com/tronprotocol/tron-docker.git @@ -166,8 +137,4 @@ cd tron-docker/private_net docker compose up -d ``` -This setup starts a block-producing SR node and a regular FullNode. Its bundled genesis accounts, -keys, and configuration are suitable for local testing only. Review and replace them before using -the setup in a shared or security-sensitive environment. See the -[private network documentation](https://github.com/tronprotocol/tron-docker/tree/main/private_net) -for configuration and additional nodes. +This setup starts a block-producing SR node and a regular FullNode. Its bundled genesis accounts, keys, and configuration are suitable for local testing only. Review and replace them before using the setup in a shared or security-sensitive environment. See the [private network documentation](https://github.com/tronprotocol/tron-docker/tree/main/private_net) for configuration and additional nodes. From 242a98e3ac52f0301fd7a61147e04185233c0444 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 20:16:18 +0800 Subject: [PATCH 15/35] fix(docker): make private network mode runnable - align private network HTTP and P2P port mappings with its configuration - enable witness mode so the single-node private network produces blocks - document private mode ports, intended use, and security limitations --- docker/docker.md | 16 ++++++++++++---- docker/docker.sh | 28 ++++++++++++++++++++++------ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index fdbc162762e..b2940307474 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -24,7 +24,7 @@ $ bash docker.sh --pull ### Run the service -Before running java-tron, make sure the required ports are available on the host. By default, `docker.sh --run` publishes the following container ports: +Before running java-tron, make sure the required ports are available on the host. By default, `docker.sh --run` publishes the following mainnet container ports: - `8090`: used by the HTTP-based JSON API - `50051`: used by the gRPC-based API @@ -48,14 +48,22 @@ $ bash docker.sh --run --net main \ -p 18888:18888/udp ``` -#### Full node on the private network +#### Single-node private network -You can also run a private network with the configuration maintained by `tron-deployment`. If `config/private_net_config.conf` does not exist in the current directory, the script downloads it automatically. An existing local configuration is reused so that local changes are preserved. +You can also run a single-node private network with the configuration maintained by `tron-deployment`. If `config/private_net_config.conf` does not exist in the current directory, the script downloads it automatically. An existing local configuration is reused so that local changes are preserved. ```shell $ bash docker.sh --run --net private ``` +Private mode starts FullNode with `--witness` so that the genesis witness produces blocks. Its default ports match `private_net_config.conf`: + +- `16667`: used by the HTTP-based JSON API +- `50051`: used by the gRPC-based API +- `16666`: TCP and UDP, used by the private P2P network + +The downloaded configuration contains a publicly known development witness key and genesis accounts. Use it only for isolated local development. For a multi-node, shared, or security-sensitive private network, use the maintained [`tron-docker/private_net`](https://github.com/tronprotocol/tron-docker/tree/main/private_net) setup and replace its keys and configuration as appropriate. + To replace an existing local copy with the latest maintained configuration, explicitly request an update. This overwrites `config/private_net_config.conf`. ```shell @@ -64,7 +72,7 @@ $ bash docker.sh --run --net private --update-config true #### Configuration -Mainnet uses the configuration bundled in the image and never downloads another configuration. The `private` network option uses `config/private_net_config.conf` from the current directory, downloading it from `tron-deployment` only when it is missing or an update is explicitly requested. +Mainnet uses the configuration bundled in the image and never downloads another configuration. The `private` network option uses `config/private_net_config.conf` from the current directory, downloading it from `tron-deployment` only when it is missing or an update is explicitly requested. It also enables witness mode so that the single-node network can produce blocks. Nile is intentionally not supported by this script because it may require features that are not yet available on the mainnet source revision. Follow the Nile-specific build instructions in the project README instead. diff --git a/docker/docker.sh b/docker/docker.sh index ac7b438b7e8..ad45f2cb578 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -34,6 +34,9 @@ DOCKER_HTTP_PORT=8090 DOCKER_RPC_PORT=50051 DOCKER_LISTEN_PORT=18888 +PRIVATE_HTTP_PORT=16667 +PRIVATE_LISTEN_PORT=16666 + VOLUME=`pwd` CONFIG_DIR="$VOLUME/config" OUTPUT_DIRECTORY="$VOLUME/output-directory" @@ -253,18 +256,31 @@ run() { fi if [[ ${#port_args[@]} -eq 0 ]]; then - port_args=( - -p "$HOST_HTTP_PORT:$DOCKER_HTTP_PORT" - -p "$HOST_RPC_PORT:$DOCKER_RPC_PORT" - -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT" - -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp" - ) + if [[ "$network" = "private" ]]; then + port_args=( + -p "$PRIVATE_HTTP_PORT:$PRIVATE_HTTP_PORT" + -p "$HOST_RPC_PORT:$DOCKER_RPC_PORT" + -p "$PRIVATE_LISTEN_PORT:$PRIVATE_LISTEN_PORT" + -p "$PRIVATE_LISTEN_PORT:$PRIVATE_LISTEN_PORT/udp" + ) + else + port_args=( + -p "$HOST_HTTP_PORT:$DOCKER_HTTP_PORT" + -p "$HOST_RPC_PORT:$DOCKER_RPC_PORT" + -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT" + -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp" + ) + fi fi if [[ ${#tron_args[@]} -eq 0 ]]; then tron_args=(-c "$BUNDLED_CONFIG_FILE") fi + if [[ "$network" = "private" ]]; then + tron_args+=(--witness) + fi + docker run -d -it --name "$CONTAINER_NAME" \ "${volume_args[@]}" \ "${port_args[@]}" \ From 08f44e850912f1e7cfd01fa67a60e1c7a4acfc22 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 20:19:28 +0800 Subject: [PATCH 16/35] fix(docker): bind API ports to localhost by default - bind mainnet and private HTTP and gRPC ports to the loopback interface - keep P2P TCP and UDP ports available on all host interfaces - update Docker documentation and custom port examples --- docker/docker.md | 18 +++++++++--------- docker/docker.sh | 9 +++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index b2940307474..141503fb0ae 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -24,11 +24,11 @@ $ bash docker.sh --pull ### Run the service -Before running java-tron, make sure the required ports are available on the host. By default, `docker.sh --run` publishes the following mainnet container ports: +Before running java-tron, make sure the required ports are available on the host. By default, HTTP and gRPC APIs are bound to the host loopback interface, while the P2P port is available on all host interfaces. Mainnet uses: -- `8090`: used by the HTTP-based JSON API -- `50051`: used by the gRPC-based API -- `18888`: TCP and UDP, used by the P2P protocol running the network +- `127.0.0.1:8090`: used by the HTTP-based JSON API +- `127.0.0.1:50051`: used by the gRPC-based API +- `18888`: TCP and UDP on all host interfaces, used by the P2P protocol #### Full node on the main network @@ -42,8 +42,8 @@ Use `-p` to customize the port mapping. Supplying any custom `-p` replaces the c ```shell $ bash docker.sh --run --net main \ - -p 8080:8090 \ - -p 40051:50051 \ + -p 127.0.0.1:8080:8090 \ + -p 127.0.0.1:40051:50051 \ -p 18888:18888 \ -p 18888:18888/udp ``` @@ -58,9 +58,9 @@ $ bash docker.sh --run --net private Private mode starts FullNode with `--witness` so that the genesis witness produces blocks. Its default ports match `private_net_config.conf`: -- `16667`: used by the HTTP-based JSON API -- `50051`: used by the gRPC-based API -- `16666`: TCP and UDP, used by the private P2P network +- `127.0.0.1:16667`: used by the HTTP-based JSON API +- `127.0.0.1:50051`: used by the gRPC-based API +- `16666`: TCP and UDP on all host interfaces, used by the private P2P network The downloaded configuration contains a publicly known development witness key and genesis accounts. Use it only for isolated local development. For a multi-node, shared, or security-sensitive private network, use the maintained [`tron-docker/private_net`](https://github.com/tronprotocol/tron-docker/tree/main/private_net) setup and replace its keys and configuration as appropriate. diff --git a/docker/docker.sh b/docker/docker.sh index ad45f2cb578..6dc468efb1d 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -26,6 +26,7 @@ DOCKER_TARGET="latest" CONTAINER_NAME="$DOCKER_REPOSITORY-$DOCKER_IMAGES" IMAGE_REFERENCE="$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" +HOST_API_BIND_ADDRESS="127.0.0.1" HOST_HTTP_PORT=8090 HOST_RPC_PORT=50051 HOST_LISTEN_PORT=18888 @@ -258,15 +259,15 @@ run() { if [[ ${#port_args[@]} -eq 0 ]]; then if [[ "$network" = "private" ]]; then port_args=( - -p "$PRIVATE_HTTP_PORT:$PRIVATE_HTTP_PORT" - -p "$HOST_RPC_PORT:$DOCKER_RPC_PORT" + -p "$HOST_API_BIND_ADDRESS:$PRIVATE_HTTP_PORT:$PRIVATE_HTTP_PORT" + -p "$HOST_API_BIND_ADDRESS:$HOST_RPC_PORT:$DOCKER_RPC_PORT" -p "$PRIVATE_LISTEN_PORT:$PRIVATE_LISTEN_PORT" -p "$PRIVATE_LISTEN_PORT:$PRIVATE_LISTEN_PORT/udp" ) else port_args=( - -p "$HOST_HTTP_PORT:$DOCKER_HTTP_PORT" - -p "$HOST_RPC_PORT:$DOCKER_RPC_PORT" + -p "$HOST_API_BIND_ADDRESS:$HOST_HTTP_PORT:$DOCKER_HTTP_PORT" + -p "$HOST_API_BIND_ADDRESS:$HOST_RPC_PORT:$DOCKER_RPC_PORT" -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT" -p "$HOST_LISTEN_PORT:$DOCKER_LISTEN_PORT/udp" ) From 16aad9e7ebe5394821a2698485b5b1a8c6be9028 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:05:25 +0800 Subject: [PATCH 17/35] docs(docker): clarify data and log persistence - document the default host location for blockchain data - explain how to use dedicated directories for different networks - clarify that container logs are not persisted by default - provide volume examples for database and log persistence --- docker/docker.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docker/docker.md b/docker/docker.md index 141503fb0ae..ff5957ff481 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -84,6 +84,28 @@ $ bash docker.sh --run \ -c /java-tron/custom.conf ``` +### Data and log persistence + +By default, the helper bind-mounts `output-directory` from the directory where `docker.sh` is executed to `/java-tron/output-directory` in the container. The blockchain database therefore remains on the host after the container is removed. Make sure that the current filesystem has sufficient space, or mount a dedicated data directory: + +```shell +$ mkdir -p "$PWD/mainnet-data" +$ bash docker.sh --run --net main \ + -v "$PWD/mainnet-data:/java-tron/output-directory" +``` + +Do not reuse one database directory across different networks. Use separate directories for mainnet and private-network data. + +Application logs are not persisted by default; they remain in the container writable layer and are deleted with the container. To retain logs after `--rm`, mount a host directory explicitly: + +```shell +$ mkdir -p "$PWD/logs" +$ bash docker.sh --run --net main \ + -v "$PWD/logs:/java-tron/logs" +``` + +Adding a log or configuration volume does not disable the default database mount. The default is replaced only when a custom volume targets `/java-tron/output-directory`. + ### View logs Use `--log` to follow the java-tron service log: From 8ce66a324ce737332616b2685f7bdeebda0699b9 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:13:28 +0800 Subject: [PATCH 18/35] docs(docker): clarify image source and tag semantics - distinguish published release images from remote master builds - explain that latest is a mutable release tag - clarify that local builds do not use the current checkout - document output tag behavior and local image replacement risk --- docker/docker.md | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index ff5957ff481..18518b39c5c 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -1,6 +1,6 @@ # Docker Shell Guide -java-tron supports containerized processes. We maintain a Docker image built from the latest version of the `master` branch on Docker Hub. The `docker.sh` helper simplifies common image and container lifecycle operations. +java-tron supports containerized processes. Official versioned release images are published on Docker Hub. The mutable `latest` tag points to the latest published release; it does not represent the current head of `master`. The `docker.sh` helper simplifies common image and container lifecycle operations. ## Prerequisites @@ -14,9 +14,9 @@ Obtain the helper from the java-tron repository, or download it independently: $ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker/docker.sh ``` -### Pull the mirror image +### Pull the official image -Get the `tronprotocol/java-tron` image from Docker Hub. The image contains a Java runtime environment and the mainnet configuration file. +Get the `tronprotocol/java-tron` image from Docker Hub. The image contains a Java runtime environment and the mainnet configuration file. The helper pulls `latest` by default. For long-running or reproducible deployments, set `DOCKER_TARGET` to a versioned tag; use Docker directly with an `image@sha256:...` reference when pinning a digest. See the available [Docker Hub tags](https://hub.docker.com/r/tronprotocol/java-tron/tags). ```shell $ bash docker.sh --pull @@ -124,16 +124,20 @@ $ bash docker.sh --stop ## Build Image -To build an image with a custom name, change these variables in `docker.sh`: +The Dockerfiles clone the remote java-tron repository and check out `master` at build time. They do not build the Java sources in the current checkout. Each local build therefore follows the state of `master` at that moment and can differ from the published Docker Hub `latest` image. + +By default, `--build` tags the result as the same `tronprotocol/java-tron:latest` reference used by `--pull` and `--run`. This moves the local tag to the newly built `master` image, so a subsequent `--run` uses that local build. Change the output image reference before building if the pulled release image must remain distinguishable. + +The following variables control only the output image reference; they do not select the java-tron source revision. In particular, assigning a release-like value to `DOCKER_TARGET` does not make the Dockerfile check out that release. - `DOCKER_REPOSITORY`: repository name - `DOCKER_IMAGES`: image name - `DOCKER_TARGET`: image tag ```shell -DOCKER_REPOSITORY="your_repository" +DOCKER_REPOSITORY="local" DOCKER_IMAGES="java-tron" -DOCKER_TARGET="1.0" +DOCKER_TARGET="master" ``` Then build the image: @@ -149,14 +153,14 @@ $ bash docker.sh --build amd64 $ bash docker.sh --build arm64 ``` -When the script is used from a java-tron checkout, the Dockerfile and build context are resolved relative to `docker.sh`, regardless of the current working directory. If only `docker.sh` was downloaded, the required architecture-specific Dockerfile is downloaded into a temporary build context and removed after the build. +When the script is used from a java-tron checkout, only the Dockerfile and build context are resolved relative to `docker.sh`, regardless of the current working directory. The current checkout's Java sources are not added to that context. If only `docker.sh` was downloaded, the required architecture-specific Dockerfile is downloaded into a temporary build context and removed after the build. Both paths build the remote `master` branch. ## Options Parameters for all functions: -- **`--build [amd64|arm64]`**: build a local image, optionally for the specified architecture -- **`--pull`**: download an image from Docker Hub +- **`--build [amd64|arm64]`**: build a local image from the remote `master` branch, optionally for the specified architecture +- **`--pull`**: download the configured image reference from Docker Hub; the default tag is `latest` - **`--run`**: run the image - **`--start`**: start the existing java-tron container - **`--log`**: follow the java-tron log in the container From 76edc6f1d0adf580b16abca0f28443465bdd6bb6 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:16:44 +0800 Subject: [PATCH 19/35] docs(docker): clarify Windows shell requirements - recommend Docker Desktop with Linux containers and WSL 2 - clarify that command examples require POSIX shell syntax - note that docker.sh cannot run directly in PowerShell or Command Prompt --- docker/docker.md | 2 ++ quickstart.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/docker/docker.md b/docker/docker.md index 18518b39c5c..56d69cad110 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -6,6 +6,8 @@ java-tron supports containerized processes. Official versioned release images ar Install Docker 20.10.12 or later before using the helper. +`docker.sh` requires Bash. On Windows, use Docker Desktop with Linux containers and run the helper from [WSL 2](https://docs.docker.com/desktop/features/wsl/) with Docker integration enabled. It cannot be executed directly from PowerShell or Command Prompt. + ## Quick Start Obtain the helper from the java-tron repository, or download it independently: diff --git a/quickstart.md b/quickstart.md index 335d957b06e..664fcf9dc3b 100644 --- a/quickstart.md +++ b/quickstart.md @@ -16,6 +16,8 @@ Install the latest Docker release for your platform: - [Windows](https://docs.docker.com/desktop/setup/install/windows-install/) - [Linux](https://docs.docker.com/engine/install/) +All commands in this guide use POSIX shell syntax. On Windows, use Docker Desktop with Linux containers and run the commands from [WSL 2](https://docs.docker.com/desktop/features/wsl/) with Docker integration enabled. The examples are not intended for native PowerShell or Command Prompt. + ## Run a mainnet FullNode Pull the official image from Docker Hub: From 7cd4fbf8368238c0206e8d52b9c4d6fd5f4e0773 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:23:08 +0800 Subject: [PATCH 20/35] docs: simplify private network quickstart guidance - remove duplicated private network deployment commands - direct users to the official tron-docker private network guide --- quickstart.md | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/quickstart.md b/quickstart.md index 664fcf9dc3b..f678f3208e4 100644 --- a/quickstart.md +++ b/quickstart.md @@ -131,12 +131,4 @@ The default image tag follows the current stable release. Pin a versioned tag or ## Deploy a multi-node private network -Use the official `tron-docker/private_net` setup when testing P2P communication, consensus, node operations, or workflows that require more than one java-tron process: - -```shell -git clone https://github.com/tronprotocol/tron-docker.git -cd tron-docker/private_net -docker compose up -d -``` - -This setup starts a block-producing SR node and a regular FullNode. Its bundled genesis accounts, keys, and configuration are suitable for local testing only. Review and replace them before using the setup in a shared or security-sensitive environment. See the [private network documentation](https://github.com/tronprotocol/tron-docker/tree/main/private_net) for configuration and additional nodes. +For multi-node private network deployment, follow the official [tron-docker private network guide](https://github.com/tronprotocol/tron-docker/tree/main/private_net). From c1b17750b9259bc7ba7c164366f0e1eb9ab4f489 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:27:35 +0800 Subject: [PATCH 21/35] chore(docker): address shellcheck style warnings - replace legacy command substitution with modern syntax - preserve backslashes and whitespace when reading user input --- docker/docker.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/docker.sh b/docker/docker.sh index 6dc468efb1d..3ea938108b6 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -38,7 +38,7 @@ DOCKER_LISTEN_PORT=18888 PRIVATE_HTTP_PORT=16667 PRIVATE_LISTEN_PORT=16666 -VOLUME=`pwd` +VOLUME=$(pwd) CONFIG_DIR="$VOLUME/config" OUTPUT_DIRECTORY="$VOLUME/output-directory" @@ -166,7 +166,7 @@ run() { if ! docker_image_exists; then echo 'warning: no java-tron mirror image, do you need to get the mirror image?[y/n]' - read need + IFS= read -r need if [[ $need == 'y' || $need == 'yes' ]]; then pull || return $? From e86eb63dd949e90b4a0906cc6b6310cad46b56ff Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:31:11 +0800 Subject: [PATCH 22/35] fix(docker): remove interactive flags from detached runs - avoid allocating stdin and a TTY for background FullNode containers - document the fixed container name and single-instance limitation - clarify the default always restart policy --- docker/docker.md | 2 ++ docker/docker.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docker/docker.md b/docker/docker.md index 56d69cad110..ea9fb1e382e 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -32,6 +32,8 @@ Before running java-tron, make sure the required ports are available on the host - `127.0.0.1:50051`: used by the gRPC-based API - `18888`: TCP and UDP on all host interfaces, used by the P2P protocol +The helper manages one container named `tronprotocol-java-tron` and creates it with Docker's `always` restart policy. It cannot run mainnet and private-network instances simultaneously; use `--rm` to remove the existing container before switching networks. A manually stopped container remains stopped until it is manually restarted or the Docker daemon restarts. Use Docker directly when multiple instances, a custom container name, or a different restart policy is required. + #### Full node on the main network ```shell diff --git a/docker/docker.sh b/docker/docker.sh index 3ea938108b6..f1c39ab8e2b 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -282,7 +282,7 @@ run() { tron_args+=(--witness) fi - docker run -d -it --name "$CONTAINER_NAME" \ + docker run -d --name "$CONTAINER_NAME" \ "${volume_args[@]}" \ "${port_args[@]}" \ --restart always \ From 450b94b8c02b5d6856816a6a622cb088e12534cd Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:47:26 +0800 Subject: [PATCH 23/35] fix(docker): avoid TTY allocation when following logs - remove interactive TTY flags from the docker log helper - update the quickstart log command for piped and non-interactive use --- docker/docker.sh | 2 +- quickstart.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/docker.sh b/docker/docker.sh index f1c39ab8e2b..80c0894a4e0 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -404,7 +404,7 @@ rm_container() { log() { if docker_container_exists; then echo "container: $CONTAINER_NAME" - docker exec -it "$CONTAINER_NAME" tail -100f "$LOG_FILE" + docker exec "$CONTAINER_NAME" tail -100f "$LOG_FILE" else echo "container not found: $CONTAINER_NAME" >&2 return 1 diff --git a/quickstart.md b/quickstart.md index f678f3208e4..657b7e28ffe 100644 --- a/quickstart.md +++ b/quickstart.md @@ -68,7 +68,7 @@ The HTTP and gRPC APIs are bound to localhost by default, while the TCP and UDP View the FullNode log: ```shell -docker exec -it java-tron tail -100f /java-tron/logs/tron.log +docker exec java-tron tail -100f /java-tron/logs/tron.log ``` Stop the container: From 05dac05e3f5071cf02dc3d70770e5d79e9d562d0 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:49:57 +0800 Subject: [PATCH 24/35] docs: clarify Docker container lifecycle in quickstart - document how to restart a stopped FullNode container - explain container removal before changing images or configuration - clarify that bind-mounted data and logs remain on the host --- quickstart.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/quickstart.md b/quickstart.md index 657b7e28ffe..c64f631b24f 100644 --- a/quickstart.md +++ b/quickstart.md @@ -77,6 +77,20 @@ Stop the container: docker stop java-tron ``` +Restart the stopped container: + +```shell +docker start java-tron +``` + +To recreate the container with a different image or configuration, remove the stopped container first: + +```shell +docker rm java-tron +``` + +The bind-mounted database and logs remain on the host after the container is removed. + The optional `docker.sh` helper provides shorter commands for image builds, private network configuration, common port mappings, and lifecycle operations. See the [Docker Shell Guide](docker/docker.md) for details. ### Mainnet and SR requirements From f467b2cea30548ad20a80ff7e9704171ffd4be47 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Sat, 29 Aug 2026 21:59:15 +0800 Subject: [PATCH 25/35] docs(docker): clarify the helper image reference - remove unsupported image variable configuration examples - document the fixed image used by pull, build, and run - direct custom tags, digests, and image names to Docker --- docker/docker.md | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index ea9fb1e382e..83f55a91a9c 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -18,7 +18,7 @@ $ wget https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker/d ### Pull the official image -Get the `tronprotocol/java-tron` image from Docker Hub. The image contains a Java runtime environment and the mainnet configuration file. The helper pulls `latest` by default. For long-running or reproducible deployments, set `DOCKER_TARGET` to a versioned tag; use Docker directly with an `image@sha256:...` reference when pinning a digest. See the available [Docker Hub tags](https://hub.docker.com/r/tronprotocol/java-tron/tags). +Get the `tronprotocol/java-tron` image from Docker Hub. The image contains a Java runtime environment and the mainnet configuration file. The helper pulls `tronprotocol/java-tron:latest`. For long-running or reproducible deployments, use Docker directly to select a versioned tag or an `image@sha256:...` reference. See the available [Docker Hub tags](https://hub.docker.com/r/tronprotocol/java-tron/tags). ```shell $ bash docker.sh --pull @@ -130,19 +130,7 @@ $ bash docker.sh --stop The Dockerfiles clone the remote java-tron repository and check out `master` at build time. They do not build the Java sources in the current checkout. Each local build therefore follows the state of `master` at that moment and can differ from the published Docker Hub `latest` image. -By default, `--build` tags the result as the same `tronprotocol/java-tron:latest` reference used by `--pull` and `--run`. This moves the local tag to the newly built `master` image, so a subsequent `--run` uses that local build. Change the output image reference before building if the pulled release image must remain distinguishable. - -The following variables control only the output image reference; they do not select the java-tron source revision. In particular, assigning a release-like value to `DOCKER_TARGET` does not make the Dockerfile check out that release. - -- `DOCKER_REPOSITORY`: repository name -- `DOCKER_IMAGES`: image name -- `DOCKER_TARGET`: image tag - -```shell -DOCKER_REPOSITORY="local" -DOCKER_IMAGES="java-tron" -DOCKER_TARGET="master" -``` +The helper uses `tronprotocol/java-tron:latest` for `--pull`, `--build`, and `--run` and does not support selecting another image reference through command-line options or environment variables. After `--build`, the local `tronprotocol/java-tron:latest` tag points to the newly built `master` image, so subsequent `--run` commands use that build. Use Docker directly when a separate tag, digest, or image name is required. Then build the image: @@ -163,9 +151,9 @@ When the script is used from a java-tron checkout, only the Dockerfile and build Parameters for all functions: -- **`--build [amd64|arm64]`**: build a local image from the remote `master` branch, optionally for the specified architecture -- **`--pull`**: download the configured image reference from Docker Hub; the default tag is `latest` -- **`--run`**: run the image +- **`--build [amd64|arm64]`**: build `tronprotocol/java-tron:latest` from the remote `master` branch, optionally for the specified architecture +- **`--pull`**: download `tronprotocol/java-tron:latest` from Docker Hub +- **`--run`**: run `tronprotocol/java-tron:latest` - **`--start`**: start the existing java-tron container - **`--log`**: follow the java-tron log in the container - **`--stop`**: stop the running container From aa1cf840f4d4626e67e1af46299bb130520706b7 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 11:33:24 +0800 Subject: [PATCH 26/35] docs(docker): clarify build requirements and option scopes - document emulation requirements for cross-architecture builds - separate docker.sh commands from --run-specific options --- docker/docker.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/docker/docker.md b/docker/docker.md index 83f55a91a9c..ba03cd18822 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -145,11 +145,13 @@ $ bash docker.sh --build amd64 $ bash docker.sh --build arm64 ``` +Building for an architecture different from the Docker daemon requires a builder with the corresponding emulation support. Docker Desktop provides this by default; standalone Docker Engine installations may require QEMU/binfmt configuration. + When the script is used from a java-tron checkout, only the Dockerfile and build context are resolved relative to `docker.sh`, regardless of the current working directory. The current checkout's Java sources are not added to that context. If only `docker.sh` was downloaded, the required architecture-specific Dockerfile is downloaded into a temporary build context and removed after the build. Both paths build the remote `master` branch. ## Options -Parameters for all functions: +### Commands - **`--build [amd64|arm64]`**: build `tronprotocol/java-tron:latest` from the remote `master` branch, optionally for the specified architecture - **`--pull`**: download `tronprotocol/java-tron:latest` from Docker Hub @@ -158,6 +160,11 @@ Parameters for all functions: - **`--log`**: follow the java-tron log in the container - **`--stop`**: stop the running container - **`--rm`**: remove the container without removing the image + +### Run options + +The following options apply only to `--run`: + - **`-p`**: publish a container port using `-p hostPort:containerPort[/protocol]`; custom mappings replace all defaults - **`-c`**: specify another java-tron configuration file in the container - **`-v`**: bind mount a volume using `-v host-src:container-dest`; `host-src` must be an absolute path From fa0fa40fd359d03dfd6d2b2a9e25182300f16c0a Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 11:52:36 +0800 Subject: [PATCH 27/35] docs(docker): clarify JVM tuning limitations - document that docker.sh uses the image and JVM default settings - direct production deployments to the JVM-tuned docker run example --- docker/docker.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docker/docker.md b/docker/docker.md index ba03cd18822..aa84483a7bf 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -40,6 +40,8 @@ The helper manages one container named `tronprotocol-java-tron` and creates it w $ bash docker.sh --run ``` +The helper does not provide an option for setting JVM heap parameters. Nodes started this way use the JVM options bundled in the image and the JVM's automatically selected heap size. For production mainnet deployments that require explicit heap sizing or other JVM tuning, use the direct `docker run` example in the [quick-start guide](../quickstart.md#run-a-mainnet-fullnode). + The mainnet configuration is bundled in the image at `/java-tron/config.conf` and comes from the same java-tron revision used to build the image. `--net main` remains available as an explicit form. Use `-p` to customize the port mapping. Supplying any custom `-p` replaces the complete default port set, so include both TCP and UDP mappings for P2P. For more parameters, see [Options](#options). From fc257c9257a19f85295d28d2e810a2ea1e55b62a Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 12:49:01 +0800 Subject: [PATCH 28/35] ci(docker): add lightweight static checks - validate docker.sh syntax and run ShellCheck - check amd64 and ARM64 Dockerfiles without building images - run only when Docker-related files change --- .github/workflows/docker-check.yml | 50 ++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 .github/workflows/docker-check.yml diff --git a/.github/workflows/docker-check.yml b/.github/workflows/docker-check.yml new file mode 100644 index 00000000000..d0d558e1018 --- /dev/null +++ b/.github/workflows/docker-check.yml @@ -0,0 +1,50 @@ +name: Docker Check + +on: + pull_request: + branches: [ 'master', 'develop', 'release_**' ] + paths: + - 'docker/docker.sh' + - 'docker/Dockerfile' + - 'docker/arm64/Dockerfile' + - 'docker/tests/**' + - '.github/workflows/docker-check.yml' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + docker-check: + name: Docker Static Check + runs-on: ubuntu-24.04 + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v5 + + - name: Check shell syntax + run: bash -n docker/docker.sh + + - name: Run ShellCheck + run: shellcheck docker/docker.sh + + - name: Check amd64 Dockerfile + run: > + docker buildx build + --check + --platform linux/amd64 + --file docker/Dockerfile + docker + + - name: Check ARM64 Dockerfile + run: > + docker buildx build + --check + --platform linux/arm64 + --file docker/arm64/Dockerfile + docker From edd9f43d644c3ca9e0d00ef0f2a9a91504b02cee Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 13:24:25 +0800 Subject: [PATCH 29/35] fix(docker): validate helper commands and expand CI coverage - reject unexpected arguments for pull, start, stop, log, and rm - add mock-based tests for mainnet and private network run behavior - cover config download, reuse, update, failure, and wget fallback - run Docker behavior tests on PRs and direct release branch pushes --- .github/workflows/docker-check.yml | 15 +- docker/docker.sh | 20 ++ docker/tests/docker-sh-test.sh | 325 +++++++++++++++++++++++++++++ 3 files changed, 358 insertions(+), 2 deletions(-) create mode 100644 docker/tests/docker-sh-test.sh diff --git a/.github/workflows/docker-check.yml b/.github/workflows/docker-check.yml index d0d558e1018..b4950dc100e 100644 --- a/.github/workflows/docker-check.yml +++ b/.github/workflows/docker-check.yml @@ -1,6 +1,14 @@ name: Docker Check on: + push: + branches: [ 'master', 'release_**' ] + paths: + - 'docker/docker.sh' + - 'docker/Dockerfile' + - 'docker/arm64/Dockerfile' + - 'docker/tests/**' + - '.github/workflows/docker-check.yml' pull_request: branches: [ 'master', 'develop', 'release_**' ] paths: @@ -28,10 +36,13 @@ jobs: - uses: actions/checkout@v5 - name: Check shell syntax - run: bash -n docker/docker.sh + run: bash -n docker/docker.sh docker/tests/docker-sh-test.sh - name: Run ShellCheck - run: shellcheck docker/docker.sh + run: shellcheck docker/docker.sh docker/tests/docker-sh-test.sh + + - name: Test Docker script behavior + run: bash docker/tests/docker-sh-test.sh - name: Check amd64 Dockerfile run: > diff --git a/docker/docker.sh b/docker/docker.sh index 80c0894a4e0..6205b0ba7b7 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -152,6 +152,16 @@ require_run_option_value() { fi } +require_no_args() { + local command=$1 + shift + + if [[ $# -gt 0 ]]; then + echo "$command: does not accept arguments: $*" >&2 + return 1 + fi +} + run() { local -a volume_args=() local -a port_args=() @@ -360,11 +370,15 @@ build() { } pull() { + require_no_args pull "$@" || return 1 + echo "docker pull $IMAGE_REFERENCE" docker pull "$IMAGE_REFERENCE" } start() { + require_no_args start "$@" || return 1 + if docker_container_exists; then echo "container: $CONTAINER_NAME" echo "docker start $CONTAINER_NAME" @@ -377,6 +391,8 @@ start() { } stop() { + require_no_args stop "$@" || return 1 + if docker_container_exists; then echo "container: $CONTAINER_NAME" echo "docker stop $CONTAINER_NAME" @@ -389,6 +405,8 @@ stop() { } rm_container() { + require_no_args rm "$@" || return 1 + if ! docker_container_exists; then echo "container not found: $CONTAINER_NAME" >&2 return 1 @@ -402,6 +420,8 @@ rm_container() { } log() { + require_no_args log "$@" || return 1 + if docker_container_exists; then echo "container: $CONTAINER_NAME" docker exec "$CONTAINER_NAME" tail -100f "$LOG_FILE" diff --git a/docker/tests/docker-sh-test.sh b/docker/tests/docker-sh-test.sh new file mode 100644 index 00000000000..dd47abc9920 --- /dev/null +++ b/docker/tests/docker-sh-test.sh @@ -0,0 +1,325 @@ +#!/bin/bash + +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +DOCKER_SCRIPT="$SCRIPT_DIR/../docker.sh" +TEST_DIRECTORY="$(mktemp -d "${TMPDIR:-/tmp}/java-tron-docker-test.XXXXXX")" +TEST_DIRECTORY="$(cd "$TEST_DIRECTORY" && pwd)" +MOCK_BINARY_DIRECTORY="$TEST_DIRECTORY/bin" +MOCK_DOWNLOAD_CONTENT="downloaded private configuration" +export MOCK_DOWNLOAD_CONTENT + +CASE_DIRECTORY="" +DOCKER_CALL_LOG="" +DOCKER_RUN_ARGS_LOG="" +DOWNLOAD_CALL_LOG="" +COMMAND_OUTPUT="" + +cleanup() { + rm -rf "$TEST_DIRECTORY" +} +trap cleanup EXIT + +fail() { + echo "FAIL: $*" >&2 + exit 1 +} + +docker() { + if [[ "${1:-}" == "info" ]]; then + return 0 + fi + + if [[ "${1:-}" == "image" && "${2:-}" == "inspect" ]]; then + return 0 + fi + + printf '%s\n' "${1:-}" >> "$DOCKER_CALL_LOG" + if [[ "${1:-}" == "run" ]]; then + shift + printf '%s\n' "$@" > "$DOCKER_RUN_ARGS_LOG" + fi +} +export -f docker + +curl() { + local output_file="" + + printf '%s\n' "$*" >> "$DOWNLOAD_CALL_LOG" + if [[ "${MOCK_CURL_FAIL:-false}" == "true" ]]; then + return 22 + fi + + while [[ $# -gt 0 ]]; do + if [[ "$1" == "--output" ]]; then + output_file=$2 + break + fi + shift + done + + [[ -n "$output_file" ]] || return 2 + printf '%s\n' "$MOCK_DOWNLOAD_CONTENT" > "$output_file" +} +export -f curl + +wget() { + local argument + local output_file="" + + printf '%s\n' "$*" >> "$DOWNLOAD_CALL_LOG" + for argument in "$@"; do + if [[ "$argument" == --output-document=* ]]; then + output_file=${argument#--output-document=} + break + fi + done + + [[ -n "$output_file" ]] || return 2 + printf '%s\n' "$MOCK_DOWNLOAD_CONTENT" > "$output_file" +} +export -f wget + +prepare_restricted_path() { + local utility + local utility_path + + mkdir -p "$MOCK_BINARY_DIRECTORY" + for utility in dirname mkdir mktemp rm chmod mv; do + utility_path=$(command -v "$utility") + ln -sf "$utility_path" "$MOCK_BINARY_DIRECTORY/$utility" + done +} + +prepare_case() { + local case_name=$1 + + CASE_DIRECTORY="$TEST_DIRECTORY/$case_name" + DOCKER_CALL_LOG="$CASE_DIRECTORY/docker-calls.log" + DOCKER_RUN_ARGS_LOG="$CASE_DIRECTORY/docker-run-args.log" + DOWNLOAD_CALL_LOG="$CASE_DIRECTORY/download-calls.log" + export DOCKER_CALL_LOG DOCKER_RUN_ARGS_LOG DOWNLOAD_CALL_LOG + export MOCK_CURL_FAIL=false + + mkdir -p "$CASE_DIRECTORY" + : > "$DOCKER_CALL_LOG" + : > "$DOCKER_RUN_ARGS_LOG" + : > "$DOWNLOAD_CALL_LOG" +} + +run_script() { + (cd "$CASE_DIRECTORY" && "$BASH" "$DOCKER_SCRIPT" "$@") +} + +run_script_with_restricted_path() { + (cd "$CASE_DIRECTORY" && PATH="$MOCK_BINARY_DIRECTORY" "$BASH" "$DOCKER_SCRIPT" "$@") +} + +assert_success() { + if ! COMMAND_OUTPUT=$(run_script "$@" 2>&1); then + fail "$* failed unexpectedly: $COMMAND_OUTPUT" + fi +} + +assert_failure() { + if COMMAND_OUTPUT=$(run_script "$@" 2>&1); then + fail "$* succeeded unexpectedly" + fi +} + +assert_file_empty() { + local file=$1 + + [[ ! -s "$file" ]] || fail "expected $file to be empty" +} + +assert_file_content() { + local file=$1 + local expected=$2 + local actual + + [[ -f "$file" ]] || fail "expected $file to exist" + actual=$(< "$file") + [[ "$actual" == "$expected" ]] \ + || fail "unexpected content in $file: $actual" +} + +assert_line_count() { + local file=$1 + local expected=$2 + local actual=0 + + while IFS= read -r _; do + actual=$((actual + 1)) + done < "$file" + + [[ "$actual" -eq "$expected" ]] \ + || fail "expected $expected lines in $file, found $actual" +} + +assert_run_args() { + local -a actual=() + local expected + local index=0 + + while IFS= read -r argument; do + actual+=("$argument") + done < "$DOCKER_RUN_ARGS_LOG" + + [[ "${#actual[@]}" -eq "$#" ]] \ + || fail "expected $# docker run arguments, found ${#actual[@]}: ${actual[*]}" + + for expected in "$@"; do + [[ "${actual[$index]}" == "$expected" ]] \ + || fail "docker run argument $index: expected '$expected', found '${actual[$index]}'" + index=$((index + 1)) + done +} + +test_rejects_extra_arguments() { + local option + local command_name + + for option in --pull --start --stop --log --rm; do + prepare_case "extra-argument-${option#--}" + assert_failure "$option" unexpected + command_name=${option#--} + [[ "$COMMAND_OUTPUT" == *"$command_name: does not accept arguments: unexpected"* ]] \ + || fail "$option returned an unexpected error: $COMMAND_OUTPUT" + assert_file_empty "$DOCKER_CALL_LOG" + done +} + +test_mainnet_defaults() { + prepare_case mainnet-defaults + assert_success --run + + assert_run_args \ + -d \ + --name tronprotocol-java-tron \ + -v "$CASE_DIRECTORY/output-directory:/java-tron/output-directory" \ + -p 127.0.0.1:8090:8090 \ + -p 127.0.0.1:50051:50051 \ + -p 18888:18888 \ + -p 18888:18888/udp \ + --restart always \ + tronprotocol/java-tron:latest \ + -c /java-tron/config.conf + assert_file_empty "$DOWNLOAD_CALL_LOG" +} + +test_custom_run_arguments() { + local custom_volume="$TEST_DIRECTORY/data directory:/java-tron/output-directory" + local custom_config="/config directory/custom.conf" + + prepare_case custom-run-arguments + assert_success --run \ + -v "$custom_volume" \ + -p 127.0.0.1:18090:8090 \ + -c "$custom_config" + + assert_run_args \ + -d \ + --name tronprotocol-java-tron \ + -v "$custom_volume" \ + -p 127.0.0.1:18090:8090 \ + --restart always \ + tronprotocol/java-tron:latest \ + -c "$custom_config" + assert_file_empty "$DOWNLOAD_CALL_LOG" +} + +test_private_network_download() { + local config_file + + prepare_case private-download + config_file="$CASE_DIRECTORY/config/private_net_config.conf" + assert_success --run --net private + + assert_file_content "$config_file" "$MOCK_DOWNLOAD_CONTENT" + assert_line_count "$DOWNLOAD_CALL_LOG" 1 + assert_run_args \ + -d \ + --name tronprotocol-java-tron \ + -v "$CASE_DIRECTORY/output-directory:/java-tron/output-directory" \ + -v "$config_file:/java-tron/config.conf:ro" \ + -p 127.0.0.1:16667:16667 \ + -p 127.0.0.1:50051:50051 \ + -p 16666:16666 \ + -p 16666:16666/udp \ + --restart always \ + tronprotocol/java-tron:latest \ + -c /java-tron/config.conf \ + --witness +} + +test_private_network_reuses_config() { + local config_file + + prepare_case private-reuse + config_file="$CASE_DIRECTORY/config/private_net_config.conf" + mkdir -p "$(dirname "$config_file")" + printf '%s\n' "user configuration" > "$config_file" + + assert_success --run --net private + assert_file_content "$config_file" "user configuration" + assert_file_empty "$DOWNLOAD_CALL_LOG" +} + +test_private_network_updates_config() { + local config_file + + prepare_case private-update + config_file="$CASE_DIRECTORY/config/private_net_config.conf" + mkdir -p "$(dirname "$config_file")" + printf '%s\n' "old configuration" > "$config_file" + + assert_success --run --net private --update-config true + assert_file_content "$config_file" "$MOCK_DOWNLOAD_CONTENT" + assert_line_count "$DOWNLOAD_CALL_LOG" 1 +} + +test_private_network_download_failure() { + local config_file + + prepare_case private-download-failure + config_file="$CASE_DIRECTORY/config/private_net_config.conf" + export MOCK_CURL_FAIL=true + + assert_failure --run --net private + [[ "$COMMAND_OUTPUT" == *"failed to download private network configuration"* ]] \ + || fail "private download returned an unexpected error: $COMMAND_OUTPUT" + [[ ! -e "$config_file" ]] || fail "failed download left $config_file behind" + assert_file_empty "$DOCKER_CALL_LOG" + assert_file_empty "$DOCKER_RUN_ARGS_LOG" +} + +test_private_network_wget_fallback() { + local config_file + + prepare_case private-wget-fallback + prepare_restricted_path + config_file="$CASE_DIRECTORY/config/private_net_config.conf" + + export -nf curl + if ! COMMAND_OUTPUT=$(run_script_with_restricted_path --run --net private 2>&1); then + export -f curl + fail "wget fallback failed unexpectedly: $COMMAND_OUTPUT" + fi + export -f curl + + assert_file_content "$config_file" "$MOCK_DOWNLOAD_CONTENT" + assert_line_count "$DOWNLOAD_CALL_LOG" 1 +} + +test_rejects_extra_arguments +test_mainnet_defaults +test_custom_run_arguments +test_private_network_download +test_private_network_reuses_config +test_private_network_updates_config +test_private_network_download_failure +test_private_network_wget_fallback + +echo "docker.sh behavior tests passed" From c4ce02de50b849ac9cd86a6b309f84c869f3c87b Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 13:39:05 +0800 Subject: [PATCH 30/35] ci(docker): keep Docker validation static - remove mock-based docker.sh behavior tests - limit CI to Bash, ShellCheck, and Dockerfile static checks - retain path-filtered PR and direct-push triggers --- .github/workflows/docker-check.yml | 9 +- docker/tests/docker-sh-test.sh | 325 ----------------------------- 2 files changed, 2 insertions(+), 332 deletions(-) delete mode 100644 docker/tests/docker-sh-test.sh diff --git a/.github/workflows/docker-check.yml b/.github/workflows/docker-check.yml index b4950dc100e..75291afa4bb 100644 --- a/.github/workflows/docker-check.yml +++ b/.github/workflows/docker-check.yml @@ -7,7 +7,6 @@ on: - 'docker/docker.sh' - 'docker/Dockerfile' - 'docker/arm64/Dockerfile' - - 'docker/tests/**' - '.github/workflows/docker-check.yml' pull_request: branches: [ 'master', 'develop', 'release_**' ] @@ -15,7 +14,6 @@ on: - 'docker/docker.sh' - 'docker/Dockerfile' - 'docker/arm64/Dockerfile' - - 'docker/tests/**' - '.github/workflows/docker-check.yml' workflow_dispatch: @@ -36,13 +34,10 @@ jobs: - uses: actions/checkout@v5 - name: Check shell syntax - run: bash -n docker/docker.sh docker/tests/docker-sh-test.sh + run: bash -n docker/docker.sh - name: Run ShellCheck - run: shellcheck docker/docker.sh docker/tests/docker-sh-test.sh - - - name: Test Docker script behavior - run: bash docker/tests/docker-sh-test.sh + run: shellcheck docker/docker.sh - name: Check amd64 Dockerfile run: > diff --git a/docker/tests/docker-sh-test.sh b/docker/tests/docker-sh-test.sh deleted file mode 100644 index dd47abc9920..00000000000 --- a/docker/tests/docker-sh-test.sh +++ /dev/null @@ -1,325 +0,0 @@ -#!/bin/bash - -set -euo pipefail - -SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" -DOCKER_SCRIPT="$SCRIPT_DIR/../docker.sh" -TEST_DIRECTORY="$(mktemp -d "${TMPDIR:-/tmp}/java-tron-docker-test.XXXXXX")" -TEST_DIRECTORY="$(cd "$TEST_DIRECTORY" && pwd)" -MOCK_BINARY_DIRECTORY="$TEST_DIRECTORY/bin" -MOCK_DOWNLOAD_CONTENT="downloaded private configuration" -export MOCK_DOWNLOAD_CONTENT - -CASE_DIRECTORY="" -DOCKER_CALL_LOG="" -DOCKER_RUN_ARGS_LOG="" -DOWNLOAD_CALL_LOG="" -COMMAND_OUTPUT="" - -cleanup() { - rm -rf "$TEST_DIRECTORY" -} -trap cleanup EXIT - -fail() { - echo "FAIL: $*" >&2 - exit 1 -} - -docker() { - if [[ "${1:-}" == "info" ]]; then - return 0 - fi - - if [[ "${1:-}" == "image" && "${2:-}" == "inspect" ]]; then - return 0 - fi - - printf '%s\n' "${1:-}" >> "$DOCKER_CALL_LOG" - if [[ "${1:-}" == "run" ]]; then - shift - printf '%s\n' "$@" > "$DOCKER_RUN_ARGS_LOG" - fi -} -export -f docker - -curl() { - local output_file="" - - printf '%s\n' "$*" >> "$DOWNLOAD_CALL_LOG" - if [[ "${MOCK_CURL_FAIL:-false}" == "true" ]]; then - return 22 - fi - - while [[ $# -gt 0 ]]; do - if [[ "$1" == "--output" ]]; then - output_file=$2 - break - fi - shift - done - - [[ -n "$output_file" ]] || return 2 - printf '%s\n' "$MOCK_DOWNLOAD_CONTENT" > "$output_file" -} -export -f curl - -wget() { - local argument - local output_file="" - - printf '%s\n' "$*" >> "$DOWNLOAD_CALL_LOG" - for argument in "$@"; do - if [[ "$argument" == --output-document=* ]]; then - output_file=${argument#--output-document=} - break - fi - done - - [[ -n "$output_file" ]] || return 2 - printf '%s\n' "$MOCK_DOWNLOAD_CONTENT" > "$output_file" -} -export -f wget - -prepare_restricted_path() { - local utility - local utility_path - - mkdir -p "$MOCK_BINARY_DIRECTORY" - for utility in dirname mkdir mktemp rm chmod mv; do - utility_path=$(command -v "$utility") - ln -sf "$utility_path" "$MOCK_BINARY_DIRECTORY/$utility" - done -} - -prepare_case() { - local case_name=$1 - - CASE_DIRECTORY="$TEST_DIRECTORY/$case_name" - DOCKER_CALL_LOG="$CASE_DIRECTORY/docker-calls.log" - DOCKER_RUN_ARGS_LOG="$CASE_DIRECTORY/docker-run-args.log" - DOWNLOAD_CALL_LOG="$CASE_DIRECTORY/download-calls.log" - export DOCKER_CALL_LOG DOCKER_RUN_ARGS_LOG DOWNLOAD_CALL_LOG - export MOCK_CURL_FAIL=false - - mkdir -p "$CASE_DIRECTORY" - : > "$DOCKER_CALL_LOG" - : > "$DOCKER_RUN_ARGS_LOG" - : > "$DOWNLOAD_CALL_LOG" -} - -run_script() { - (cd "$CASE_DIRECTORY" && "$BASH" "$DOCKER_SCRIPT" "$@") -} - -run_script_with_restricted_path() { - (cd "$CASE_DIRECTORY" && PATH="$MOCK_BINARY_DIRECTORY" "$BASH" "$DOCKER_SCRIPT" "$@") -} - -assert_success() { - if ! COMMAND_OUTPUT=$(run_script "$@" 2>&1); then - fail "$* failed unexpectedly: $COMMAND_OUTPUT" - fi -} - -assert_failure() { - if COMMAND_OUTPUT=$(run_script "$@" 2>&1); then - fail "$* succeeded unexpectedly" - fi -} - -assert_file_empty() { - local file=$1 - - [[ ! -s "$file" ]] || fail "expected $file to be empty" -} - -assert_file_content() { - local file=$1 - local expected=$2 - local actual - - [[ -f "$file" ]] || fail "expected $file to exist" - actual=$(< "$file") - [[ "$actual" == "$expected" ]] \ - || fail "unexpected content in $file: $actual" -} - -assert_line_count() { - local file=$1 - local expected=$2 - local actual=0 - - while IFS= read -r _; do - actual=$((actual + 1)) - done < "$file" - - [[ "$actual" -eq "$expected" ]] \ - || fail "expected $expected lines in $file, found $actual" -} - -assert_run_args() { - local -a actual=() - local expected - local index=0 - - while IFS= read -r argument; do - actual+=("$argument") - done < "$DOCKER_RUN_ARGS_LOG" - - [[ "${#actual[@]}" -eq "$#" ]] \ - || fail "expected $# docker run arguments, found ${#actual[@]}: ${actual[*]}" - - for expected in "$@"; do - [[ "${actual[$index]}" == "$expected" ]] \ - || fail "docker run argument $index: expected '$expected', found '${actual[$index]}'" - index=$((index + 1)) - done -} - -test_rejects_extra_arguments() { - local option - local command_name - - for option in --pull --start --stop --log --rm; do - prepare_case "extra-argument-${option#--}" - assert_failure "$option" unexpected - command_name=${option#--} - [[ "$COMMAND_OUTPUT" == *"$command_name: does not accept arguments: unexpected"* ]] \ - || fail "$option returned an unexpected error: $COMMAND_OUTPUT" - assert_file_empty "$DOCKER_CALL_LOG" - done -} - -test_mainnet_defaults() { - prepare_case mainnet-defaults - assert_success --run - - assert_run_args \ - -d \ - --name tronprotocol-java-tron \ - -v "$CASE_DIRECTORY/output-directory:/java-tron/output-directory" \ - -p 127.0.0.1:8090:8090 \ - -p 127.0.0.1:50051:50051 \ - -p 18888:18888 \ - -p 18888:18888/udp \ - --restart always \ - tronprotocol/java-tron:latest \ - -c /java-tron/config.conf - assert_file_empty "$DOWNLOAD_CALL_LOG" -} - -test_custom_run_arguments() { - local custom_volume="$TEST_DIRECTORY/data directory:/java-tron/output-directory" - local custom_config="/config directory/custom.conf" - - prepare_case custom-run-arguments - assert_success --run \ - -v "$custom_volume" \ - -p 127.0.0.1:18090:8090 \ - -c "$custom_config" - - assert_run_args \ - -d \ - --name tronprotocol-java-tron \ - -v "$custom_volume" \ - -p 127.0.0.1:18090:8090 \ - --restart always \ - tronprotocol/java-tron:latest \ - -c "$custom_config" - assert_file_empty "$DOWNLOAD_CALL_LOG" -} - -test_private_network_download() { - local config_file - - prepare_case private-download - config_file="$CASE_DIRECTORY/config/private_net_config.conf" - assert_success --run --net private - - assert_file_content "$config_file" "$MOCK_DOWNLOAD_CONTENT" - assert_line_count "$DOWNLOAD_CALL_LOG" 1 - assert_run_args \ - -d \ - --name tronprotocol-java-tron \ - -v "$CASE_DIRECTORY/output-directory:/java-tron/output-directory" \ - -v "$config_file:/java-tron/config.conf:ro" \ - -p 127.0.0.1:16667:16667 \ - -p 127.0.0.1:50051:50051 \ - -p 16666:16666 \ - -p 16666:16666/udp \ - --restart always \ - tronprotocol/java-tron:latest \ - -c /java-tron/config.conf \ - --witness -} - -test_private_network_reuses_config() { - local config_file - - prepare_case private-reuse - config_file="$CASE_DIRECTORY/config/private_net_config.conf" - mkdir -p "$(dirname "$config_file")" - printf '%s\n' "user configuration" > "$config_file" - - assert_success --run --net private - assert_file_content "$config_file" "user configuration" - assert_file_empty "$DOWNLOAD_CALL_LOG" -} - -test_private_network_updates_config() { - local config_file - - prepare_case private-update - config_file="$CASE_DIRECTORY/config/private_net_config.conf" - mkdir -p "$(dirname "$config_file")" - printf '%s\n' "old configuration" > "$config_file" - - assert_success --run --net private --update-config true - assert_file_content "$config_file" "$MOCK_DOWNLOAD_CONTENT" - assert_line_count "$DOWNLOAD_CALL_LOG" 1 -} - -test_private_network_download_failure() { - local config_file - - prepare_case private-download-failure - config_file="$CASE_DIRECTORY/config/private_net_config.conf" - export MOCK_CURL_FAIL=true - - assert_failure --run --net private - [[ "$COMMAND_OUTPUT" == *"failed to download private network configuration"* ]] \ - || fail "private download returned an unexpected error: $COMMAND_OUTPUT" - [[ ! -e "$config_file" ]] || fail "failed download left $config_file behind" - assert_file_empty "$DOCKER_CALL_LOG" - assert_file_empty "$DOCKER_RUN_ARGS_LOG" -} - -test_private_network_wget_fallback() { - local config_file - - prepare_case private-wget-fallback - prepare_restricted_path - config_file="$CASE_DIRECTORY/config/private_net_config.conf" - - export -nf curl - if ! COMMAND_OUTPUT=$(run_script_with_restricted_path --run --net private 2>&1); then - export -f curl - fail "wget fallback failed unexpectedly: $COMMAND_OUTPUT" - fi - export -f curl - - assert_file_content "$config_file" "$MOCK_DOWNLOAD_CONTENT" - assert_line_count "$DOWNLOAD_CALL_LOG" 1 -} - -test_rejects_extra_arguments -test_mainnet_defaults -test_custom_run_arguments -test_private_network_download -test_private_network_reuses_config -test_private_network_updates_config -test_private_network_download_failure -test_private_network_wget_fallback - -echo "docker.sh behavior tests passed" From 888d1f0e5c7ab59b6ebbeba2472808a9cd705811 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 13:39:39 +0800 Subject: [PATCH 31/35] docs(docker): document private JSON-RPC port mapping - clarify that private JSON-RPC port 8545 is not published by default - provide the complete custom port set required to expose it locally --- docker/docker.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/docker/docker.md b/docker/docker.md index aa84483a7bf..e96d229c7d7 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -62,12 +62,23 @@ You can also run a single-node private network with the configuration maintained $ bash docker.sh --run --net private ``` -Private mode starts FullNode with `--witness` so that the genesis witness produces blocks. Its default ports match `private_net_config.conf`: +Private mode starts FullNode with `--witness` so that the genesis witness produces blocks. By default, the helper publishes the following ports used by `private_net_config.conf`: - `127.0.0.1:16667`: used by the HTTP-based JSON API - `127.0.0.1:50051`: used by the gRPC-based API - `16666`: TCP and UDP on all host interfaces, used by the private P2P network +The private configuration also enables JSON-RPC on container port `8545`, but the helper does not publish that port by default. To make JSON-RPC available on the host loopback interface, provide the complete custom port set because specifying any `-p` replaces all default mappings: + +```shell +$ bash docker.sh --run --net private \ + -p 127.0.0.1:16667:16667 \ + -p 127.0.0.1:50051:50051 \ + -p 127.0.0.1:8545:8545 \ + -p 16666:16666 \ + -p 16666:16666/udp +``` + The downloaded configuration contains a publicly known development witness key and genesis accounts. Use it only for isolated local development. For a multi-node, shared, or security-sensitive private network, use the maintained [`tron-docker/private_net`](https://github.com/tronprotocol/tron-docker/tree/main/private_net) setup and replace its keys and configuration as appropriate. To replace an existing local copy with the latest maintained configuration, explicitly request an update. This overwrites `config/private_net_config.conf`. From 2166a7fe7f89e229645bc1e81d39ee1ac8710644 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 14:04:33 +0800 Subject: [PATCH 32/35] fix(docker): validate run options before image lookup - reject invalid run options before checking or pulling the image - consolidate download and container lifecycle handling - detect custom output volumes during argument parsing - simplify command dispatch without changing runtime behavior --- docker/docker.sh | 182 ++++++++++++++++++----------------------------- 1 file changed, 71 insertions(+), 111 deletions(-) diff --git a/docker/docker.sh b/docker/docker.sh index 6205b0ba7b7..78cc1fe39ca 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -68,28 +68,32 @@ docker_image_exists() { docker image inspect "$IMAGE_REFERENCE" >/dev/null 2>&1 } -download_build_file() { +download_file() { local source_url=$1 local destination=$2 + local failure_message=$3 + local missing_tool_message=$4 + local empty_file_message=$5 + local error_fd=$6 + local -a download_command if command -v curl >/dev/null 2>&1; then - if ! curl --fail --silent --show-error --location \ - --output "$destination" "$source_url"; then - echo "build: failed to download: $source_url" >&2 - return 1 - fi + download_command=(curl --fail --silent --show-error --location + --output "$destination" "$source_url") elif command -v wget >/dev/null 2>&1; then - if ! wget --quiet --output-document="$destination" "$source_url"; then - echo "build: failed to download: $source_url" >&2 - return 1 - fi + download_command=(wget --quiet --output-document="$destination" "$source_url") else - echo "build: curl or wget is required to download build files" >&2 + echo "$missing_tool_message" >&"$error_fd" + return 1 + fi + + if ! "${download_command[@]}"; then + echo "$failure_message" >&"$error_fd" return 1 fi if [[ ! -s "$destination" ]]; then - echo "build: downloaded file is empty: $source_url" >&2 + echo "$empty_file_message" >&"$error_fd" return 1 fi } @@ -108,33 +112,15 @@ download_private_config() { return 1 fi - if command -v curl >/dev/null 2>&1; then - if ! curl --fail --silent --show-error --location \ - --output "$temp_file" "$PRIVATE_NET_CONFIG_URL"; then - rm -f "$temp_file" - echo "run: failed to download private network configuration" - return 1 - fi - elif command -v wget >/dev/null 2>&1; then - if ! wget --quiet --output-document="$temp_file" "$PRIVATE_NET_CONFIG_URL"; then - rm -f "$temp_file" - echo "run: failed to download private network configuration" - return 1 - fi - else - rm -f "$temp_file" - echo "run: curl or wget is required to download the private network configuration" - return 1 - fi - - if [[ ! -s "$temp_file" ]]; then + if ! download_file "$PRIVATE_NET_CONFIG_URL" "$temp_file" \ + "run: failed to download private network configuration" \ + "run: curl or wget is required to download the private network configuration" \ + "run: downloaded private network configuration is empty" 1; then rm -f "$temp_file" - echo "run: downloaded private network configuration is empty" return 1 fi - chmod 644 "$temp_file" - if ! mv -f "$temp_file" "$config_file"; then + if ! chmod 644 "$temp_file" || ! mv -f "$temp_file" "$config_file"; then rm -f "$temp_file" echo "run: failed to save private network configuration: $config_file" return 1 @@ -168,29 +154,18 @@ run() { local -a tron_args=() local network="main" local network_config="" - local custom_config=false local update_config=false local has_output_volume=false - local mount - local index - - if ! docker_image_exists; then - echo 'warning: no java-tron mirror image, do you need to get the mirror image?[y/n]' - IFS= read -r need - - if [[ $need == 'y' || $need == 'yes' ]]; then - pull || return $? - else - echo "warning: no mirror image found, go ahead and download a mirror." - exit 1 - fi - fi while [[ $# -gt 0 ]]; do case "$1" in -v) require_run_option_value "$@" || return 1 volume_args+=(-v "$2") + if [[ "$2" == *":/java-tron/output-directory" \ + || "$2" == *":/java-tron/output-directory:"* ]]; then + has_output_volume=true + fi shift 2 ;; -p) @@ -201,7 +176,6 @@ run() { -c) require_run_option_value "$@" || return 1 tron_args+=(-c "$2") - custom_config=true shift 2 ;; --net) @@ -232,7 +206,7 @@ run() { return 1 fi - if [[ "$custom_config" = true && -n "$network_config" ]]; then + if [[ ${#tron_args[@]} -gt 0 && -n "$network_config" ]]; then echo "run: -c cannot be combined with --net private" >&2 return 1 fi @@ -242,6 +216,18 @@ run() { return 1 fi + if ! docker_image_exists; then + echo 'warning: no java-tron mirror image, do you need to get the mirror image?[y/n]' + IFS= read -r need + + if [[ $need == 'y' || $need == 'yes' ]]; then + pull || return $? + else + echo "warning: no mirror image found, go ahead and download a mirror." + return 1 + fi + fi + if [[ -n "$network_config" ]]; then if [[ "$update_config" = true ]]; then echo "updating private network configuration from tron-deployment" @@ -253,15 +239,6 @@ run() { volume_args+=(-v "$network_config:$BUNDLED_CONFIG_FILE:ro") fi - for ((index = 1; index < ${#volume_args[@]}; index += 2)); do - mount=${volume_args[$index]} - if [[ "$mount" == *":/java-tron/output-directory" \ - || "$mount" == *":/java-tron/output-directory:"* ]]; then - has_output_volume=true - break - fi - done - if [[ "$has_output_volume" = false ]]; then volume_args=(-v "$OUTPUT_DIRECTORY:/java-tron/output-directory" "${volume_args[@]}") fi @@ -348,7 +325,10 @@ build() { dockerfile_path="$temporary_context/Dockerfile" echo "build files not found next to docker.sh; downloading a temporary build context" - if ! download_build_file "$dockerfile_source" "$dockerfile_path"; then + if ! download_file "$dockerfile_source" "$dockerfile_path" \ + "build: failed to download: $dockerfile_source" \ + "build: curl or wget is required to download build files" \ + "build: downloaded file is empty: $dockerfile_source" 2; then rm -rf "$temporary_context" return 1 fi @@ -376,32 +356,28 @@ pull() { docker pull "$IMAGE_REFERENCE" } -start() { - require_no_args start "$@" || return 1 +change_container_state() { + local command_name=$1 + shift - if docker_container_exists; then - echo "container: $CONTAINER_NAME" - echo "docker start $CONTAINER_NAME" - docker start "$CONTAINER_NAME" || return $? - docker ps - else + require_no_args "$command_name" "$@" || return 1 + if ! docker_container_exists; then echo "container not found: $CONTAINER_NAME" >&2 return 1 fi + + echo "container: $CONTAINER_NAME" + echo "docker $command_name $CONTAINER_NAME" + docker "$command_name" "$CONTAINER_NAME" || return $? + docker ps } -stop() { - require_no_args stop "$@" || return 1 +start() { + change_container_state start "$@" +} - if docker_container_exists; then - echo "container: $CONTAINER_NAME" - echo "docker stop $CONTAINER_NAME" - docker stop "$CONTAINER_NAME" || return $? - docker ps - else - echo "container not found: $CONTAINER_NAME" >&2 - return 1 - fi +stop() { + change_container_state stop "$@" } rm_container() { @@ -431,37 +407,21 @@ log() { fi } -case "$1" in - --pull) - pull "${@:2}" - exit $? - ;; - --start) - start "${@:2}" - exit $? - ;; - --stop) - stop "${@:2}" - exit $? - ;; - --build) - build "${@:2}" - exit $? - ;; - --run) - run "${@:2}" - exit $? - ;; - --rm) - rm_container "${@:2}" - exit $? - ;; - --log) - log "${@:2}" - exit $? - ;; +command_name=${1:-} +[[ $# -eq 0 ]] || shift + +case "$command_name" in + --pull) pull "$@" ;; + --start) start "$@" ;; + --stop) stop "$@" ;; + --build) build "$@" ;; + --run) run "$@" ;; + --rm) rm_container "$@" ;; + --log) log "$@" ;; *) - echo "arg: $1 is not a valid parameter" >&2 + echo "arg: $command_name is not a valid parameter" >&2 exit 1 ;; esac + +exit $? From 52fdb1e37ddd451d170c1b87a2ef161818e67deb Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Mon, 31 Aug 2026 16:08:11 +0800 Subject: [PATCH 33/35] fix(docker): send private config errors to stderr Route private network configuration setup and download failures to stderr while keeping successful status messages on stdout. --- docker/docker.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docker/docker.sh b/docker/docker.sh index 78cc1fe39ca..75a67fe2ff1 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -103,26 +103,26 @@ download_private_config() { local temp_file if ! mkdir -p "$CONFIG_DIR"; then - echo "run: failed to create configuration directory: $CONFIG_DIR" + echo "run: failed to create configuration directory: $CONFIG_DIR" >&2 return 1 fi if ! temp_file=$(mktemp "$CONFIG_DIR/.private_net_config.conf.XXXXXX"); then - echo "run: failed to create a temporary configuration file" + echo "run: failed to create a temporary configuration file" >&2 return 1 fi if ! download_file "$PRIVATE_NET_CONFIG_URL" "$temp_file" \ "run: failed to download private network configuration" \ "run: curl or wget is required to download the private network configuration" \ - "run: downloaded private network configuration is empty" 1; then + "run: downloaded private network configuration is empty" 2; then rm -f "$temp_file" return 1 fi if ! chmod 644 "$temp_file" || ! mv -f "$temp_file" "$config_file"; then rm -f "$temp_file" - echo "run: failed to save private network configuration: $config_file" + echo "run: failed to save private network configuration: $config_file" >&2 return 1 fi From c9fd4e02f35be143ad81435d85ea82451744abd0 Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Tue, 1 Sep 2026 14:36:18 +0800 Subject: [PATCH 34/35] fix(docker): keep private P2P unpublished by default - stop publishing private P2P TCP and UDP ports in single-node mode - preserve explicit custom mappings for intentional multi-node setups - document port exposure and container recreation requirements --- docker/docker.md | 13 +++++++------ docker/docker.sh | 3 --- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/docker/docker.md b/docker/docker.md index e96d229c7d7..3e253f1fa7d 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -26,7 +26,7 @@ $ bash docker.sh --pull ### Run the service -Before running java-tron, make sure the required ports are available on the host. By default, HTTP and gRPC APIs are bound to the host loopback interface, while the P2P port is available on all host interfaces. Mainnet uses: +Before running java-tron, make sure the required ports are available on the host. By default, HTTP and gRPC APIs are bound to the host loopback interface. Mainnet P2P remains available on all host interfaces: - `127.0.0.1:8090`: used by the HTTP-based JSON API - `127.0.0.1:50051`: used by the gRPC-based API @@ -66,21 +66,22 @@ Private mode starts FullNode with `--witness` so that the genesis witness produc - `127.0.0.1:16667`: used by the HTTP-based JSON API - `127.0.0.1:50051`: used by the gRPC-based API -- `16666`: TCP and UDP on all host interfaces, used by the private P2P network -The private configuration also enables JSON-RPC on container port `8545`, but the helper does not publish that port by default. To make JSON-RPC available on the host loopback interface, provide the complete custom port set because specifying any `-p` replaces all default mappings: +The private configuration also enables JSON-RPC on container port `8545` and listens for P2P on container port `16666`, but the helper publishes neither port by default. To make JSON-RPC available on the host loopback interface, provide the complete custom port set because specifying any `-p` replaces all default mappings: ```shell $ bash docker.sh --run --net private \ -p 127.0.0.1:16667:16667 \ -p 127.0.0.1:50051:50051 \ - -p 127.0.0.1:8545:8545 \ - -p 16666:16666 \ - -p 16666:16666/udp + -p 127.0.0.1:8545:8545 ``` The downloaded configuration contains a publicly known development witness key and genesis accounts. Use it only for isolated local development. For a multi-node, shared, or security-sensitive private network, use the maintained [`tron-docker/private_net`](https://github.com/tronprotocol/tron-docker/tree/main/private_net) setup and replace its keys and configuration as appropriate. +To connect an intentionally configured helper-based node from another machine, provide the complete custom port set and include explicit P2P mappings such as `-p :16666:16666` and `-p :16666:16666/udp`. Before exposing P2P, replace the public development credentials and configure the peers and witness roles; publishing the ports alone does not create a multi-node private network. + +Existing containers keep their original port mappings when restarted. After upgrading from a helper version that published private P2P by default, run `bash docker.sh --rm` and then create the private node again with `bash docker.sh --run --net private`. + To replace an existing local copy with the latest maintained configuration, explicitly request an update. This overwrites `config/private_net_config.conf`. ```shell diff --git a/docker/docker.sh b/docker/docker.sh index 75a67fe2ff1..a8f228abf0f 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -36,7 +36,6 @@ DOCKER_RPC_PORT=50051 DOCKER_LISTEN_PORT=18888 PRIVATE_HTTP_PORT=16667 -PRIVATE_LISTEN_PORT=16666 VOLUME=$(pwd) CONFIG_DIR="$VOLUME/config" @@ -248,8 +247,6 @@ run() { port_args=( -p "$HOST_API_BIND_ADDRESS:$PRIVATE_HTTP_PORT:$PRIVATE_HTTP_PORT" -p "$HOST_API_BIND_ADDRESS:$HOST_RPC_PORT:$DOCKER_RPC_PORT" - -p "$PRIVATE_LISTEN_PORT:$PRIVATE_LISTEN_PORT" - -p "$PRIVATE_LISTEN_PORT:$PRIVATE_LISTEN_PORT/udp" ) else port_args=( From 305bb066b855df553433ce4345a6ccc548d408df Mon Sep 17 00:00:00 2001 From: 3for <287494524@qq.com> Date: Wed, 2 Sep 2026 17:56:42 +0800 Subject: [PATCH 35/35] fix(docker): reject run when container already exists - detect the managed container before image checks or configuration downloads - provide clear guidance for starting or recreating an existing container - document the helper's repeated-run and container lifecycle behavior --- docker/docker.md | 2 +- docker/docker.sh | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docker/docker.md b/docker/docker.md index 3e253f1fa7d..193a320e85a 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -32,7 +32,7 @@ Before running java-tron, make sure the required ports are available on the host - `127.0.0.1:50051`: used by the gRPC-based API - `18888`: TCP and UDP on all host interfaces, used by the P2P protocol -The helper manages one container named `tronprotocol-java-tron` and creates it with Docker's `always` restart policy. It cannot run mainnet and private-network instances simultaneously; use `--rm` to remove the existing container before switching networks. A manually stopped container remains stopped until it is manually restarted or the Docker daemon restarts. Use Docker directly when multiple instances, a custom container name, or a different restart policy is required. +The helper manages one container named `tronprotocol-java-tron` and creates it with Docker's `always` restart policy. If this container already exists, `--run` exits without changing it. Use `--start` to start a stopped container, or use `--rm` before `--run` to recreate it with new settings. The helper cannot run mainnet and private-network instances simultaneously; remove the existing container before switching networks. A manually stopped container remains stopped until it is manually restarted or the Docker daemon restarts. Use Docker directly when multiple instances, a custom container name, or a different restart policy is required. #### Full node on the main network diff --git a/docker/docker.sh b/docker/docker.sh index a8f228abf0f..a14ce9d4920 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -215,6 +215,12 @@ run() { return 1 fi + if docker_container_exists; then + echo "container already exists: $CONTAINER_NAME" >&2 + echo "use --start if it is stopped, or --rm before rerunning --run" >&2 + return 1 + fi + if ! docker_image_exists; then echo 'warning: no java-tron mirror image, do you need to get the mirror image?[y/n]' IFS= read -r need