diff --git a/.dockerignore b/.dockerignore index d171944d877..57c53d50a15 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1 @@ ./* -!docker-entrypoint.sh - diff --git a/.github/workflows/docker-check.yml b/.github/workflows/docker-check.yml new file mode 100644 index 00000000000..75291afa4bb --- /dev/null +++ b/.github/workflows/docker-check.yml @@ -0,0 +1,56 @@ +name: Docker Check + +on: + push: + branches: [ 'master', 'release_**' ] + paths: + - 'docker/docker.sh' + - 'docker/Dockerfile' + - 'docker/arm64/Dockerfile' + - '.github/workflows/docker-check.yml' + pull_request: + branches: [ 'master', 'develop', 'release_**' ] + paths: + - 'docker/docker.sh' + - 'docker/Dockerfile' + - 'docker/arm64/Dockerfile' + - '.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 diff --git a/docker/Dockerfile b/docker/Dockerfile index 2732f5a55ed..2f7915e7032 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,44 +1,69 @@ -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 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 \ + && 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 \ + # 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 - -COPY docker-entrypoint.sh $BASE_DIR/bin +ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libtcmalloc_minimal.so.4" +ENV TCMALLOC_RELEASE_RATE=10 WORKDIR $BASE_DIR -ENTRYPOINT ["./bin/docker-entrypoint.sh"] +ENTRYPOINT ["./bin/FullNode"] + +# 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..8b4601223b6 100644 --- a/docker/arm64/Dockerfile +++ b/docker/arm64/Dockerfile @@ -1,33 +1,49 @@ -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 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 \ + && 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 \ + # 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/FullNode"] + +# 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/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.md b/docker/docker.md index 79aa6b08e2d..193a320e85a 100644 --- a/docker/docker.md +++ b/docker/docker.md @@ -1,110 +1,186 @@ # 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. 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 -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. +`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 -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 the DockerHub, this image contains the full JDK environment and the host network configuration file, using the script for simple docker operations. +### 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 `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 -$ sh docker.sh --pull +$ 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: -- `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 + +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 +- `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. 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 ```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 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). ```shell -$ sh docker.sh --run --net main -p 8080:8090 -p 40051:50051 +$ bash docker.sh --run --net main \ + -p 127.0.0.1:8080:8090 \ + -p 127.0.0.1:40051:50051 \ + -p 18888:18888 \ + -p 18888:18888/udp ``` -#### Full node on the nile test network +#### Single-node private network + +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. 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 + +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 -$ sh docker.sh --run --net test +$ 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 ``` -#### 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. +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 -$ 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. 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. + +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. +### 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 -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 -$ 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 +Use `--stop` to stop the java-tron container: ```shell -$ sh docker.sh --stop +$ 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: +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. + +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: ```shell -DOCKER_REPOSITORY="your_repository" -DOCKER_IMAGES="java-tron" -DOCKER_TARGET="1.0" +$ bash docker.sh --build ``` -then execute the build: +The script detects the Docker daemon architecture by default. You can also select the target architecture explicitly: ```shell -$ sh docker.sh --build +$ 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 +- **`--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 +- **`--rm`**: remove the container without removing the image -* **`--build`** building a local mirror image -* **`--pull`** download a docker mirror from **DockerHub** -* **`--run`** run the docker mirror -* **`--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` -* **`-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 +### 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 +- **`--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..a14ce9d4920 100644 --- a/docker/docker.sh +++ b/docker/docker.sh @@ -17,12 +17,16 @@ # ############################################################################## +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" BASE_DIR="/java-tron" 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_API_BIND_ADDRESS="127.0.0.1" HOST_HTTP_PORT=8090 HOST_RPC_PORT=50051 HOST_LISTEN_PORT=18888 @@ -31,261 +35,396 @@ DOCKER_HTTP_PORT=8090 DOCKER_RPC_PORT=50051 DOCKER_LISTEN_PORT=18888 -VOLUME=`pwd` -CONFIG="$VOLUME/config" +PRIVATE_HTTP_PORT=16667 + +VOLUME=$(pwd) +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" +PRIVATE_NET_CONFIG_URL="https://raw.githubusercontent.com/tronprotocol/tron-deployment/master/$PRIVATE_NET_CONFIG_FILE" -# update the configuration file, if true, the configuration file will be fetched from the network every time you start -UPDATE_CONFIG=true +LOG_FILE="$BASE_DIR/logs/tron.log" -LOG_FILE="/logs/tron.log" +JAVA_TRON_DOCKER_URL="https://raw.githubusercontent.com/tronprotocol/java-tron/develop/docker" -JAVA_TRON_REPOSITORY="https://raw.githubusercontent.com/tronprotocol/java-tron/develop/" -DOCKER_FILE="Dockerfile" -ENDPOINT_SHELL="docker-entrypoint.sh" +if ! command -v docker >/dev/null 2>&1; then + echo "docker is required but was not found" >&2 + exit 1 +fi -if test docker; then - docker -v -else - echo "warning: docker must be installed, please install docker first." - exit +if ! docker info >/dev/null 2>&1; then + echo "unable to connect to the Docker daemon" >&2 + exit 1 fi -docker_ps() { - containerID=`docker ps -a | grep "$DOCKER_REPOSITORY-$DOCKER_IMAGES" | awk '{print $1}'` - cid=$containerID +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_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_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 + download_command=(curl --fail --silent --show-error --location + --output "$destination" "$source_url") + elif command -v wget >/dev/null 2>&1; then + download_command=(wget --quiet --output-document="$destination" "$source_url") + else + 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 "$empty_file_message" >&"$error_fd" + return 1 fi } +download_private_config() { + local config_file=$1 + local temp_file -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 - fi + if ! mkdir -p "$CONFIG_DIR"; then + 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" >&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" 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" >&2 + return 1 + fi + + 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 +} + +require_no_args() { + local command=$1 + shift + + if [[ $# -gt 0 ]]; then + echo "$command: does not accept arguments: $*" >&2 + return 1 fi } run() { - docker_image + local -a volume_args=() + local -a port_args=() + local -a tron_args=() + local network="main" + local network_config="" + local update_config=false + local has_output_volume=false + + 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) + require_run_option_value "$@" || return 1 + port_args+=(-p "$2") + shift 2 + ;; + -c) + require_run_option_value "$@" || return 1 + tron_args+=(-c "$2") + 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 [[ ${#tron_args[@]} -gt 0 && -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" >&2 + return 1 + fi - if [ ! $image ] ; then + 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]' - read need + IFS= read -r need if [[ $need == 'y' || $need == 'yes' ]]; then - pull + pull || return $? else echo "warning: no mirror image found, go ahead and download a mirror." - exit + return 1 fi fi - volume="" - parameter="" - tron_parameter="" - 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" - UPDATE_CONFIG=false - 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 - shift 2 - ;; - --update-config) - UPDATE_CONFIG=$2 - shift 2 - ;; - *) - echo "run: arg $1 is not a valid parameter" - exit - ;; - esac - done - if [ $UPDATE_CONFIG = true ]; then - download_config + 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 [ -z "$volume" ]; then - volume=" -v $CONFIG:/java-tron/config -v $OUTPUT_DIRECTORY:/java-tron/output-directory" - fi + if [[ "$has_output_volume" = false ]]; then + volume_args=(-v "$OUTPUT_DIRECTORY:/java-tron/output-directory" "${volume_args[@]}") + 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" + if [[ ${#port_args[@]} -eq 0 ]]; then + if [[ "$network" = "private" ]]; then + port_args=( + -p "$HOST_API_BIND_ADDRESS:$PRIVATE_HTTP_PORT:$PRIVATE_HTTP_PORT" + -p "$HOST_API_BIND_ADDRESS:$HOST_RPC_PORT:$DOCKER_RPC_PORT" + ) + else + port_args=( + -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" + ) fi + fi - if [ -z "$tron_parameter" ]; then - tron_parameter=" -c $CONFIG_PATH$CONFIG_FILE" - fi + if [[ ${#tron_args[@]} -eq 0 ]]; then + tron_args=(-c "$BUNDLED_CONFIG_FILE") + fi - # Using custom parameters - docker run -d -it --name "$DOCKER_REPOSITORY-$DOCKER_IMAGES" \ - $volume \ - $parameter \ - --restart always \ - "$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" + if [[ "$network" = "private" ]]; then + tron_args+=(--witness) fi + + docker run -d --name "$CONTAINER_NAME" \ + "${volume_args[@]}" \ + "${port_args[@]}" \ + --restart always \ + "$IMAGE_REFERENCE" \ + "${tron_args[@]}" } 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" ]]; 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 - # download Dockerfile - `$DOWNLOAD_CMD "$JAVA_TRON_REPOSITORY$DOCKER_FILE"` - `$DOWNLOAD_CMD "$JAVA_TRON_REPOSITORY$ENDPOINT_SHELL"` - chmod u+rwx $ENDPOINT_SHELL + + 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_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 + fi + + echo "docker build --platform $platform --file $dockerfile_path" + docker build \ + --platform "$platform" \ + --file "$dockerfile_path" \ + --tag "$IMAGE_REFERENCE" \ + "$build_context" + build_status=$? + + if [[ -n "$temporary_context" ]]; then + rm -rf "$temporary_context" fi - docker build -t "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" . + + return "$build_status" } pull() { - echo "docker pull $DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" - docker pull "$DOCKER_REPOSITORY/$DOCKER_IMAGES:$DOCKER_TARGET" + require_no_args pull "$@" || return 1 + + 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 - docker ps - else - echo "container not running!" +change_container_state() { + local command_name=$1 + shift + + 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 +} + +start() { + change_container_state start "$@" } stop() { - docker_ps - if [ $cid ]; then - echo "containerID: $cid" - echo "docker stop $cid" - docker stop $cid - docker ps - else - echo "container not running!" - fi + change_container_state stop "$@" } rm_container() { - stop - if [ $cid ]; then - echo "containerID: $cid" - echo "docker rm $cid" - docker rm $cid - docker_ps - else - echo "image not exists!" + require_no_args rm "$@" || return 1 + + 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 + require_no_args log "$@" || return 1 - 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 "$CONTAINER_NAME" tail -100f "$LOG_FILE" else - echo "container not exists!" + echo "container not found: $CONTAINER_NAME" >&2 + return 1 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" - exit + echo "arg: $command_name is not a valid parameter" >&2 + exit 1 ;; esac + +exit $? diff --git a/quickstart.md b/quickstart.md index b3eeb7b7713..c64f631b24f 100644 --- a/quickstart.md +++ b/quickstart.md @@ -2,222 +2,147 @@ ## 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 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. ## 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 +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. -### Build the docker image from source +## Run a mainnet FullNode -#### Clone the java-tron repo +Pull the official image from Docker Hub: -Clone the java-tron repo from github and enter the directory `java-tron`: +```shell +docker pull tronprotocol/java-tron:latest ``` -git clone https://github.com/tronprotocol/java-tron.git -cd java-tron + +Create host directories for the blockchain database and application logs: + +```shell +mkdir -p output-directory logs ``` -#### Build the docker image +Set JVM memory options for the architecture used by the Docker image. Run one of the following commands: -Use the command below to navigate to the docker directory and start the build: +```shell +# amd64 / JDK 8 +JAVA_TRON_JVM_OPTIONS="-Xms9G -Xmx12G -XX:MaxDirectMemorySize=1G" ``` -cd docker -docker build -t tronprotocol/java-tron . + +```shell +# ARM64 / JDK 17 +JAVA_TRON_JVM_OPTIONS="-Xmx9G -XX:MaxDirectMemorySize=1G" ``` -#### Using the official Docker images +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. -Download the official docker image from the Dockerhub with below command if you'd like to use the official images: -``` -docker pull tronprotocol/java-tron +Start the FullNode with the mainnet configuration bundled in the image: + +```shell +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 ``` -### Run the container +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: -You can run the command below to start the java-tron: +```shell +docker exec java-tron tail -100f /java-tron/logs/tron.log ``` -docker run -it -d -p 8090:8090 -p 18888:18888 -p 50051:50051 --restart always tronprotocol/java-tron + +Stop the container: + +```shell +docker stop 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: +Restart the stopped container: + +```shell +docker start java-tron ``` -docker run -it -d -p 8080:8080 -p 8090:8090 -p 18888:18888 -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 + +To recreate the container with a different image or configuration, remove the stopped container first: + +```shell +docker rm java-tron ``` -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. -## Quickstart for using docker-tron-quickstart +The bind-mounted database and logs remain on the host after the container is removed. -The image exposes a Full Node and Event Server. Through TRON Quickstart, users can deploy DApps, smart contracts, and interact with the TronWeb library. +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. -> 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) +### Mainnet and SR requirements -### 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 -``` +A Mainnet FullNode requires production-grade CPU, memory, SSD capacity, and network bandwidth. The current official deployment requirements are: -### Pull the image using docker: -```shell -docker pull trontools/quickstart -``` +| 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 + +[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: -## 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 \ +docker pull tronbox/tre +docker run --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"} + -p 127.0.0.1:9090:9090 \ + -e useDefaultPrivateKey=true \ + tronbox/tre ``` -## Docker Commands -Here are some useful docker commands, which will help you manage the TRON Quickstart Docker container on your machine. +Check that the environment is ready: -**To list all active containers on your machine, run:** ```shell -docker container ps -``` -**Output:** -```shell -docker container ps +curl -fsS http://127.0.0.1:9090/healthcheck +``` -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 -``` +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. -### How to check the logs of the FullNode ### -``` - docker exec -it tron tail -f /tron/FullNode/logs/tron.log -``` +> **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 -
- -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 - ``` -
+For multi-node private network deployment, follow the official [tron-docker private network guide](https://github.com/tronprotocol/tron-docker/tree/main/private_net).