Files
openairinterface5g/docker
Jaroslava Fiedlerova e6105b9d6a Merge remote-tracking branch 'origin/recordDb' into integration_2026_w10 (!3800)
Add tracer to record configured events to database

This extends the functionality provided by record in that it allows
collection of data into a Clickhouse database, allowing aggregation of
data from gNB and UE for functions like channel estimation for PUSCH
transmissions that did not decode successfully at the gNB.

It is intended to be used in conjunction with Aerial Data Lake but is
not limited to it. Data access is simpler than in !3462 (merged), but
could be improved using the metadata approach from !3462 (merged).

Usage is similar to the exsting record tracer:

        docker exec -it oai-nr-ue bash -c "record_db -on UE -off VCD -ch-droptables -off UE_PHY_UL_TICK -off UE_PHY_DL_TICK -off UE_PHY_PDSCH_IQ"

Which outputs recorded data every 5 seconds:

        17:35:40.945037 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:21   name:UE_PHY_INITIATE_RA_PROCEDURE    has_frame_slot:false columns:5
        17:35:40.945924 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:26   name:NRUE_PHY_MIB                    has_frame_slot:true columns:6
        17:35:40.946717 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:53   name:NRUE_MAC_DL_PDU_WITH_DATA       has_frame_slot:true columns:7
        17:35:40.947467 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:54   name:NRUE_MAC_UL_PDU_WITH_DATA       has_frame_slot:true columns:7
        17:35:40.948208 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:55   name:NRUE_MAC_DL_RAR_PDU_WITH_DATA   has_frame_slot:true columns:6
        17:35:40.948912 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:318  name:UE_MASTER_TICK                  has_frame_slot:true columns:5
        17:35:40.949679 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:321  name:UE_PHY_DLSCH_UE_DCI             has_frame_slot:true columns:10
        17:35:40.950397 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:322  name:UE_PHY_DLSCH_UE_ACK             has_frame_slot:true columns:7
        17:35:40.951125 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:323  name:UE_PHY_DLSCH_UE_NACK            has_frame_slot:true columns:7
        17:35:40.951903 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:324  name:UE_PHY_ULSCH_UE_DCI             has_frame_slot:true columns:12
        17:35:40.952604 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:325  name:UE_PHY_ULSCH_UE_ACK             has_frame_slot:true columns:7
        17:35:40.953305 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:326  name:UE_PHY_ULSCH_UE_NACK            has_frame_slot:true columns:7
        17:35:40.954035 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:327  name:UE_PHY_INPUT_SIGNAL             has_frame_slot:true columns:7
        17:35:40.954778 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:328  name:UE_PHY_DL_CHANNEL_ESTIMATE      has_frame_slot:true columns:8
        17:35:40.955533 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:329  name:UE_PHY_DL_CHANNEL_ESTIMATE_FREQ has_frame_slot:true columns:8
        17:35:40.956250 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:330  name:UE_PHY_PDCCH_IQ                 has_frame_slot:false columns:5
        17:35:40.957010 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:331  name:UE_PHY_PDCCH_ENERGY             has_frame_slot:true columns:9
        17:35:40.957781 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:333  name:UE_PHY_PDSCH_ENERGY             has_frame_slot:true columns:9
        17:35:40.958599 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:334  name:UE_PHY_PUSCH_TX_POWER           has_frame_slot:true columns:10
        17:35:40.959364 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:335  name:UE_PHY_PUCCH_TX_POWER           has_frame_slot:true columns:9
        17:35:40.960154 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:336  name:UE_PHY_MEAS                     has_frame_slot:true columns:12
        17:35:40.961126 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:337  name:UE_PHY_UL_PAYLOAD_TX_BITS       has_frame_slot:true columns:30
        17:35:40.962126 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:338  name:UE_PHY_UL_SCRAMBLED_TX_BITS     has_frame_slot:true columns:30
        17:35:40.962455 record_db.cpp:1063 INF[main  ] Tables created, waiting for messages...

        17:36:00.842116 record_db.cpp:1096 INF[main  ]   UE_PHY_UL_SCRAMBLED_TX_BITS     rows:       52  total:        119
        17:36:00.842117 record_db.cpp:1096 INF[main  ]   UE_PHY_UL_PAYLOAD_TX_BITS       rows:       55  total:        119
        17:36:00.842117 record_db.cpp:1096 INF[main  ]   UE_PHY_MEAS                     rows:        5  total:         12
        17:36:00.842117 record_db.cpp:1096 INF[main  ]   UE_PHY_PDSCH_ENERGY             rows:        6  total:         29
        17:36:00.842117 record_db.cpp:1096 INF[main  ]   NRUE_MAC_DL_PDU_WITH_DATA       rows:        6  total:         28
        17:36:00.842117 record_db.cpp:1096 INF[main  ]   NRUE_MAC_UL_PDU_WITH_DATA       rows:       54  total:        118
        17:36:00.842118 record_db.cpp:1096 INF[main  ]   NRUE_PHY_MIB                    rows:      260  total:        495
        17:36:00.842118 record_db.cpp:1100 INF[main  ]
        17:36:05.861012 record_db.cpp:1096 INF[main  ]   UE_PHY_UL_SCRAMBLED_TX_BITS     rows:       55  total:        174
        17:36:05.861013 record_db.cpp:1096 INF[main  ]   UE_PHY_UL_PAYLOAD_TX_BITS       rows:       55  total:        174
        17:36:05.861013 record_db.cpp:1096 INF[main  ]   UE_PHY_MEAS                     rows:        5  total:         17
        17:36:05.861013 record_db.cpp:1096 INF[main  ]   UE_PHY_PDSCH_ENERGY             rows:       12  total:         41
        17:36:05.861013 record_db.cpp:1096 INF[main  ]   NRUE_MAC_DL_PDU_WITH_DATA       rows:       12  total:         40
        17:36:05.861014 record_db.cpp:1096 INF[main  ]   NRUE_MAC_UL_PDU_WITH_DATA       rows:       56  total:        174
        17:36:05.861014 record_db.cpp:1096 INF[main  ]   NRUE_PHY_MIB                    rows:      260  total:        755

This can also be done for the L2 on the gNB side:

        $ docker exec -it oai-gnb-aerial bash -c "record_db -on GNB_MAC_DL_PDU_WITH_DATA"
        turning ON GNB_MAC_DL_PDU_WITH_DATA
        connecting to 127.0.0.1:2021
        16:31:01.742287 record_db.cpp:1000 INF[main  ] on: item: GNB_MAC_DL_PDU_WITH_DATA, on_off_name: GNB_MAC_DL_PDU_WITH_DATA, on_off_action: 1
        16:31:01.742340 record_db.cpp:1011 INF[main  ] No database file provided, using default: T_messages.txt
        16:31:01.751101 record_db.cpp:1020 INF[main  ] Number of events: 801
        16:31:01.752264 record_db.cpp:439 INF[main  ] ClickHouse connection initialized
        16:31:01.752997 record_db.cpp:570 INF[main  ] Initialized buffer for event_id:49   name:GNB_MAC_DL_PDU_WITH_DATA        has_frame_slot:true columns:9
        16:31:01.753065 record_db.cpp:1063 INF[main  ] Tables created, waiting for messages...
        16:31:07.299147 record_db.cpp:1096 INF[main  ]   GNB_MAC_DL_PDU_WITH_DATA        rows:        1  total:          1
        16:31:07.299148 record_db.cpp:1100 INF[main  ]
        16:31:12.299490 record_db.cpp:1096 INF[main  ]   GNB_MAC_DL_PDU_WITH_DATA        rows:      234  total:        235
        16:31:12.299491 record_db.cpp:1100 INF[main  ]
        16:31:17.299594 record_db.cpp:1096 INF[main  ]   GNB_MAC_DL_PDU_WITH_DATA        rows:      260  total:        495
2026-03-06 10:29:34 +01:00
..

OAI Docker/Podman Build and Usage Procedures

Table of Contents

[[TOC]]


1. Build Strategy

For all platforms, the strategy for building docker/podman images is the same:

  • First we create a common shared image ran-base that contains:
    • the latest source files (by using the COPY function)
    • all the means to build an OAI RAN executable
      • all packages, compilers, ...
      • especially UHD is installed
  • Then, from the ran-base shared image, we create a shared image ran-build into which all targets are compiled.
  • Then from the ran-build shared image, we can build target images for:
    • eNB
    • gNB/DU (with UHD)
    • gNB/DU (with AW2S), only on RHEL9
    • lte-UE
    • nr-UE
    • nr-cuup These target images will only contain:
    • the generated executable (for example lte-softmodem)
    • the generated shared libraries (for example liboai_usrpdevif.so)
    • the needed libraries and packages to run these generated binaries
    • Some configuration file templates
    • Some tools (such as ping, ifconfig)
  • From the ran-build-fhi72 image, we can build target image for:
    • gNB/DU (with FHI 7.2)

Note that on every push to develop (i.e., typically after integrating merge requests), we build all images and push them to Docker Hub. To pull them, do

docker pull oaisoftwarealliance/oai-gnb:develop
docker pull oaisoftwarealliance/oai-nr-ue:develop
docker pull oaisoftwarealliance/oai-enb:develop
docker pull oaisoftwarealliance/oai-lte-ue:develop

Have a look at this README to get some information on how to use the images.

2. File organization

Dockerfiles are named with the following naming convention: Dockerfile.${target}.${OS-version}

Targets can be:

  • base for an image named ran-base (shared image)
  • build for an image named ran-build (shared image)
  • build.fhi72 for an image named ran-build-fhi72
  • eNB for an image named oai-enb
  • gNB for an image named oai-gnb
  • nr-cuup for an image named oai-nr-cuup
  • gNB.aw2s for an image named oai-gnb-aw2s
  • gNB.fhi for an image named oai-gnb-fhi72
  • lteUE for an image named oai-lte-ue
  • nrUE for an image named oai-nr-ue

The currently-supported OS are:

  • rhel9 for Red Hat Enterprise Linux and Openshift Universal Base Image
  • ubuntu for Ubuntu 24.04 LTS
  • rocky for Rocky-Linux 9

For more details regarding the build on an Openshift Cluster, see OpenShift README.

3. Building using docker under Ubuntu 22.04

3.1. Pre-requisites

  • git installed
  • docker-ce installed
  • Pulling ubuntu:jammy from DockerHub

The docker files in this directory rely on automatic Docker platform arguments TARGETARCH and TARGETPLATFORM to be defined. This is the case when using BuildKit, which is automatically enabled in newer (v23.0+) docker versions.

If you are running an older version of docker that does not have BuildKit enabled and do not wish to upgrade to a newer docker version, you have two possibilities:

  1. Enable BuildKit when building: DOCKER_BUILDKIT=1 docker build ...
  2. You should be able to define these variables manually.
    • x86: docker build --build-arg TARGETARCH=amd64 --build-arg TARGETPLATFORM=linux/amd64 ...
    • arm: docker build --build-arg TARGETARCH=arm64 --build-arg TARGETPLATFORM=linux/arm64 ...

3.2. Building the shared images

There are two shared images: one that has all dependencies, and a second that compiles all targets (eNB, gNB, [nr]UE).

git clone https://gitlab.eurecom.fr/oai/openairinterface5g.git
cd openairinterface5g
# default branch is develop, to change use git checkout <BRANCH>
docker build --target ran-base --tag ran-base:latest --file docker/Dockerfile.base.ubuntu .
# if you want use USRP, AW2S and RFSimulator radios
docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu .
# if you want to use front-haul 7.2 and RFSimulator radios
docker build --tag ran-build-fhi72:latest --file docker/Dockerfile.build.fhi72.ubuntu .

After building:

docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ran-build           latest              f2633a7f5102        1 minute ago        6.81GB
ran-base            latest              5c9c02a5b4a8        1 minute ago        2.4GB
ran-build-fhi72     latest              5190c06dbb4d        1 minute ago    6.86GB
...

Note that the steps are identical for rocky-linux.

3.2.1. Additional build options

This is only available for the Ubuntu version of Dockerfiles.

You can, for example, create a sanitizer version of the ran-build image.

docker build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.ubuntu --build-arg "BUILD_OPTION=--sanitize" .

Currently the --sanitize option for build_oai enables:

After building:

docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ran-build           latest              f2633a7f5102        1 minute ago        8.78GB
...

Note that the image is much bigger.

You can also use this docker build arguments to pass any available option(s) on the build-oai script.

3.3. Building any target image

For example, the eNB:

docker build --target oai-enb --tag oai-enb:latest --file docker/Dockerfile.eNB.ubuntu .

To build gNB/DU with 7.2 fronthaul support:

docker build --target oai-gnb-fhi72 --tag oai-gnb-fhi72:latest --file docker/Dockerfile.gNB.fhi72.ubuntu  .

After a while:

docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
oai-enb             latest              25ddbd8b7187        1 minute ago        516MB
ran-build           latest              f2633a7f5102        1 hour ago          6.81GB
ran-base            latest              5c9c02a5b4a8        1 hour ago          2.4GB

Do not forget to remove the temporary image:

docker image prune --force

Note that the steps are identical for rocky-linux.

If you have used the sanitizer option, then you should also pass it when building the target image:

docker build --target oai-gnb --tag oai-gnb:latest --file docker/Dockerfile.gNB.ubuntu --build-arg "BUILD_OPTION=--sanitize" .

Normally the target image will be around 200 Mbytes bigger.

4. Building using podman under Red Hat Entreprise Linux 9.X

Analogous to the above steps:

podman build --target ran-base --tag ran-base:latest --file docker/Dockerfile.base.rhel9 .
# if you want use USRP, AW2S and RFSimulator radios
podman build --target ran-build --tag ran-build:latest --file docker/Dockerfile.build.rhel9 .
# if you want to use front-haul 7.2 and RFSimulator radios
podman build --tag ran-build-fhi72:latest --file docker/Dockerfile.build.fhi72.rhel9 .

4.1 Building target images

For example, the eNB:

podman build --target oai-enb --tag oai-gnb:latest --file docker/Dockerfile.eNB.rhel9 .

To build gNB/DU with 7.2 fronthaul support:

podman build --target oai-gnb-fhi72 --tag oai-gnb-fhi72:latest --file docker/Dockerfile.gNB.fhi72.rhel9  .

5. Running modems using docker under Ubuntu

The easiest is to run them from a docker-compose file, which is used by the CI to test OAI. Some folders under ci-scripts/yaml_files have a README that you can follow. For 5G, the easiest is to start with the RFsimulator, as described in this README (you would of course use your own images instead of downloading them from Docker hub).

For an example using a B210, please refer to this docker-compose file.

It is also possible to mount your own configuration file. The following docker-compose file can be used to start a gNB using a B210 and your own config, located at /tmp/gnb.conf:

services:
    gnb_mono_tdd:
        image: oai-gnb:latest
        container_name: sa-b200-gnb
        cap_drop:
            - ALL
        cap_add:
            - SYS_NICE
            - IPC_LOCK
        ulimits:
          core: -1 # for core dumps
        environment:
            USE_B2XX: 'yes'
            USE_ADDITIONAL_OPTIONS: --RUs.[0].sdr_addrs serial=30C51D4 --telnetsrv --telnetsrv.shrmod ci --continuous-tx --log_config.global_log_options level,nocolor,time,line_num,function
        devices:
            - /dev/bus/usb/:/dev/bus/usb/
        volumes:
            - ../../conf_files/gnb.sa.band78.51prb.usrpb200.conf:/opt/oai-gnb/etc/gnb.conf
        # for performance reasons, we use host mode: in bridge mode, we have
        # unacceptable DL TCP performance. However, the whole point of
        # containerization is to not be in host mode, so update this to macvlan
        # later.
        network_mode: "host"
        #entrypoint: /bin/bash -c "sleep infinity"
        healthcheck:
            # pgrep does NOT work
            test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem"
            interval: 10s
            timeout: 5s
            retries: 5

You should also change the image to the right image name and tag of the gNB you are using. Start like this:

docker-compose up    # gNB in foreground
docker-compose up -d # gNB in background

Stop it like this (in both cases):

docker-compose down