This is an automated email from the ASF dual-hosted git repository.

djwang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit fd5be5d672ddec4a918505f4e7dd15d95ab2ee64
Author: Dianjin Wang <[email protected]>
AuthorDate: Tue Jun 17 14:48:33 2025 +0800

    Sandbox: updates for the main branch/release
    
    In this commit, main changes are included:
    
    - Add the standard Apache license headers for files
    - Refactor the Dockerfile.*.rockylinux 9
    - Adopt a more friendly way to support running the sandbox with
      multi-nodes.
    - Strengthen the robustness of sandbox.
---
 README.md                                      |   9 +-
 devops/sandbox/.env                            |  21 +-
 devops/sandbox/Dockerfile.RELEASE.rockylinux9  | 420 ++++++++++++++++---------
 devops/sandbox/Dockerfile.main.rockylinux9     | 380 +++++++++++++---------
 devops/sandbox/README.md                       |  92 ++++--
 devops/sandbox/configs/90-cbdb-limits.conf     |  19 ++
 devops/sandbox/configs/90-cbdb-sysctl.conf     |  19 ++
 devops/sandbox/configs/gpinitsystem_multinode  |  27 +-
 devops/sandbox/configs/gpinitsystem_singlenode |  19 ++
 devops/sandbox/configs/init_system.sh          | 168 ++++++----
 devops/sandbox/configs/multinode-gpinit-hosts  |   2 +-
 devops/sandbox/docker-compose-rockylinux9.yml  |  36 +++
 devops/sandbox/run.sh                          |  46 +--
 pom.xml                                        |   4 +
 14 files changed, 857 insertions(+), 405 deletions(-)

diff --git a/README.md b/README.md
index 1c467c6e471..a72c42fd266 100644
--- a/README.md
+++ b/README.md
@@ -68,9 +68,8 @@ Linux OS (including RHEL/Rocky Linux, and Ubuntu) and macOS.
 ### Try out quickly
 
 Welcome to try out Cloudberry via building [one Docker-based
-Sandbox](https://github.com/apache/cloudberry-bootcamp), which is tailored to
-help you gain a basic understanding of Cloudberry's capabilities and features
-a range of materials, including tutorials, sample code, and crash courses.
+Sandbox](./devops/sandbox), which is tailored to help you gain a basic
+understanding of Cloudberry's capabilities and features.
 
 ## Repositories
 
@@ -79,10 +78,8 @@ this, there are several ecosystem repositories for 
Cloudberry, including the
 website, extensions, connectors, adapters, and other utilities.
 
 * [apache/cloudberry-site](https://github.com/apache/cloudberry-site): website 
and documentation sources.
-* [apache/cloudberry-bootcamp](https://github.com/apache/cloudberry-bootcamp): 
help you quickly try out Cloudberry via one Docker-based Sandbox.
-* [apache/cloudberry-gpbackup](https://github.com/apache/cloudberry-gpbackup): 
backup utility for Cloudberry.
+* [apache/cloudberry-backup](https://github.com/apache/cloudberry-backup): 
backup utility for Cloudberry.
 * [apache/cloudberry-go-libs](https://github.com/apache/cloudberry-go-libs): 
go-libs for Cloudberry.
-* 
[apache/cloudberry-gpbackup-s3-plugin](https://github.com/apache/cloudberry-gpbackup-s3-plugin):
 S3 plugin for use with Cloudberry backup utility.
 * [apache/cloudberry-pxf](https://github.com/apache/cloudberry-pxf): Platform 
Extension Framework (PXF) for Cloudberry.
 
 ## Community & Support
diff --git a/devops/sandbox/.env b/devops/sandbox/.env
index 5f1596515d2..233d7c5b1b5 100644
--- a/devops/sandbox/.env
+++ b/devops/sandbox/.env
@@ -1,2 +1,21 @@
-CODEBASE_VERSION=1.6.0
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
+CODEBASE_VERSION=2.0.0
 OS_VERSION=rockylinux9
diff --git a/devops/sandbox/Dockerfile.RELEASE.rockylinux9 
b/devops/sandbox/Dockerfile.RELEASE.rockylinux9
index 948bbfa7986..f9f422f57f6 100644
--- a/devops/sandbox/Dockerfile.RELEASE.rockylinux9
+++ b/devops/sandbox/Dockerfile.RELEASE.rockylinux9
@@ -1,155 +1,287 @@
-FROM rockylinux/rockylinux:9
-
-ARG CODEBASE_VERSION_VAR=${CODEBASE_VERSION_VAR}
-ARG TIMEZONE_VAR="Asia/Shanghai"
-
-ENV container=docker
-ENV MULTINODE=false
-
-RUN dnf update -y && \
-    dnf install -y systemd \
-                   systemd-libs && \
-    dnf clean all
-
-# Clean up unnecessary systemd units
-RUN [ -d /lib/systemd/system/sysinit.target.wants ] && find 
/lib/systemd/system/sysinit.target.wants/ -type l -not -name 
'systemd-tmpfiles-setup.service' -delete || echo "Directory 
/lib/systemd/system/sysinit.target.wants does not exist" && \
-    [ -d /lib/systemd/system/multi-user.target.wants ] && find 
/lib/systemd/system/multi-user.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/multi-user.target.wants does not exist" && \
-    find /etc/systemd/system/*.wants/ -type l -delete || echo "Directory 
/etc/systemd/system/*.wants does not exist" && \
-    [ -d /lib/systemd/system/local-fs.target.wants ] && find 
/lib/systemd/system/local-fs.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/local-fs.target.wants does not exist" && \
-    [ -d /lib/systemd/system/sockets.target.wants ] && find 
/lib/systemd/system/sockets.target.wants/ -type l -not -name '*udev*' -delete 
|| echo "Directory /lib/systemd/system/sockets.target.wants does not exist" && \
-    [ -d /lib/systemd/system/basic.target.wants ] && find 
/lib/systemd/system/basic.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/basic.target.wants does not exist" && \
-    [ -d /lib/systemd/system/anaconda.target.wants ] && find 
/lib/systemd/system/anaconda.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/anaconda.target.wants does not exist"
-
-COPY ./configs/* /tmp/
-
-RUN     echo root:cbdb@123 | chpasswd && \
-        dnf makecache && \
-        dnf install -y yum-utils \
-                       epel-release \
-                       git && \
-        yum-config-manager --disable epel-cisco-openh264 && \
-        dnf makecache && \
-        yum-config-manager --disable epel && \
-        dnf install -y --enablerepo=epel \
-                       the_silver_searcher \
-                       bat \
-                       htop && \
-        dnf install -y bison \
-                       cmake3 \
-                       ed \
-                       flex \
-                       gcc \
-                       gcc-c++ \
-                       glibc-langpack-en \
-                       go \
-                       initscripts \
-                       iproute \
-                       less \
-                       m4 \
-                       net-tools \
-                       openssh-clients \
-                       openssh-server \
-                       passwd \
-                       perl \
-                       rsync \
-                       sudo \
-                       tar \
-                       unzip \
-                       util-linux-ng \
-                       wget \
-                       sshpass \
-                       which && \
-        dnf install -y apr-devel \
-                       bzip2-devel \
-                       krb5-devel \
-                       libcurl-devel \
-                       libevent-devel \
-                       libxml2-devel \
-                       libzstd-devel \
-                       openldap-devel \
-                       openssl-devel \
-                       pam-devel \
-                       perl-ExtUtils-Embed \
-                       perl-Test-Simple \
-                       perl-core \
-                       python3-devel \
-                       readline-devel \
-                       zlib-devel && \
-        dnf install -y --enablerepo=crb \
-                       libuv-devel \
-                       libyaml-devel \
-                       perl-IPC-Run && \
-        dnf install -y --enablerepo=epel \
-                       xerces-c-devel
-
-RUN     cp /tmp/90-cbdb-sysctl.conf /etc/sysctl.conf && \
-        cp /tmp/90-cbdb-limits.conf /etc/security/limits.d/90-cbdb-limits.conf 
&& \
-        cat /usr/share/zoneinfo/${TIMEZONE_VAR} > /etc/localtime && \
-        echo "cdw" > /tmp/gpdb-hosts && \
-        echo "/usr/local/lib" >> /etc/ld.so.conf && \
-        echo "/usr/local/lib64" >> /etc/ld.so.conf && \
-        ldconfig && \
-        chmod 777 /tmp/gpinitsystem_singlenode && \
-        chmod 777 /tmp/init_system.sh && \
-        hostname > ~/orig_hostname && \
-        /usr/sbin/groupadd gpadmin && \
-        /usr/sbin/useradd  gpadmin -g gpadmin -G wheel && \
-        setcap cap_net_raw+ep /usr/bin/ping && \
-        echo "cbdb@123"|passwd --stdin gpadmin && \
-        echo "gpadmin        ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers && 
\
-        echo "root           ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers && 
\
-        echo "export 
COORDINATOR_DATA_DIRECTORY=/data0/database/coordinator/gpseg-1" >> 
/home/gpadmin/.bashrc && \
-        echo "source /usr/local/cloudberry-db/greenplum_path.sh"               
 >> /home/gpadmin/.bashrc && \
-        mkdir -p /data0/database/coordinator /data0/database/primary 
/data0/database/mirror && \
-        chown -R gpadmin:gpadmin /data0 && \
-        ssh-keygen -A && \
-        echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
-
-RUN     cd /tmp/ && \
-        unzip -d /tmp /tmp/cloudberrydb-${CODEBASE_VERSION_VAR}.zip && \
-        mv /tmp/cloudberrydb-${CODEBASE_VERSION_VAR} /tmp/cloudberry
-
-RUN     cd /tmp/cloudberry && \
-        ./configure --prefix=/usr/local/cloudberry-db \
-                    --enable-cassert                  \
-                    --enable-debug-extensions         \
-                    --enable-ic-proxy                 \
-                    --enable-mapreduce                \
-                    --enable-orafce                   \
-                    --enable-orca                     \
-                    --enable-pxf                      \
-                    --enable-tap-tests                \
-                    --with-gssapi                     \
-                    --with-ldap                       \
-                    --with-libxml                     \
-                    --with-openssl                    \
-                    --with-pam                        \
-                    --with-perl                       \
-                    --with-pgport=5432                \
-                    --with-python                     \
-                    --with-pythonsrc-ext
-
-RUN     cd /tmp/cloudberry && \
-        make -j$(nproc) && \
-        make install
-
-RUN     cd /tmp/cloudberry/contrib && \
-        make -j$(nproc) && \
-        make install
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
+# Multi-stage Dockerfile for Apache Cloudberry Sandbox Environment (Release)
+# --------------------------------------------------------------------
+# This Dockerfile compiles and installs a specific release version of
+# Cloudberry, then creates a runtime environment for testing and development.
+# --------------------------------------------------------------------
+
+# --------------------------------------------------------------------
+# Build stage: Rocky Linux 9 builder to compile Cloudberry (release tarball)
+# --------------------------------------------------------------------
+FROM rockylinux/rockylinux:9.6 AS builder
+
+# Install build toolchains and development headers (avoid coreutils/curl 
conflicts on arm64)
+RUN dnf makecache && \
+    dnf install -y \
+        epel-release \
+        git && \
+    dnf config-manager --disable epel-cisco-openh264 && \
+    dnf makecache && \
+    dnf config-manager --disable epel && \
+    dnf install -y --enablerepo=epel \
+        the_silver_searcher \
+        bat \
+        htop && \
+    dnf install -y \
+        bison \
+        cmake3 \
+        ed \
+        file \
+        flex \
+        gcc \
+        gcc-c++ \
+        gdb \
+        glibc-langpack-en \
+        glibc-locale-source \
+        initscripts \
+        iproute \
+        less \
+        lsof \
+        m4 \
+        net-tools \
+        openssh-clients \
+        openssh-server \
+        perl \
+        rpm-build \
+        rpmdevtools \
+        rsync \
+        sudo \
+        tar \
+        unzip \
+        util-linux-ng \
+        wget \
+        sshpass \
+        which && \
+    dnf install -y \
+        apr-devel \
+        bzip2-devel \
+        java-11-openjdk \
+        java-11-openjdk-devel \
+        krb5-devel \
+        libcurl-devel \
+        libevent-devel \
+        libxml2-devel \
+        libuuid-devel \
+        libzstd-devel \
+        lz4 \
+        lz4-devel \
+        openldap-devel \
+        openssl-devel \
+        pam-devel \
+        perl-ExtUtils-Embed \
+        perl-Test-Simple \
+        perl-core \
+        python3-devel \
+        python3-pytest \
+        readline-devel \
+        zlib-devel && \
+    dnf install -y --enablerepo=crb \
+        libuv-devel \
+        libyaml-devel \
+        perl-IPC-Run \
+        protobuf-devel && \
+    dnf clean all && \
+    cd && XERCES_LATEST_RELEASE=3.3.0 && \
+    wget -nv 
"https://archive.apache.org/dist/xerces/c/3/sources/xerces-c-${XERCES_LATEST_RELEASE}.tar.gz";
 && \
+    echo "$(curl -sL 
https://archive.apache.org/dist/xerces/c/3/sources/xerces-c-${XERCES_LATEST_RELEASE}.tar.gz.sha256)"
 | sha256sum -c - && \
+    tar xf "xerces-c-${XERCES_LATEST_RELEASE}.tar.gz"; rm 
"xerces-c-${XERCES_LATEST_RELEASE}.tar.gz" && \
+    cd xerces-c-${XERCES_LATEST_RELEASE} && \
+    ./configure --prefix=/usr/local/xerces-c && \
+    make -j$(nproc) && \
+    make install -C ~/xerces-c-${XERCES_LATEST_RELEASE} && \
+    rm -rf ~/xerces-c*
+
+# Create gpadmin user and grant passwordless sudo in builder
+RUN groupadd -r gpadmin && \
+    useradd -m -r -g gpadmin -s /bin/bash gpadmin && \
+    echo "gpadmin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/gpadmin && \
+    chmod 440 /etc/sudoers.d/gpadmin
+
+# Switch to gpadmin user
+USER gpadmin
+WORKDIR /home/gpadmin
+
+# Release version to build (Apache official tarball)
+ARG CB_RELEASE_VERSION=2.0.0-incubating
+
+# Download and extract the specified release version from Apache
+RUN wget -nv 
"https://downloads.apache.org/incubator/cloudberry/${CB_RELEASE_VERSION}/apache-cloudberry-${CB_RELEASE_VERSION}-src.tar.gz";
 -O /home/gpadmin/apache-cloudberry-${CB_RELEASE_VERSION}-src.tar.gz && \
+    tar -xzf /home/gpadmin/apache-cloudberry-${CB_RELEASE_VERSION}-src.tar.gz 
-C /home/gpadmin && \
+    rm -f /home/gpadmin/apache-cloudberry-${CB_RELEASE_VERSION}-src.tar.gz && \
+    mv /home/gpadmin/apache-cloudberry-${CB_RELEASE_VERSION} 
/home/gpadmin/cloudberry
+
+# Build Cloudberry using the official build scripts
+RUN cd /home/gpadmin/cloudberry && \
+    export SRC_DIR=/home/gpadmin/cloudberry && \
+    mkdir -p "${SRC_DIR}/build-logs" && \
+    # Ensure Cloudberry lib dir exists and has Xerces libs available
+    sudo rm -rf /usr/local/cloudberry-db && \
+    sudo mkdir -p /usr/local/cloudberry-db/lib && \
+    sudo cp -v /usr/local/xerces-c/lib/libxerces-c.so \
+              /usr/local/xerces-c/lib/libxerces-c-3.*.so \
+              /usr/local/cloudberry-db/lib/ && \
+    sudo chown -R gpadmin:gpadmin /usr/local/cloudberry-db && \
+    # Configure with required features and paths
+    export LD_LIBRARY_PATH=/usr/local/cloudberry-db/lib:$LD_LIBRARY_PATH && \
+    ./configure --prefix=/usr/local/cloudberry-db \
+                --disable-external-fts \
+                --enable-debug \
+                --enable-cassert \
+                --enable-debug-extensions \
+                --enable-gpcloud \
+                --enable-ic-proxy \
+                --enable-mapreduce \
+                --enable-orafce \
+                --enable-orca \
+                --enable-pax \
+                --enable-pxf \
+                --enable-tap-tests \
+                --with-gssapi \
+                --with-ldap \
+                --with-libxml \
+                --with-lz4 \
+                --with-pam \
+                --with-perl \
+                --with-pgport=5432 \
+                --with-python \
+                --with-pythonsrc-ext \
+                --with-ssl=openssl \
+                --with-uuid=e2fs \
+                --with-includes=/usr/local/xerces-c/include \
+                --with-libraries=/usr/local/cloudberry-db/lib && \
+    # Build and install
+    make -j$(nproc) --directory ${SRC_DIR} && \
+    make -j$(nproc) --directory ${SRC_DIR}/contrib && \
+    make install --directory ${SRC_DIR} && \
+    make install --directory "${SRC_DIR}/contrib"
+
+# --------------------------------------------------------------------
+# Runtime stage: Rocky Linux 9 runtime with required dependencies
+# --------------------------------------------------------------------
+FROM rockylinux/rockylinux:9.6
+
+# Install required runtime dependencies, SSH server, sudo, and tools
+# Note: Use dnf on Rocky Linux 9
+RUN dnf -y update && \
+    dnf -y install \
+      openssh-server openssh-clients \
+      sudo shadow-utils \
+      bash procps-ng \
+      ca-certificates \
+      python3 \
+      apr \
+      bzip2-libs \
+      krb5-libs \
+      libevent \
+      libicu \
+      libuuid \
+      libxml2 \
+      libyaml \
+      libzstd \
+      lz4 \
+      ncurses \
+      openldap \
+      openssl \
+      pam \
+      pcre2 \
+      perl \
+      protobuf \
+      readline \
+      zlib \
+      glibc-langpack-en \
+      libuv \
+      iproute \
+      net-tools \
+      which \
+      rsync \
+      keyutils \
+      libstdc++ && \
+    dnf clean all && rm -rf /var/cache/dnf
+
+# Create gpadmin user and group, grant passwordless sudo
+RUN groupadd -r gpadmin && \
+    useradd -m -r -g gpadmin -s /bin/bash gpadmin && \
+    echo "gpadmin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/gpadmin && \
+    chmod 440 /etc/sudoers.d/gpadmin
+
+# Prepare SSH daemon: generate host keys, ensure runtime dir, and allow 
gpadmin to start it
+RUN ssh-keygen -A && mkdir -p /run/sshd && chmod u+s /usr/sbin/sshd
+
+# Copy built Cloudberry from builder stage
+COPY --from=builder /usr/local/cloudberry-db /usr/local/cloudberry-db
+
+# Bring Xerces libs into Cloudberry lib dir
+COPY --from=builder /usr/local/xerces-c/lib/libxerces-c.so 
/usr/local/cloudberry-db/lib/
+COPY --from=builder /usr/local/xerces-c/lib/libxerces-c-3.*.so 
/usr/local/cloudberry-db/lib/
+
+# Copy configuration files to their final destinations
+COPY ./configs/90-cbdb-limits.conf /etc/security/limits.d/90-cbdb-limits.conf
+COPY ./configs/90-cbdb-sysctl.conf /etc/sysctl.d/90-cbdb-sysctl.conf
+COPY ./configs/gpinitsystem_singlenode /tmp/gpinitsystem_singlenode
+COPY ./configs/gpinitsystem_multinode /tmp/gpinitsystem_multinode
+COPY ./configs/multinode-gpinit-hosts /tmp/multinode-gpinit-hosts
+COPY ./configs/init_system.sh /tmp/init_system.sh
+
+# Runtime configuration
+RUN echo "cdw" > /tmp/gpdb-hosts && \
+    chmod 755 /tmp/gpinitsystem_singlenode && \
+    chmod 755 /tmp/gpinitsystem_multinode && \
+    chmod 755 /tmp/init_system.sh && \
+    mkdir -p /data0/database/coordinator /data0/database/primary 
/data0/database/mirror && \
+    chown -R gpadmin:gpadmin \
+      /usr/local/cloudberry-db \
+      /tmp/gpinitsystem_singlenode \
+      /tmp/gpinitsystem_multinode \
+      /tmp/gpdb-hosts \
+      /tmp/multinode-gpinit-hosts \
+      /data0 && \
+    echo "export 
COORDINATOR_DATA_DIRECTORY=/data0/database/coordinator/gpseg-1" >> 
/home/gpadmin/.bashrc && \
+    echo -e '\n# Add Cloudberry entries\nif [ -f 
/usr/local/cloudberry-db/cloudberry-env.sh ]; then\n  source 
/usr/local/cloudberry-db/cloudberry-env.sh\nfi\n# Add Greenplum compatibility 
entries\nif [ -f /usr/local/cloudberry-db/greenplum_path.sh ]; then\n  source 
/usr/local/cloudberry-db/greenplum_path.sh\nfi' >> /home/gpadmin/.bashrc
 
 # ----------------------------------------------------------------------
-# Set the Default User and Command
+# Generate SSH keypair for gpadmin user at build time
 # ----------------------------------------------------------------------
-# The default user is set to 'gpadmin', and the container starts by
-# running the init_system.sh script. This container serves as a base
-# environment, and the Apache Cloudberry RPM can be installed for
-# testing and functional verification.
+# WARNING: This embeds a fixed SSH keypair in the Docker image for
+# sandbox convenience. This is ONLY suitable for local testing and
+# development. DO NOT use this image in production or any environment
+# where security is a concern.
 # ----------------------------------------------------------------------
+RUN mkdir -p /home/gpadmin/.ssh && \
+    ssh-keygen -t rsa -b 4096 -N '' -C 'gpadmin@cloudberry-sandbox' \
+               -f /home/gpadmin/.ssh/id_rsa && \
+    cat /home/gpadmin/.ssh/id_rsa.pub >> /home/gpadmin/.ssh/authorized_keys && 
\
+    chmod 700 /home/gpadmin/.ssh && \
+    chmod 600 /home/gpadmin/.ssh/id_rsa && \
+    chmod 644 /home/gpadmin/.ssh/id_rsa.pub && \
+    chmod 600 /home/gpadmin/.ssh/authorized_keys && \
+    chown -R gpadmin:gpadmin /home/gpadmin/.ssh
+
+# Set default user and working directory
 USER gpadmin
-ENV USER=gpadmin
 WORKDIR /home/gpadmin
 
 EXPOSE 5432 22
 
+# cgroup mount (provided by compose/run)
 VOLUME [ "/sys/fs/cgroup" ]
+
+# Start the container by running the initialization script
 CMD ["bash","-c","/tmp/init_system.sh"]
diff --git a/devops/sandbox/Dockerfile.main.rockylinux9 
b/devops/sandbox/Dockerfile.main.rockylinux9
index 2073ebcb2a6..cd8725c130a 100644
--- a/devops/sandbox/Dockerfile.main.rockylinux9
+++ b/devops/sandbox/Dockerfile.main.rockylinux9
@@ -1,160 +1,242 @@
-FROM rockylinux/rockylinux:9
-
-# Argument for configuring the timezone
-ARG TIMEZONE_VAR="America/Los_Angeles"
-
-# Environment variables
-ENV container=docker
-ENV MULTINODE=false
-
-RUN dnf update -y && \
-    dnf install -y systemd \
-                   systemd-libs && \
-    dnf clean all
-
-# Clean up unnecessary systemd units
-RUN [ -d /lib/systemd/system/sysinit.target.wants ] && find 
/lib/systemd/system/sysinit.target.wants/ -type l -not -name 
'systemd-tmpfiles-setup.service' -delete || echo "Directory 
/lib/systemd/system/sysinit.target.wants does not exist" && \
-    [ -d /lib/systemd/system/multi-user.target.wants ] && find 
/lib/systemd/system/multi-user.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/multi-user.target.wants does not exist" && \
-    find /etc/systemd/system/*.wants/ -type l -delete || echo "Directory 
/etc/systemd/system/*.wants does not exist" && \
-    [ -d /lib/systemd/system/local-fs.target.wants ] && find 
/lib/systemd/system/local-fs.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/local-fs.target.wants does not exist" && \
-    [ -d /lib/systemd/system/sockets.target.wants ] && find 
/lib/systemd/system/sockets.target.wants/ -type l -not -name '*udev*' -delete 
|| echo "Directory /lib/systemd/system/sockets.target.wants does not exist" && \
-    [ -d /lib/systemd/system/basic.target.wants ] && find 
/lib/systemd/system/basic.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/basic.target.wants does not exist" && \
-    [ -d /lib/systemd/system/anaconda.target.wants ] && find 
/lib/systemd/system/anaconda.target.wants/ -type l -delete || echo "Directory 
/lib/systemd/system/anaconda.target.wants does not exist"
-
-COPY ./configs/* /tmp/
-
-RUN     dnf makecache && \
-        dnf install -y yum-utils \
-                       epel-release \
-                       git && \
-        yum-config-manager --disable epel-cisco-openh264 && \
-        dnf makecache && \
-        yum-config-manager --disable epel && \
-        dnf install -y --enablerepo=epel \
-                       the_silver_searcher \
-                       bat \
-                       htop && \
-        dnf install -y bison \
-                       cmake3 \
-                       ed \
-                       flex \
-                       gcc \
-                       gcc-c++ \
-                       glibc-langpack-en \
-                       go \
-                       initscripts \
-                       iproute \
-                       less \
-                       m4 \
-                       net-tools \
-                       openssh-clients \
-                       openssh-server \
-                       passwd \
-                       perl \
-                       rsync \
-                       sudo \
-                       tar \
-                       unzip \
-                       util-linux-ng \
-                       wget \
-                       sshpass \
-                       which && \
-        dnf install -y apr-devel \
-                       bzip2-devel \
-                       krb5-devel \
-                       libcurl-devel \
-                       libevent-devel \
-                       libxml2-devel \
-                       libuuid-devel \
-                       libzstd-devel \
-                       lz4-devel \
-                       openldap-devel \
-                       openssl-devel \
-                       pam-devel \
-                       perl-ExtUtils-Embed \
-                       perl-Test-Simple \
-                       perl-core \
-                       python3-devel \
-                       readline-devel \
-                       zlib-devel && \
-        dnf install -y --enablerepo=crb \
-                       libuv-devel \
-                       libyaml-devel \
-                       protobuf-devel \
-                       perl-IPC-Run && \
-        dnf install -y --enablerepo=epel \
-                       xerces-c-devel
-
-RUN     cp /tmp/90-cbdb-sysctl.conf /etc/sysctl.conf && \
-        cp /tmp/90-cbdb-limits.conf /etc/security/limits.d/90-cbdb-limits.conf 
&& \
-        cat /usr/share/zoneinfo/${TIMEZONE_VAR} > /etc/localtime && \
-        echo "cdw" > /tmp/gpdb-hosts && \
-        echo "/usr/local/lib" >> /etc/ld.so.conf && \
-        echo "/usr/local/lib64" >> /etc/ld.so.conf && \
-        ldconfig && \
-        chmod 777 /tmp/gpinitsystem_singlenode && \
-        chmod 777 /tmp/init_system.sh && \
-        hostname > ~/orig_hostname && \
-        /usr/sbin/groupadd gpadmin && \
-        /usr/sbin/useradd  gpadmin -g gpadmin -G wheel && \
-        setcap cap_net_raw+ep /usr/bin/ping && \
-        echo "cbdb@123"|passwd --stdin gpadmin && \
-        echo "gpadmin        ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers && 
\
-        echo "root           ALL=(ALL)       NOPASSWD: ALL" >> /etc/sudoers && 
\
-        echo "export 
COORDINATOR_DATA_DIRECTORY=/data0/database/coordinator/gpseg-1" >> 
/home/gpadmin/.bashrc && \
-        echo "source /usr/local/cloudberry-db/greenplum_path.sh"               
 >> /home/gpadmin/.bashrc && \
-        mkdir -p /data0/database/coordinator /data0/database/primary 
/data0/database/mirror && \
-        chown -R gpadmin:gpadmin /data0 && \
-        ssh-keygen -A && \
-        echo "PasswordAuthentication yes" >> /etc/ssh/sshd_config
-
-RUN     cd /tmp/ && \
-        git clone --recurse-submodules --branch main --single-branch --depth=1 
https://github.com/apache/cloudberry.git
-
-RUN     cd /tmp/cloudberry && \
-        ./configure --prefix=/usr/local/cloudberry-db \
-                    --enable-cassert                  \
-                    --enable-debug-extensions         \
-                    --enable-gpcloud                  \
-                    --enable-ic-proxy                 \
-                    --enable-mapreduce                \
-                    --enable-orafce                   \
-                    --enable-orca                     \
-                    --enable-pax                      \
-                    --enable-pxf                      \
-                    --enable-tap-tests                \
-                    --with-gssapi                     \
-                    --with-ldap                       \
-                    --with-libxml                     \
-                    --with-lz4                        \
-                    --with-openssl                    \
-                    --with-pam                        \
-                    --with-perl                       \
-                    --with-pgport=5432                \
-                    --with-python                     \
-                    --with-pythonsrc-ext
-
-RUN     cd /tmp/cloudberry && \
-        make -j$(nproc) && \
-        make install
-
-RUN     cd /tmp/cloudberry/contrib && \
-        make -j$(nproc) && \
-        make install
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
+# Multi-stage Dockerfile for Apache Cloudberry Sandbox Environment
+# --------------------------------------------------------------------
+# This Dockerfile uses pre-built Apache Cloudberry build images to
+# compile and install Cloudberry from the main branch, then creates
+# a runtime environment for testing and development.
+# --------------------------------------------------------------------
+
+# Build stage: Use pre-built image to compile Cloudberry
+FROM rockylinux/rockylinux:9.6 AS builder
+
+# Install build toolchains and development headers (avoid coreutils/curl 
conflicts on arm64)
+RUN dnf makecache && \
+    dnf install -y \
+        epel-release \
+        git && \
+    dnf config-manager --disable epel-cisco-openh264 && \
+    dnf makecache && \
+    dnf config-manager --disable epel && \
+    dnf install -y --enablerepo=epel \
+        the_silver_searcher \
+        bat \
+        htop && \
+    dnf install -y \
+        bison \
+        cmake3 \
+        ed \
+        file \
+        flex \
+        gcc \
+        gcc-c++ \
+        gdb \
+        glibc-langpack-en \
+        glibc-locale-source \
+        initscripts \
+        iproute \
+        less \
+        lsof \
+        m4 \
+        net-tools \
+        openssh-clients \
+        openssh-server \
+        perl \
+        rpm-build \
+        rpmdevtools \
+        rsync \
+        sudo \
+        tar \
+        unzip \
+        util-linux-ng \
+        wget \
+        sshpass \
+        which && \
+    dnf install -y \
+        apr-devel \
+        bzip2-devel \
+        java-11-openjdk \
+        java-11-openjdk-devel \
+        krb5-devel \
+        libcurl-devel \
+        libevent-devel \
+        libxml2-devel \
+        libuuid-devel \
+        libzstd-devel \
+        lz4 \
+        lz4-devel \
+        openldap-devel \
+        openssl-devel \
+        pam-devel \
+        perl-ExtUtils-Embed \
+        perl-Test-Simple \
+        perl-core \
+        python3-devel \
+        python3-pytest \
+        readline-devel \
+        zlib-devel && \
+    dnf install -y --enablerepo=crb \
+        libuv-devel \
+        libyaml-devel \
+        perl-IPC-Run \
+        protobuf-devel && \
+    dnf clean all && \
+    cd && XERCES_LATEST_RELEASE=3.3.0 && \
+    wget -nv 
"https://archive.apache.org/dist/xerces/c/3/sources/xerces-c-${XERCES_LATEST_RELEASE}.tar.gz";
 && \
+    echo "$(curl -sL 
https://archive.apache.org/dist/xerces/c/3/sources/xerces-c-${XERCES_LATEST_RELEASE}.tar.gz.sha256)"
 | sha256sum -c - && \
+    tar xf "xerces-c-${XERCES_LATEST_RELEASE}.tar.gz"; rm 
"xerces-c-${XERCES_LATEST_RELEASE}.tar.gz" && \
+    cd xerces-c-${XERCES_LATEST_RELEASE} && \
+    ./configure --prefix=/usr/local/xerces-c && \
+    make -j$(nproc) && \
+    make install -C ~/xerces-c-${XERCES_LATEST_RELEASE} && \
+    rm -rf ~/xerces-c*
+
+# Create gpadmin user and grant passwordless sudo in builder
+RUN groupadd -r gpadmin && \
+    useradd -m -r -g gpadmin -s /bin/bash gpadmin && \
+    echo "gpadmin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/gpadmin && \
+    chmod 440 /etc/sudoers.d/gpadmin
+
+# Switch to gpadmin user
+USER gpadmin
+WORKDIR /home/gpadmin
+
+# Clone the latest Cloudberry source code
+RUN git clone --recurse-submodules --branch main --single-branch --depth=1 
https://github.com/apache/cloudberry.git
+
+# Build Cloudberry using the official build scripts
+RUN cd /home/gpadmin/cloudberry && \
+    export SRC_DIR=/home/gpadmin/cloudberry && \
+    mkdir -p ${SRC_DIR}/build-logs && \
+    ./devops/build/automation/cloudberry/scripts/configure-cloudberry.sh && \
+    ./devops/build/automation/cloudberry/scripts/build-cloudberry.sh
+
+# --------------------------------------------------------------------
+# Runtime stage: Switch to a slimmer base image (Rocky Linux 9)
+# --------------------------------------------------------------------
+FROM rockylinux/rockylinux:9.6
+
+# Install required runtime dependencies, SSH server, sudo, and tools
+# Note: Use dnf on Rocky Linux 9
+RUN dnf -y update && \
+    dnf -y install \
+      openssh-server openssh-clients \
+      sudo shadow-utils \
+      bash procps-ng \
+      ca-certificates \
+      python3 \
+      apr \
+      bzip2-libs \
+      krb5-libs \
+      libevent \
+      libicu \
+      libuuid \
+      libxml2 \
+      libyaml \
+      libzstd \
+      lz4 \
+      ncurses \
+      openldap \
+      openssl \
+      pam \
+      pcre2 \
+      perl \
+      protobuf \
+      readline \
+      zlib \
+      glibc-langpack-en \
+      libuv \
+      iproute \
+      net-tools \
+      which \
+      rsync \
+      keyutils \
+      libstdc++ && \
+    dnf clean all && rm -rf /var/cache/dnf
+
+# Create gpadmin user and group, grant passwordless sudo
+RUN groupadd -r gpadmin && \
+    useradd -m -r -g gpadmin -s /bin/bash gpadmin && \
+    echo "gpadmin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/gpadmin && \
+    chmod 440 /etc/sudoers.d/gpadmin
+
+# Prepare SSH daemon: generate host keys, ensure runtime dir, and allow 
gpadmin to start it
+RUN ssh-keygen -A && mkdir -p /run/sshd && chmod u+s /usr/sbin/sshd
+
+# Copy built Cloudberry from builder stage
+COPY --from=builder /usr/local/cloudberry-db /usr/local/cloudberry-db
+
+# Bring Xerces libs into Cloudberry lib dir and normalize SONAME via 
builder-installed versioned prefix
+COPY --from=builder /usr/local/xerces-c/lib/libxerces-c.so 
/usr/local/cloudberry-db/lib/
+COPY --from=builder /usr/local/xerces-c/lib/libxerces-c-3.*.so 
/usr/local/cloudberry-db/lib/
+
+# Copy configuration files to their final destinations
+COPY ./configs/90-cbdb-limits.conf /etc/security/limits.d/90-cbdb-limits.conf
+COPY ./configs/90-cbdb-sysctl.conf /etc/sysctl.d/90-cbdb-sysctl.conf
+COPY ./configs/gpinitsystem_singlenode /tmp/gpinitsystem_singlenode
+COPY ./configs/gpinitsystem_multinode /tmp/gpinitsystem_multinode
+COPY ./configs/multinode-gpinit-hosts /tmp/multinode-gpinit-hosts
+COPY ./configs/init_system.sh /tmp/init_system.sh
+
+# Runtime configuration
+RUN echo "cdw" > /tmp/gpdb-hosts && \
+    chmod 755 /tmp/gpinitsystem_singlenode && \
+    chmod 755 /tmp/gpinitsystem_multinode && \
+    chmod 755 /tmp/init_system.sh && \
+    mkdir -p /data0/database/coordinator /data0/database/primary 
/data0/database/mirror && \
+    chown -R gpadmin:gpadmin \
+      /usr/local/cloudberry-db \
+      /tmp/gpinitsystem_singlenode \
+      /tmp/gpinitsystem_multinode \
+      /tmp/gpdb-hosts \
+      /tmp/multinode-gpinit-hosts \
+      /data0 && \
+    echo "export 
COORDINATOR_DATA_DIRECTORY=/data0/database/coordinator/gpseg-1" >> 
/home/gpadmin/.bashrc && \
+    echo -e '\n# Add Cloudberry entries\nif [ -f 
/usr/local/cloudberry-db/cloudberry-env.sh ]; then\n  source 
/usr/local/cloudberry-db/cloudberry-env.sh\nfi' >> /home/gpadmin/.bashrc
 
 # ----------------------------------------------------------------------
-# Set the Default User and Command
+# Generate SSH keypair for gpadmin user at build time
 # ----------------------------------------------------------------------
-# The default user is set to 'gpadmin', and the container starts by
-# running the init_system.sh script. This container serves as a base
-# environment, and the Apache Cloudberry RPM can be installed for
-# testing and functional verification.
+# WARNING: This embeds a fixed SSH keypair in the Docker image for
+# sandbox convenience. This is ONLY suitable for local testing and
+# development. DO NOT use this image in production or any environment
+# where security is a concern.
 # ----------------------------------------------------------------------
+RUN mkdir -p /home/gpadmin/.ssh && \
+    ssh-keygen -t rsa -b 4096 -N '' -C 'gpadmin@cloudberry-sandbox' \
+               -f /home/gpadmin/.ssh/id_rsa && \
+    cat /home/gpadmin/.ssh/id_rsa.pub >> /home/gpadmin/.ssh/authorized_keys && 
\
+    chmod 700 /home/gpadmin/.ssh && \
+    chmod 600 /home/gpadmin/.ssh/id_rsa && \
+    chmod 644 /home/gpadmin/.ssh/id_rsa.pub && \
+    chmod 600 /home/gpadmin/.ssh/authorized_keys && \
+    chown -R gpadmin:gpadmin /home/gpadmin/.ssh
+
+# Set default user and working directory
 USER gpadmin
-ENV USER=gpadmin
 WORKDIR /home/gpadmin
 
 EXPOSE 5432 22
 
+# cgroup mount (provided by compose/run)
 VOLUME [ "/sys/fs/cgroup" ]
+
+# Start the container by running the initialization script
 CMD ["bash","-c","/tmp/init_system.sh"]
diff --git a/devops/sandbox/README.md b/devops/sandbox/README.md
index b8e0043c574..bf39e5348fd 100644
--- a/devops/sandbox/README.md
+++ b/devops/sandbox/README.md
@@ -1,14 +1,39 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied.  See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
 ---
 title: Sandbox of Apache Cloudberry
 ---
 
 # Install Apache Cloudberry With Docker
 
-This document guides you on how to quickly set up and connect to a Apache 
Cloudberry in a Docker environment. You can try out Apache Cloudberry by 
performing some basic operations and running SQL commands. 
+This document guides you on how to quickly set up and connect to Apache 
Cloudberry in a Docker environment. You can try out Apache Cloudberry by 
performing some basic operations and running SQL commands.
 
 > [!WARNING]
 > This guide is intended for testing or development. DO NOT use it for 
 > production.
 
+> [!WARNING]
+> **Security Notice: Embedded SSH Keys**
+>
+> For ease of use, this sandbox environment includes **pre-generated SSH keys 
embedded in the Docker image**. All containers built from the same image share 
the same SSH keypair, allowing passwordless SSH communication between nodes.
+>
+> **This is ONLY acceptable for local testing and development environments.** 
These embedded keys are **NOT secure** and must **NEVER** be used in production 
or any environment where security is a concern. Anyone with access to the 
Docker image can extract these keys.
+
 
 ## Prerequisites
 
@@ -19,13 +44,13 @@ Make sure that your environment meets the following 
requirements:
 
 ## Build the Sandbox
 
-When building and deploying Cloudberry in Docker, you will have 2 different 
deployment options as well as different build options.
+When building and deploying Apache Cloudberry in Docker, you will have 2 
different deployment options as well as different build options.
 
 **Deployment Options**
-1. **Single Container** (Default) - With the single container option, you will 
have the coordinator as well as the Cloudberry segments all running on a single 
container. This is the default behavior when deploying using the `run.sh` 
script provided.
-2. **Multi-Container** - Deploying with the multi-container option will give 
you a more realistic deployment of what actual production Cloudberry clusters 
look like. With multi-node, you will have the coordinator, the standby 
coordinator, and 2 segment hosts all on their own respective containers. This 
is to both highlight the distributed nature of Apache Cloudberry as well as 
highlight how high availability (HA) features work in the event of a server (or 
in this case a container) failin [...]
+1. **Single Container** (Default) - With the single container option, you will 
have the coordinator as well as the Apache Cloudberry segments all running on a 
single container. This is the default behavior when deploying using the 
`run.sh` script provided.
+2. **Multi-Container** - Deploying with the multi-container option will give 
you a more realistic deployment of what actual production Apache Cloudberry 
clusters look like. With multi-node, you will have the coordinator, the standby 
coordinator, and 2 segment hosts all on their own respective containers. This 
is to both highlight the distributed nature of Apache Cloudberry as well as 
highlight how high availability (HA) features work in the event of a server (or 
in this case a container) [...]
 
-![cloudberry Sandbox Deployments](../images/sandbox-deployment.jpg)
+![cloudberry Sandbox Deployments](./sandbox-deployment.jpg)
 
 **Build Options**
 
@@ -36,48 +61,48 @@ Build and deploy steps:
 
 1. Start Docker Desktop and make sure it is running properly on your host 
platform.
 
-2. Download this repository (which is 
[apache/cloudberry-bootcamp](https://github.com/apache/cloudberry-bootcamp)) to 
the target machine.
+2. Clone the Apache Cloudberry repository to the target machine.
 
     ```shell
-    git clone https://github.com/apache/cloudberry-bootcamp.git
+    git clone https://github.com/apache/cloudberry.git
     ```
 
 3. Enter the repository and run the `run.sh` script to start the Docker 
container. This will start the automatic installation process. Depending on 
your environment, you may need to run this with 'sudo' command.
 
-    - For latest Cloudberry DB release running on a single container
+    - For latest Apache Cloudberry release running on a single container
 
     ```shell
-    cd bootcamp/000-cbdb-sandbox
-    ./run.sh
+    cd cloudberry/devops/sandbox
+    ./run.sh -c 2.0.0
     ```
-    - For latest Cloudberry DB release running across multiple containers
+    - For latest Apache Cloudberry release running across multiple containers
 
     ```shell
-    cd bootcamp/000-cbdb-sandbox
-    ./run.sh -m
+    cd cloudberry/devops/sandbox
+    ./run.sh -c 2.0.0 -m
     ```
     - For latest main branch running on a single container
 
     ```shell
-    cd bootcamp/000-cbdb-sandbox
+    cd cloudberry/devops/sandbox
     ./run.sh -c main
     ```
 
     - For latest main branch running across multiple containers
 
     ```shell
-    cd bootcamp/000-cbdb-sandbox
+    cd cloudberry/devops/sandbox
     ./run.sh -c main -m
     ```
 
-    Once the script finishes without error, the sandbox is built and running 
successfully. The `docker run` and `docker compose` commands use the --detach 
option allowing you to ssh or access the running CBDB instance remotely.
+    Once the script finishes without error, the sandbox is built and running 
successfully. The `docker run` and `docker compose` commands use the --detach 
option allowing you to ssh or access the running Apache Cloudberry instance 
remotely.
 
     Please review run.sh script for additional options (e.g. setting Timezone 
in running container, only building container). You can also execute `./run.sh 
-h` to see the usage.
 
 ## Connect to the database
 
 > [!NOTE]
-> When deploying the multi-container Cloudberry environment it may take extra 
time for the database to initialize, so you may need to wait a few minutes 
before you can execute the psql prompt successfully. You can run `docker logs 
cbdb-cdw -f` to see the current state of the database initialization process, 
you'll know the process is finished when you see the "Deployment Successful" 
output.
+> When deploying the multi-container Apache Cloudberry environment it may take 
extra time for the database to initialize, so you may need to wait a few 
minutes before you can execute the psql prompt successfully. You can run 
`docker logs cbdb-cdw -f` to see the current state of the database 
initialization process, you'll know the process is finished when you see the 
"Deployment Successful" output.
 
 You can now connect to the database and try some basic operations.
 
@@ -97,23 +122,38 @@ You can now connect to the database and try some basic 
operations.
 
     ```shell
     [gpadmin@cdw ~]$ psql  # Connects to the database with the default 
database name "gpadmin".
-    
+
     # psql (14.4, server 14.4)
     # Type "help" for help.
+    # Note: No password is required for the gpadmin user in this sandbox 
environment.
     ```
 
     ```sql
     gpadmin=# SELECT VERSION();  -- Checks the database version.
-            
+
     PostgreSQL 14.4 (Apache Cloudberry 1.0.0 build dev) on 
aarch64-unknown-linux-gnu, compiled by gcc (GCC) 10.2.1 20210130 (Red Hat 
10.2.1-11), 64-bit compiled on Oct 24 2023 10:24:28
     (1 row)
     ```
 
-Now you have a Apache Cloudberry and can continue with [Apache Cloudberry 
Tutorials Based on Docker 
Installation](https://github.com/apache/cloudberry-bootcamp/blob/main/101-cbdb-tutorials/README.md)!
 Enjoy!
+3. Alternatively, you can connect to the database directly from your host 
machine without entering the container:
 
-## Working with your Cloudberry Docker environment
+    The Apache Cloudberry coordinator port (default 5432) is mapped to port 
**15432** on your host machine. You can use the `psql` client on your host to 
connect directly:
 
-When working with the Cloudberry Docker environment there are a few commands 
that will be useful to you.
+    ```shell
+    # Connect from host machine
+    psql -h localhost -p 15432 -d postgres -U gpadmin
+    ```
+
+    > [!NOTE]
+    > - No password is required for the `gpadmin` user in this sandbox 
environment.
+    > - Make sure you have PostgreSQL client (`psql`) installed on your host 
machine.
+    > - The port mapping is: Container port `5432` → Host port `15432`
+
+Now you have an Apache Cloudberry and can continue with [Apache Cloudberry 
Tutorials](https://cloudberry.apache.org/docs/)! Enjoy!
+
+## Working with your Apache Cloudberry Docker environment
+
+When working with the Apache Cloudberry Docker environment there are a few 
commands that will be useful to you.
 
 **Stopping Your Single Container Deployment With Docker**
 
@@ -143,7 +183,7 @@ To stop the **multi-container** deployment and also remove 
the network and volum
 docker compose -f docker-compose-rockylinux9.yml down -v
 ```
 
-**Starting A Stopped Single Container Cloudberry Docker Deployment**
+**Starting A Stopped Single Container Apache Cloudberry Docker Deployment**
 
 If you've run any of the commands above that keep the Docker volumes persisted 
between shutting the containers down, you can use the following commands to 
bring that same deployment back up with it's previous state.
 
@@ -153,7 +193,7 @@ To start a **single container** deployment after it was 
shut down, you can simpl
 docker start cbdb-cdw
 ```
 
-**Starting A Stopped Multi-Container Cloudberry Docker Deployment**
+**Starting A Stopped Multi-Container Apache Cloudberry Docker Deployment**
 
 To start a **multi-container** deployment after it was shut down, you can run 
the following command.
 
@@ -162,10 +202,10 @@ docker compose -f docker-compose-rockylinux9.yml start
 ```
 
 > [!NOTE]
-> When starting a previously stopped Cloudberry Docker environment, you'll 
need to manually start the database back up. To do this, just run the following 
commands once the container(s) are back up and running. The `gpstart` command 
is used for starting the database, and -a is a flag saying to start the 
database without prompting (non-interactive).
+> When starting a previously stopped Apache Cloudberry Docker environment, 
you'll need to manually start the database back up. To do this, just run the 
following commands once the container(s) are back up and running. The `gpstart` 
command is used for starting the database, and -a is a flag saying to start the 
database without prompting (non-interactive).
 
 ```shell
 docker exec -it cbdb-cdw /bin/bash
 
 [gpadmin@cdw /] gpstart -a
-```
+```
\ No newline at end of file
diff --git a/devops/sandbox/configs/90-cbdb-limits.conf 
b/devops/sandbox/configs/90-cbdb-limits.conf
index d2bf601095b..33088f92278 100644
--- a/devops/sandbox/configs/90-cbdb-limits.conf
+++ b/devops/sandbox/configs/90-cbdb-limits.conf
@@ -1,3 +1,22 @@
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
 ######################
 # CBDB CONFIG PARAMS #
 ######################
diff --git a/devops/sandbox/configs/90-cbdb-sysctl.conf 
b/devops/sandbox/configs/90-cbdb-sysctl.conf
index ed806a5d8d1..9f0b7c576e4 100644
--- a/devops/sandbox/configs/90-cbdb-sysctl.conf
+++ b/devops/sandbox/configs/90-cbdb-sysctl.conf
@@ -1,3 +1,22 @@
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
 ######################
 # CBDB CONFIG PARAMS #
 ######################
diff --git a/devops/sandbox/configs/gpinitsystem_multinode 
b/devops/sandbox/configs/gpinitsystem_multinode
index ef96d730068..d6a46d4d410 100644
--- a/devops/sandbox/configs/gpinitsystem_multinode
+++ b/devops/sandbox/configs/gpinitsystem_multinode
@@ -1,9 +1,28 @@
-# FILE NAME: gpinitsystem_singlenode
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
+# FILE NAME: gpinitsystem_multinode
 
 # A configuration file is needed by the gpinitsystem utility.
-# This sample file initializes a Apache Cloudberry Single Node
-# Edition (SNE) system with one coordinator and  two segment instances
-# on the local host. This file is referenced when you run gpinitsystem.
+# This sample file initializes an Apache Cloudberry multi-node cluster
+# with one coordinator, one standby coordinator, and segment instances
+# across multiple hosts. This file is referenced when you run gpinitsystem.
 
 ################################################
 # REQUIRED PARAMETERS
diff --git a/devops/sandbox/configs/gpinitsystem_singlenode 
b/devops/sandbox/configs/gpinitsystem_singlenode
index baaaebfba83..f221d81938c 100644
--- a/devops/sandbox/configs/gpinitsystem_singlenode
+++ b/devops/sandbox/configs/gpinitsystem_singlenode
@@ -1,3 +1,22 @@
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
 # FILE NAME: gpinitsystem_singlenode
 
 # A configuration file is needed by the gpinitsystem utility.
diff --git a/devops/sandbox/configs/init_system.sh 
b/devops/sandbox/configs/init_system.sh
index 73dafa9b001..455341ff46c 100755
--- a/devops/sandbox/configs/init_system.sh
+++ b/devops/sandbox/configs/init_system.sh
@@ -1,74 +1,130 @@
 #!/bin/bash
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
 ## ======================================================================
-## Container initialization script
+## Container initialization script for Apache Cloudberry Sandbox
 ## ======================================================================
 
 # ----------------------------------------------------------------------
 # Start SSH daemon and setup for SSH access
 # ----------------------------------------------------------------------
 # The SSH daemon is started to allow remote access to the container via
-# SSH. This is useful for development and debugging purposes. If the SSH
-# daemon fails to start, the script exits with an error.
+# SSH. This is useful for development and debugging purposes.
 # ----------------------------------------------------------------------
-if ! sudo /usr/sbin/sshd; then
+
+# Ensure SSH directory exists (created at build time; ignore errors if any)
+mkdir -p /run/sshd 2>/dev/null || true
+
+# Start SSH daemon directly (binary is setuid-root in the image)
+if ! /usr/sbin/sshd; then
     echo "Failed to start SSH daemon" >&2
     exit 1
 fi
 
+# Give SSH daemon time to start
+sleep 5
+
 # ----------------------------------------------------------------------
 # Remove /run/nologin to allow logins
 # ----------------------------------------------------------------------
 # The /run/nologin file, if present, prevents users from logging into
 # the system. This file is removed to ensure that users can log in via SSH.
 # ----------------------------------------------------------------------
-sudo rm -rf /run/nologin
-
-# ## Set gpadmin ownership - Clouberry install directory and supporting
-# ## cluster creation files.
-sudo chown -R gpadmin.gpadmin /usr/local/cloudberry-db \
-                              /tmp/gpinitsystem_singlenode \
-                              /tmp/gpinitsystem_multinode \
-                              /tmp/gpdb-hosts \
-                              /tmp/multinode-gpinit-hosts \
-                              /tmp/faa.tar.gz \
-                              /tmp/smoke-test.sh
+rm -f /run/nologin 2>/dev/null || true
 
 # ----------------------------------------------------------------------
 # Configure passwordless SSH access for 'gpadmin' user
 # ----------------------------------------------------------------------
-# The script sets up SSH key-based authentication for the 'gpadmin' user,
-# allowing passwordless SSH access. It generates a new SSH key pair if one
-# does not already exist, and configures the necessary permissions.
+# SSH keys are already generated and configured in the Docker image at
+# build time. All containers from the same image share the same keypair,
+# which allows passwordless SSH between containers.
+#
+# This is ONLY suitable for sandbox/testing environments.
+# DO NOT use this approach in production.
 # ----------------------------------------------------------------------
-mkdir -p /home/gpadmin/.ssh
-chmod 700 /home/gpadmin/.ssh
 
+# Verify SSH keys exist (they should be in the image already)
 if [ ! -f /home/gpadmin/.ssh/id_rsa ]; then
-    ssh-keygen -t rsa -b 4096 -C gpadmin -f /home/gpadmin/.ssh/id_rsa -P "" > 
/dev/null 2>&1
+    echo "ERROR: SSH keys not found in image. This should not happen."
+    exit 1
 fi
 
-cat /home/gpadmin/.ssh/id_rsa.pub >> /home/gpadmin/.ssh/authorized_keys
-chmod 600 /home/gpadmin/.ssh/authorized_keys
-
-# Add the container's hostname to the known_hosts file to avoid SSH warnings
-ssh-keyscan -t rsa cdw > /home/gpadmin/.ssh/known_hosts 2>/dev/null
-
-# Source Cloudberry environment variables and set
-# COORDINATOR_DATA_DIRECTORY
-source /usr/local/cloudberry-db/greenplum_path.sh
-export COORDINATOR_DATA_DIRECTORY=/data0/database/coordinator/gpseg-1
+# Add container hostnames to the known_hosts file to avoid SSH warnings
+if [[ "${MULTINODE:-false}" == "true" ]]; then
+    ssh-keyscan -t rsa cdw scdw sdw1 sdw2 > /home/gpadmin/.ssh/known_hosts 
2>/dev/null || true
+else
+    ssh-keyscan -t rsa cdw > /home/gpadmin/.ssh/known_hosts 2>/dev/null || true
+fi
+chmod 600 /home/gpadmin/.ssh/known_hosts
+chown gpadmin:gpadmin /home/gpadmin/.ssh/known_hosts
+
+# Load Cloudberry/Greenplum environment with fallback, then ensure PATH
+if [ -f "/usr/local/cloudberry-db/cloudberry-env.sh" ]; then
+  # shellcheck disable=SC1091
+  . /usr/local/cloudberry-db/cloudberry-env.sh
+elif [ -f "/usr/local/cloudberry-db/greenplum_path.sh" ]; then
+  # shellcheck disable=SC1091
+  . /usr/local/cloudberry-db/greenplum_path.sh
+else
+  # Fallback: minimal env to find gp* tools
+  export GPHOME="/usr/local/cloudberry-db"
+fi
+# Ensure coordinator data dir variable is set
+export 
COORDINATOR_DATA_DIRECTORY="${COORDINATOR_DATA_DIRECTORY:-/data0/database/coordinator/gpseg-1}"
+# Ensure PATH includes Cloudberry bin
+if [ -d "/usr/local/cloudberry-db/bin" ]; then
+  case ":$PATH:" in
+    *":/usr/local/cloudberry-db/bin:"*) : ;;
+    *) export PATH="/usr/local/cloudberry-db/bin:$PATH" ;;
+  esac
+fi
 
 # Initialize single node Cloudberry cluster
-if [[ $MULTINODE == "false" && $HOSTNAME == "cdw" ]]; then
+if [[ "${MULTINODE:-false}" == "false" && "$HOSTNAME" == "cdw" ]]; then
     gpinitsystem -a \
                  -c /tmp/gpinitsystem_singlenode \
                  -h /tmp/gpdb-hosts \
                  --max_connections=100
 # Initialize multi node Cloudberry cluster
-elif [[ $MULTINODE == "true" && $HOSTNAME == "cdw" ]]; then
-    sshpass -p "cbdb@123" ssh-copy-id -o StrictHostKeyChecking=no sdw1
-    sshpass -p "cbdb@123" ssh-copy-id -o StrictHostKeyChecking=no sdw2
-    sshpass -p "cbdb@123" ssh-copy-id -o StrictHostKeyChecking=no scdw
+elif [[ "${MULTINODE:-false}" == "true" && "$HOSTNAME" == "cdw" ]]; then
+    # Wait for other containers' SSH to become reachable (max 120s per host)
+    for host in sdw1 sdw2 scdw; do
+        MAX_WAIT=120
+        WAITED=0
+        until ssh -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o 
ConnectTimeout=5 gpadmin@${host} "echo Connected to ${host}" 2>/dev/null; do
+            if [ $WAITED -ge $MAX_WAIT ]; then
+                echo "Timeout waiting for SSH on ${host}"
+                exit 1
+            fi
+            sleep 5
+            WAITED=$((WAITED+5))
+        done
+    done
+
+    # Clean up any existing data directories to avoid conflicts
+    rm -rf /data0/database/coordinator/* /data0/database/primary/* 
/data0/database/mirror/* 2>/dev/null || true
+
+    # Ensure database directories exist with proper permissions
+    mkdir -p /data0/database/coordinator /data0/database/primary 
/data0/database/mirror
+    chmod -R 700 /data0/database
+
     gpinitsystem -a \
                  -c /tmp/gpinitsystem_multinode \
                  -h /tmp/multinode-gpinit-hosts \
@@ -77,19 +133,23 @@ elif [[ $MULTINODE == "true" && $HOSTNAME == "cdw" ]]; then
     printf "sdw1\nsdw2\n" >> /tmp/gpdb-hosts
 fi
 
-if [ $HOSTNAME == "cdw" ]; then
-     ## Allow any host access the Cloudberry Cluster
-     echo 'host all all 0.0.0.0/0 trust' >> 
/data0/database/coordinator/gpseg-1/pg_hba.conf
-     gpstop -u
-
-     psql -d template1 \
-          -c "ALTER USER gpadmin PASSWORD 'cbdb@123'"
+# ----------------------------------------------------------------------
+# Post-initialization configuration (applies to both single and multi-node)
+# ----------------------------------------------------------------------
+# Configure pg_hba.conf to allow passwordless access from any host,
+# remove password requirement for gpadmin user, and display cluster info.
+# This section runs on the coordinator node after cluster initialization.
+# ----------------------------------------------------------------------
+if [ "$HOSTNAME" == "cdw" ]; then
+    ## Allow any host access the Cloudberry Cluster
+    echo 'host all all 0.0.0.0/0 trust' >> 
/data0/database/coordinator/gpseg-1/pg_hba.conf
+    gpstop -u
 
-     cat <<-'EOF'
+    cat <<-'EOF'
 
 ======================================================================
-         ____ _                 _ _                          
-        / ___| | ___  _   _  __| | |__   ___ _ __ _ __ _   _  
+         ____ _                 _ _
+        / ___| | ___  _   _  __| | |__   ___ _ __ _ __ _   _
        | |   | |/ _ \| | | |/ _` | '_ \ / _ \ '__| '__| | | |
        | |___| | (_) | |_| | (_| | |_) |  __/ |  | |  | |_| |
         \____|_|\___/ \__,_|\__,_|_.__/ \___|_|  |_|   \__, |
@@ -97,7 +157,7 @@ if [ $HOSTNAME == "cdw" ]; then
 ======================================================================
 EOF
 
-     cat <<-'EOF'
+    cat <<-'EOF'
 
 ======================================================================
 Sandbox: Apache Cloudberry Cluster details
@@ -105,14 +165,14 @@ Sandbox: Apache Cloudberry Cluster details
 
 EOF
 
-     echo "Current time: $(date)"
-     source /etc/os-release
-     echo "OS Version: ${NAME} ${VERSION}"
+    echo "Current time: $(date)"
+    source /etc/os-release
+    echo "OS Version: ${NAME} ${VERSION}"
 
-     ## Set gpadmin password, display version and cluster configuration
-     psql -P pager=off -d template1 -c "SELECT VERSION()"
-     psql -P pager=off -d template1 -c "SELECT * FROM gp_segment_configuration 
ORDER BY dbid"
-     psql -P pager=off -d template1 -c "SHOW optimizer"
+    ## Display version and cluster configuration
+    psql -P pager=off -d template1 -c "SELECT VERSION()"
+    psql -P pager=off -d template1 -c "SELECT * FROM gp_segment_configuration 
ORDER BY dbid"
+    psql -P pager=off -d template1 -c "SHOW optimizer"
 fi
 
 echo """
diff --git a/devops/sandbox/configs/multinode-gpinit-hosts 
b/devops/sandbox/configs/multinode-gpinit-hosts
index a85b4c3f097..6da00621266 100644
--- a/devops/sandbox/configs/multinode-gpinit-hosts
+++ b/devops/sandbox/configs/multinode-gpinit-hosts
@@ -1,2 +1,2 @@
 sdw1
-sdw2
\ No newline at end of file
+sdw2
diff --git a/devops/sandbox/docker-compose-rockylinux9.yml 
b/devops/sandbox/docker-compose-rockylinux9.yml
index 37cccc98ca6..c37471898d1 100644
--- a/devops/sandbox/docker-compose-rockylinux9.yml
+++ b/devops/sandbox/docker-compose-rockylinux9.yml
@@ -1,3 +1,23 @@
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
+
 services:
   cbdb-coordinator:
     container_name: cbdb-cdw
@@ -11,6 +31,9 @@ services:
         ipv4_address: 10.5.0.10
     environment:
       MULTINODE: "true"
+    volumes:
+      - /sys/fs/cgroup:/sys/fs/cgroup:ro
+
   cbdb-standby-coordinator:
     container_name: cbdb-scdw
     image: cbdb-${CODEBASE_VERSION}:${OS_VERSION}
@@ -19,6 +42,10 @@ services:
     networks:
       interconnect:
         ipv4_address: 10.5.0.11
+    environment:
+      MULTINODE: "true"
+    volumes:
+      - /sys/fs/cgroup:/sys/fs/cgroup:ro
   cbdb-segment-host-1:
     container_name: cbdb-sdw1
     image: cbdb-${CODEBASE_VERSION}:${OS_VERSION}
@@ -27,6 +54,10 @@ services:
     networks:
       interconnect:
         ipv4_address: 10.5.0.12
+    environment:
+      MULTINODE: "true"
+    volumes:
+      - /sys/fs/cgroup:/sys/fs/cgroup:ro
   cbdb-segment-host-2:
     container_name: cbdb-sdw2
     image: cbdb-${CODEBASE_VERSION}:${OS_VERSION}
@@ -35,6 +66,11 @@ services:
     networks:
       interconnect:
         ipv4_address: 10.5.0.13
+    environment:
+      MULTINODE: "true"
+    volumes:
+      - /sys/fs/cgroup:/sys/fs/cgroup:ro
+
 networks:
   interconnect:
     name: cbdb-interconnect
diff --git a/devops/sandbox/run.sh b/devops/sandbox/run.sh
index d42b55e1ecf..5e1888498ab 100755
--- a/devops/sandbox/run.sh
+++ b/devops/sandbox/run.sh
@@ -1,5 +1,24 @@
-#!/bin/bash
-set -eu
+#!/usr/bin/env bash
+# --------------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to You under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# --------------------------------------------------------------------
+set -euo pipefail
 
 # Default values
 DEFAULT_OS_VERSION="rockylinux9"
@@ -19,7 +38,7 @@ 
PIP_INDEX_URL_VAR="${PIP_INDEX_URL_VAR:-$DEFAULT_PIP_INDEX_URL_VAR}"
 # Function to display help message
 function usage() {
     echo "Usage: $0 [-o <os_version>] [-c <codebase_version>] [-b] [-m]"
-    echo "  -c  Codebase version (valid values: main, or determined from 
release zip file name)"
+    echo "  -c  Codebase version (valid values: main, or other available 
version like 2.0.0)"
     echo "  -t  Timezone (default: America/Los_Angeles, or set via 
TIMEZONE_VAR environment variable)"
     echo "  -p  Python Package Index (PyPI) (default: https://pypi.org/simple, 
or set via PIP_INDEX_URL_VAR environment variable)"
     echo "  -b  Build only, do not run the container (default: false, or set 
via BUILD_ONLY environment variable)"
@@ -64,23 +83,10 @@ if [[ "${MULTINODE}" == "true" && "${BUILD_ONLY}" == "true" 
]]; then
     exit 1
 fi
 
-# If CODEBASE_VERSION is not specified, determine it from the file name
+# CODEBASE_VERSION must be specified via -c argument or CODEBASE_VERSION 
environment variable
 if [[ -z "$CODEBASE_VERSION" ]]; then
-    BASE_CODEBASE_FILE=$(ls configs/cloudberrydb-*.zip 2>/dev/null)
-
-    if [[ -z "$BASE_CODEBASE_FILE" ]]; then
-        echo "Error: No configs/cloudberrydb-*.zip file found and codebase 
version not specified."
-        exit 1
-    fi
-
-    CODEBASE_FILE=$(basename ${BASE_CODEBASE_FILE})
-
-    if [[ $CODEBASE_FILE =~ cloudberrydb-([0-9]+\.[0-9]+\.[0-9]+)\.zip ]]; then
-        CODEBASE_VERSION="${BASH_REMATCH[1]}"
-    else
-        echo "Error: Cannot extract version from file name $CODEBASE_FILE"
-        exit 1
-    fi
+    echo "Error: CODEBASE_VERSION must be specified via environment variable 
or '-c' command line parameter."
+    usage
 fi
 
 # Validate OS_VERSION and map to appropriate Docker image
@@ -104,6 +110,7 @@ fi
 if [[ "${CODEBASE_VERSION}" = "main"  ]]; then
     DOCKERFILE=Dockerfile.${CODEBASE_VERSION}.${OS_VERSION}
 
+    # Single image build
     docker build --file ${DOCKERFILE} \
                  --build-arg TIMEZONE_VAR="${TIMEZONE_VAR}" \
                  --tag cbdb-${CODEBASE_VERSION}:${OS_VERSION} .
@@ -112,7 +119,6 @@ else
 
     docker build --file ${DOCKERFILE} \
                  --build-arg TIMEZONE_VAR="${TIMEZONE_VAR}" \
-                 --build-arg PIP_INDEX_URL_VAR="${PIP_INDEX_URL_VAR}" \
                  --build-arg CODEBASE_VERSION_VAR="${CODEBASE_VERSION}" \
                  --tag cbdb-${CODEBASE_VERSION}:${OS_VERSION} .
 fi
diff --git a/pom.xml b/pom.xml
index d6913ec5053..6d33d7e9de5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1748,6 +1748,10 @@ code or new licensing patterns.
             -->
             <exclude>devops/build/packaging/deb/ubuntu22.04/**</exclude>
 
+            <!-- Exclude the multinode hosts configuration file for Cloudberry 
sandbox
+            -->
+            <exclude>devops/sandbox/configs/multinode-gpinit-hosts</exclude>
+
           </excludes>
 
           <!--


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to