CI: Enable build of nrUE on Jetson with CUDA support

Add new Dockerfiles to enable building nrUE and gNB with CUDA support on Jetson.
Compared to the standard build, these images use Ubuntu 22.04 instead of Ubuntu
24.04. This change is required because CUDA 12.2.0 runtime and development
images are only available for Ubuntu 22.04.

To build the nrUE and gNB image with CUDA support, run the following commands:

    docker build  --target ran-base-cuda --tag ran-base-cuda:latest --file docker/Dockerfile.base.cuda.ubuntu .
    docker build  --target ran-build-cuda --tag ran-build-cuda:latest --file docker/Dockerfile.build.cuda.ubuntu .
    docker build  --target oai-gnb --tag oai-gnb:test --file docker/Dockerfile.gNB.cuda.ubuntu .
    docker build  --target oai-nr-ue --tag oai-nr-ue:test --file docker/Dockerfile.nrUE.cuda.ubuntu .

A new XML file was added to build images on Jetson3 and push images with CUDA
support, using the prefix "armv8_cuda".
This commit is contained in:
Jaroslava Fiedlerova
2026-03-02 17:25:08 +01:00
committed by Robert Schmidt
parent 5c9a73304d
commit f3ab9e3ae1
6 changed files with 410 additions and 15 deletions

View File

@@ -178,9 +178,20 @@ class Containerize():
dockerfileprefix = '.ubuntu'
baseImage = 'ran-base'
baseTag = 'develop'
buildImage = 'ran-build'
forceBaseImageBuild = False
imageTag = 'develop'
result = re.search('native_cuda_armv8', self.imageKind)
if result is not None:
baseImage = 'ran-base-cuda'
buildImage = 'ran-build-cuda'
dockerfileprefix = '.cuda.ubuntu'
# we always build the ran-build image with all targets
# Creating a tupple with the imageName, the DockerFile prefix pattern, targetName and sanitized option
imageNames = [('ran-build', 'build', 'ran-build', '')]
imageNames = [(buildImage, 'build', f'{buildImage}', '')]
result = re.search('eNB', self.imageKind)
if result is not None:
imageNames.append(('oai-enb', 'eNB', 'oai-enb', ''))
@@ -220,13 +231,13 @@ class Containerize():
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
imageNames.append(('oai-nr-cuup', 'nr-cuup', 'oai-nr-cuup', ''))
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
result = re.search('native_cuda_armv8', self.imageKind)
if result is not None:
imageNames.append(('oai-gnb', 'gNB', 'oai-gnb', ''))
imageNames.append(('oai-nr-ue', 'nrUE', 'oai-nr-ue', ''))
cmd.cd(lSourcePath)
baseImage = 'ran-base'
baseTag = 'develop'
forceBaseImageBuild = False
imageTag = 'develop'
if (self.merge):
imageTag = 'ci-temp'
if self.targetBranch == 'develop':
@@ -254,17 +265,17 @@ class Containerize():
# On when the base image docker file is being modified.
if forceBaseImageBuild:
cmd.run(f"docker image rm {baseImage}:{baseTag}")
logfile = f'{lSourcePath}/cmake_targets/log/ran-base.docker.log'
logfile = f'{lSourcePath}/cmake_targets/log/{baseImage}.docker.log'
option = f" --build-arg UBUNTU_IMAGE={DEFAULT_REGISTRY}/{ubuntuImage}"
cmd.run(f"docker build --target {baseImage} --tag {baseImage}:{baseTag} --file docker/Dockerfile.base{dockerfileprefix} {option} . &> {logfile}", timeout=1600)
t = ("ran-base", archiveArtifact(cmd, ctx, logfile))
t = (baseImage, archiveArtifact(cmd, ctx, logfile))
log_files.append(t)
# First verify if the base image was properly created.
ret = cmd.run(f"docker image inspect --format=\'Size = {{{{.Size}}}} bytes\' {baseImage}:{baseTag}")
allImagesSize = {}
if ret.returncode != 0:
logging.error('\u001B[1m Could not build properly ran-base\u001B[0m')
logging.error(f'\u001B[1m Could not build properly {baseImage}\u001B[0m')
# Recover the name of the failed container?
cmd.run(f"docker ps --quiet --filter \"status=exited\" -n1 | xargs --no-run-if-empty docker rm -f")
cmd.run(f"docker image prune --force")
@@ -277,10 +288,10 @@ class Containerize():
if result is not None:
size = float(result.group("size")) / 1000000
imageSizeStr = f'{size:.1f}'
logging.debug(f'\u001B[1m ran-base size is {imageSizeStr} Mbytes\u001B[0m')
allImagesSize['ran-base'] = f'{imageSizeStr} Mbytes'
logging.debug(f'\u001B[1m {baseImage} size is {imageSizeStr} Mbytes\u001B[0m')
allImagesSize[baseImage] = f'{imageSizeStr} Mbytes'
else:
logging.debug('ran-base size is unknown')
logging.debug(f'{baseImage} size is unknown')
# Build the target image(s)
status = True
@@ -291,11 +302,11 @@ class Containerize():
cmd.run(f'sed -i -e "s#{baseImage}:latest#{baseImage}:{baseTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
# target images should use the proper ran-build image
if image != 'ran-build' and "-asan" in name:
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
cmd.run(f'sed -i -e "s#{buildImage}:latest#{buildImage}-asan:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif "fhi72" in name or name == "oai-nr-oru":
cmd.run(f'sed -i -e "s#ran-build-fhi72:latest#ran-build-fhi72:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
elif image != 'ran-build':
cmd.run(f'sed -i -e "s#ran-build:latest#ran-build:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
cmd.run(f'sed -i -e "s#{buildImage}:latest#{buildImage}:{imageTag}#" docker/Dockerfile.{pattern}{dockerfileprefix}')
if image == 'oai-gnb-aerial':
cmd.run('cp -f /opt/nvidia-ipc/nvipc_src.2026.01.07.tar.gz .')
logfile = f'{lSourcePath}/cmake_targets/log/{name}.docker.log'

View File

@@ -0,0 +1,28 @@
<!-- SPDX-License-Identifier: LicenseRef-CSSL-1.0 -->
<testCaseList>
<htmlTabRef>build-cuda-tab</htmlTabRef>
<htmlTabName>Build Container Images for ARM with CUDA</htmlTabName>
<htmlTabIcon>wrench</htmlTabIcon>
<testCase>
<class>Create_Workspace</class>
<desc>Create new Workspace for server 0</desc>
<node>jetson3-oai</node>
</testCase>
<testCase>
<class>Build_Image</class>
<desc>Build all Images</desc>
<node>jetson3-oai</node>
<kind>native_cuda_armv8</kind>
</testCase>
<testCase>
<class>Push_Local_Registry</class>
<desc>Push Images to Local Registry</desc>
<node>jetson3-oai</node>
<tag_prefix>armv8_cuda_</tag_prefix>
</testCase>
</testCaseList>

View File

@@ -0,0 +1,76 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 24.04
#
#---------------------------------------------------------------------
FROM nvidia/cuda:12.2.0-devel-ubuntu22.04 AS ran-base-cuda
ARG NEEDED_GIT_PROXY
ARG TARGETARCH
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Paris
ENV BUILD_UHD_FROM_SOURCE=True
ENV UHD_VERSION=4.8.0.0
#install developers pkg/repo
RUN apt-get update && \
apt-get upgrade --yes && \
apt-get install --yes \
#gcc needed for build_oai
build-essential \
ccache \
psmisc \
git \
#use gcc-12 to avoid problems of default gcc-11 in FlexRIC
gcc-12 \
g++-12 \
xxd \
libpcre2-dev \
python3-dev \
bison \
flex \
m4 \
# python3-pip for conf template generation
python3-pip \
wget \
flatbuffers-compiler \
libflatbuffers-dev \
libnanomsg-dev && \
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 100 --slave /usr/bin/g++ g++ /usr/bin/g++-12 && \
pip3 install --ignore-installed pyyaml
# Add "Tini - A tiny but valid init for containers", https://github.com/krallin/tini
# it will be copied into target containers, to print exit numbers and handle signals properly
ENV TINI_VERSION=v0.19.0
RUN wget https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini-${TARGETARCH} -O /tini && chmod +x /tini
ENV YQ_VERSION=v4.2.0
RUN wget https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_${TARGETARCH} -O /usr/local/bin/yq &&\
chmod +x /usr/local/bin/yq
# In some network environments, GIT proxy is required
RUN /bin/bash -c "if [[ -v NEEDED_GIT_PROXY ]]; then git config --global http.proxy $NEEDED_GIT_PROXY; fi"
# Copying only the needed files to create ran-base
WORKDIR /oai-ran/cmake_targets/tools
COPY cmake_targets/tools/build_helper \
cmake_targets/tools/uhd-4.x-tdd-patch.diff \
./
WORKDIR /oai-ran/cmake_targets
COPY cmake_targets/build_oai .
WORKDIR /oai-ran
COPY oaienv .
#run build_oai -I to get the builder image
RUN /bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai -I -w USRP -w BLADERF --install-optional-packages

View File

@@ -0,0 +1,58 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 24.04
#
#---------------------------------------------------------------------
FROM ran-base-cuda:latest AS ran-build-cuda
ARG BUILD_OPTION
ARG E2AP_VERSION=E2AP_V3
ARG KPM_VERSION=KPM_V3_00
RUN rm -Rf /oai-ran
WORKDIR /oai-ran
COPY . .
# build all targets so final targets can be created afterwards
RUN \
# Mount CCache cache direrctory
--mount=type=cache,target=/root/.cache/ccache/ \
# Mount CPM package cache
--mount=type=cache,target=/root/.cache/cpm/ \
/bin/sh oaienv && \
cd cmake_targets && \
mkdir -p log && \
./build_oai -c --ninja \
--eNB --gNB --RU --UE --nrUE \
--build-lib "telnetsrv enbscope uescope nrscope ldpc_cuda" \
-w USRP -t Ethernet -w BLADERF \
--build-e2 --cmake-opt -DKPM_VERSION=$KPM_VERSION --cmake-opt -DE2AP_VERSION=$E2AP_VERSION \
--cmake-opt -DOAI_VRTSIM_TAPS_CLIENT=ON \
--cmake-opt -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda-12.2 \
--noavx512 \
--build-tool-opt -k10 \
--cmake-opt -DCMAKE_C_FLAGS="-Werror" --cmake-opt -DCMAKE_CXX_FLAGS="-Werror" $BUILD_OPTION && \
# Mainly to see if the sanitize option was perfectly executed
echo "---- ldd on executables ----" && \
ldd ran_build/build/*softmodem* ran_build/build/nr-cuup ran_build/build/oairu && \
echo "---- ldd on shared libraries ----" && \
ldd ran_build/build/*.so
## Build FlexRIC for SM Models
RUN \
# Mount CCache cache direrctory
--mount=type=cache,target=/root/.cache/ccache/ \
mkdir -p openair2/E2AP/flexric/build && \
cd openair2/E2AP/flexric/build && \
cmake -GNinja -DCMAKE_BUILD_TYPE=Release \
-DKPM_VERSION=$KPM_VERSION \
-DCMAKE_C_COMPILER=gcc-12 \
-DCMAKE_CXX_COMPILER=g++-12 .. \
-DE2AP_VERSION=$E2AP_VERSION .. && \
ninja && \
ninja install

View File

@@ -0,0 +1,115 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 24.04
#
#---------------------------------------------------------------------
ARG UBUNTU_IMAGE=ubuntu:noble
FROM ran-base-cuda:latest AS gnb-base
FROM ran-build-cuda:latest AS gnb-build
#start from scratch for target executable
FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04 AS oai-gnb
ARG BUILD_OPTION
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Paris
RUN apt-get update && \
apt-get upgrade --yes && \
apt-get install --yes \
software-properties-common \
procps \
libsctp1 \
libboost-chrono1.74.0 \
libboost-date-time1.74.0 \
libboost-filesystem1.74.0 \
libboost-regex1.74.0 \
libboost-serialization1.74.0 \
libboost-thread1.74.0 \
libboost-system1.74.0 \
libboost-program-options1.74.0 \
tzdata \
libconfig9 \
openssl \
net-tools \
iperf \
iperf3 \
iproute2 \
iputils-ping \
gdb \
python3 \
python3-six \
python3-requests \
libusb-1.0-0 \
libyaml-cpp-dev \
libnanomsg5 && \
# if the --sanitize option was used to build, additional packages are required
/bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \
libasan8 \
libubsan1; fi' && \
apt-get clean -y && \
rm -rf /var/lib/apt/lists/*
WORKDIR /opt/oai-gnb/bin
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/nr-softmodem ./
COPY ./docker/scripts/gnb_entrypoint.sh ./entrypoint.sh
COPY ./docker/scripts/check-prach-io.sh ./check-prach-io.sh
COPY --from=gnb-build \
/oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
/oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ci.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_bearer.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_rrc.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_o1.so \
/oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
# Now we are copying from builder-image the UHD files.
COPY --from=gnb-base /usr/local/bin/uhd_find_devices /usr/local/bin
COPY --from=gnb-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib
COPY --from=gnb-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-gnb/bin
## Copy E2 SM models
COPY --from=gnb-build /usr/local/lib/flexric /usr/local/lib/flexric
RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \
ldconfig && \
echo "---- ldd on nr-softmodem ----" && \
ldd /opt/oai-gnb/bin/nr-softmodem && \
echo "---- ldd on shared libraries ----" && \
ldd /usr/local/lib/liboai_eth_transpro.so \
/usr/local/lib/librfsimulator.so \
/usr/local/lib/liboai_usrpdevif.so \
/usr/local/lib/libcoding.so \
/usr/local/lib/libparams_libconfig.so \
/usr/local/lib/libdfts.so \
/usr/local/lib/libldpc*.so \
/usr/local/lib/libtelnetsrv.so \
/usr/local/lib/libtelnetsrv_ci.so \
/usr/local/lib/libuhd.so.4.8.0
WORKDIR /opt/oai-gnb
#EXPOSE 2152/udp # S1U, GTP/UDP
#EXPOSE 22100/tcp # ?
#EXPOSE 36412/udp # S1C, SCTP/UDP
#EXPOSE 36422/udp # X2C, SCTP/UDP
#EXPOSE 50000/udp # IF5 / ORI (control)
#EXPOSE 50001/udp # IF5 / ECPRI (data)
COPY --from=gnb-base /usr/local/bin/yq /usr/local/bin/yq
COPY --from=gnb-base /tini /tini
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-gnb/bin/entrypoint.sh"]
CMD ["/opt/oai-gnb/bin/nr-softmodem"]

View File

@@ -0,0 +1,107 @@
# SPDX-License-Identifier: LicenseRef-CSSL-1.0
#---------------------------------------------------------------------
#
# Dockerfile for the Open-Air-Interface BUILD service
# Valid for Ubuntu 24.04
#
#---------------------------------------------------------------------
FROM ran-base-cuda:latest AS nr-ue-base
FROM ran-build-cuda:latest AS nr-ue-build
#start from scratch for target executable
FROM nvidia/cuda:12.2.0-runtime-ubuntu22.04 AS oai-nr-ue
ARG BUILD_OPTION
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Europe/Paris
RUN apt-get update && \
apt-get upgrade --yes && \
apt-get install --yes \
arping \
software-properties-common \
procps \
libsctp1 \
libboost-chrono1.74.0 \
libboost-date-time1.74.0 \
libboost-filesystem1.74.0 \
libboost-regex1.74.0 \
libboost-serialization1.74.0 \
libboost-thread1.74.0 \
libboost-system1.74.0 \
libboost-program-options1.74.0 \
tzdata \
libconfig9 \
openssl \
net-tools \
gdb \
python3 \
python3-six \
python3-requests \
libusb-1.0-0 \
iputils-ping \
iproute2 \
iperf3 \
iperf \
libyaml-cpp-dev \
libnanomsg5 && \
# if the --sanitize option was used to build, additional packages are required
/bin/bash -c 'if [[ "$BUILD_OPTION" = "--sanitize" ]]; then DEBIAN_FRONTEND=noninteractive apt-get install --yes \
libasan8 \
libubsan1; fi' && \
apt-get clean -y && \
rm -rf /var/lib/apt/lists/*
WORKDIR /opt/oai-nr-ue/bin
COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/nr-uesoftmodem \
./
COPY ./docker/scripts/nr_ue_entrypoint.sh ./entrypoint.sh
WORKDIR /opt/oai-nr-ue/etc
COPY --from=nr-ue-build \
/oai-ran/cmake_targets/ran_build/build/liboai_eth_transpro.so \
/oai-ran/cmake_targets/ran_build/build/librfsimulator.so \
/oai-ran/cmake_targets/ran_build/build/liboai_usrpdevif.so \
/oai-ran/cmake_targets/ran_build/build/libcoding.so \
/oai-ran/cmake_targets/ran_build/build/libparams_libconfig.so \
/oai-ran/cmake_targets/ran_build/build/libdfts.so \
/oai-ran/cmake_targets/ran_build/build/libldpc*.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_ciUE.so \
/oai-ran/cmake_targets/ran_build/build/libtelnetsrv_5Gue.so \
/oai-ran/cmake_targets/ran_build/build/libparams_yaml.so \
/oai-ran/cmake_targets/ran_build/build/libvrtsim.so \
/usr/local/lib/
# Now we are copying from builder-image the UHD files.
COPY --from=nr-ue-base /usr/local/bin/uhd_find_devices /usr/local/bin
COPY --from=nr-ue-base /usr/local/lib/libuhd.so.4.8.0 /usr/local/lib
COPY --from=nr-ue-base /usr/local/lib/uhd/utils/uhd_images_downloader.py /opt/oai-nr-ue/bin
RUN /bin/bash -c "ln -s /usr/local/lib/liboai_usrpdevif.so /usr/local/lib/liboai_device.so" && \
ldconfig && \
echo "---- ldd on nr-uesoftmodem ----" && \
ldd /opt/oai-nr-ue/bin/nr-uesoftmodem && \
echo "---- ldd on shared libraries ----" && \
ldd /usr/local/lib/liboai_eth_transpro.so \
/usr/local/lib/librfsimulator.so \
/usr/local/lib/liboai_usrpdevif.so \
/usr/local/lib/libcoding.so \
/usr/local/lib/libparams_libconfig.so \
/usr/local/lib/libdfts.so \
/usr/local/lib/libldpc*.so \
/usr/local/lib/libtelnetsrv.so \
/usr/local/lib/libtelnetsrv_ciUE.so \
/usr/local/lib/libtelnetsrv_5Gue.so \
/usr/local/lib/libuhd.so.4.8.0
WORKDIR /opt/oai-nr-ue
COPY --from=nr-ue-base /usr/local/bin/yq /usr/local/bin/yq
COPY --from=nr-ue-base /tini /tini
CMD ["/opt/oai-nr-ue/bin/nr-uesoftmodem"]
ENTRYPOINT ["/tini", "-v", "--", "/opt/oai-nr-ue/bin/entrypoint.sh"]