Skip to content

Packaging

xApps ship as Docker images built FROM the SDK base image. This page covers the in-tree layout and build_docker.sh, which is how the reference xApps in xapps/ are built.

For your own project, the CLI does this

A project generated by airpuls-sdk xapp new has its own Dockerfile and launcher; airpuls-sdk xapp package builds the image and xapp deploy publishes it and uploads the deployment entry. You only need this page's build_docker.sh flow when working inside an airpuls-ric checkout.

The SDK base image

airpuls-xapp-sdk is the foundation every xApp image builds on. It ships:

  • libairpuls_common.a, every libe2sm_<sm>.a, and libric_client.a at /opt/airpuls/lib/
  • the public headers at /opt/airpuls/include/
  • the Python binding, preinstalled

It is published on Docker Hub for linux/amd64 and linux/arm64, and its Hub name is the canonical reference everything uses:

docker pull airpuls/airpuls-xapp-sdk:latest

Three tags are available. X.Y.Z is immutable and never repointed; X.Y follows the newest patch of that series; latest follows the newest release.

Projects generated by airpuls-sdk xapp new build FROM airpuls/airpuls-xapp-sdk:latest; xapp new --base-tag X.Y pins a project to a series (and --base-tag X.Y.Z to a byte-identical base) — the pin lives in the Dockerfile's FROM line, which is the single source of truth for the base reference. The pull alone is enough: airpuls-sdk xapp package and airpuls-sdk xapp deploy check exactly the reference the project's FROM names, and airpuls-sdk doctor reports that same reference. With the image absent, xapp package and xapp deploy offer to run the pull on a terminal; declining prints the pull command.

From an airpuls-ric checkout you can build it instead — the build also tags the canonical airpuls/airpuls-xapp-sdk:latest name, so the CLI sees a checkout build too, and produces the companion airpuls-xapp-sdk-builder:latest:

./build_docker.sh base

The builder image compiles Go and C xApps against the pre-built archives inside the container, so no host pre-build is needed. It is not published on Docker Hub — the public base image covers Python xApps, while Go and C xApps are built from a checkout.

Directory layout

Each xApp folder is language-partitioned, with one shared xapp.yml at the root (every language reads it through the C SDK's config loader):

xapps/<name>/
    xapp.yml            # runtime config, shared by all languages
    README.md           # language-agnostic overview
    python/             # main.py + Dockerfile
    go/                 # main.go + go.mod + Makefile + Dockerfile
    c/                  # main.c + CMakeLists.txt + Dockerfile

The Docker build context is the xApp root so xapp.yml is reachable from every language's Dockerfile.

Dockerfiles

# xapps/my-xapp/python/Dockerfile
FROM airpuls/airpuls-xapp-sdk:latest
COPY python/main.py python/my_module.py /opt/airpuls/xapps/my-xapp/
COPY xapp.yml /etc/airpuls/xapp.yml
WORKDIR /opt/airpuls/xapps/my-xapp
ENTRYPOINT ["python3", "main.py"]
# xapps/my-xapp/go/Dockerfile — Go xApps build inside the builder image
FROM airpuls/airpuls-xapp-sdk:latest
COPY go/my-xapp /usr/local/bin/my-xapp
COPY xapp.yml /etc/airpuls/xapp.yml
ENTRYPOINT ["/usr/local/bin/my-xapp"]

build_docker.sh compiles the Go binary inside airpuls-xapp-sdk-builder before this stage copies it in.

# xapps/my-xapp/c/Dockerfile — the builder stage compiles one .c file
# against the SDK's pre-built static archives, then the binary is
# copied into the lean runtime image.
FROM airpuls/airpuls-xapp-sdk:latest
COPY c/my-xapp /usr/local/bin/my-xapp
COPY xapp.yml /etc/airpuls/xapp.yml
ENTRYPOINT ["/usr/local/bin/my-xapp"]

Building and running

# Build all languages of an xApp:
./build_docker.sh my-xapp

# Build one language:
./build_docker.sh my-xapp:go
./build_docker.sh my-xapp:python
./build_docker.sh my-xapp:c

Images are tagged <name>-<lang>:latest. Run with the config mounted or baked in:

docker run --rm --network=host \
  -v $(pwd)/xapp.yml:/etc/airpuls/xapp.yml \
  my-xapp-python:latest -c /etc/airpuls/xapp.yml

docker run --rm --network=host my-xapp-go:latest    -c /etc/airpuls/xapp.yml
docker run --rm --network=host my-xapp-c:latest     -c /etc/airpuls/xapp.yml

One shared config, three images

Because xapp.yml lives at the xApp root and every language reads it through the same loader, the Python, Go, and C images of an xApp are interchangeable at the config level — the same xapp.yml drives all three. kpm-monitor ships all three flavours and uses the C variant as the binding-overhead baseline.