3.6. Bundle packaged integrations#

This section describes how to bundle various plugins to packaged integrations in a container image so that Nubus for Kubernetes can load them.

This section assumes you have knowledge about how to build container images. Describing the single build steps, and how to publish a container image to a registry is beyond the scope of this document.

Nubus for Kubernetes uses container images to load packaged integrations. The purpose of this container image is that the Kubernetes cluster starts the container image and runs the entry point script or binary as loader. The loader’s only purpose is to copy your packaged integration files to defined target locations in appropriate Kubernetes pods depending on the plugin type.

To bundle any packaged integration documented in Packaged integrations, use the steps in the following sections:

  1. Packaged integration structure

  2. Create Dockerfile

  3. Packaged integration loader

  4. Add plugins

3.6.1. Packaged integration structure#

To start with a packaged integration, you need to create the file structure.

  1. Create an empty directory, for example packaged-integration-project.

  2. Create the subdirectory docker/. The directory contains the files of your packaged integration, the script, and the Dockerfile.

  3. Create the subdirectory plugins for the actual plugins of your packaged integration, for example packaged-integration-project/plugins.

  4. Create the empty Dockerfile. For the content, see Create Dockerfile.

  5. Create the empty loader.sh file. For the content, see Packaged integration loader.

Your directory structure then looks similar to the directory structure in Listing 3.8.

Listing 3.8 Directory structure for Nubus packaged integrations#
packaged-integration-project/
├── docker
│   ├── Dockerfile
│   └── loader.sh
└── plugins
    ├── ldap-acls
    ├── ldap-schema
    ├── udm-handlers
    ├── udm-hooks.d
    ├── udm-modules
    ├── udm-syntax.d
    ├── umc-icons
    └── umc-modules

3.6.2. Create Dockerfile#

Create your Dockerfile. You can use any container image as base image. It must be able to run your loader. Keep the image as slim as possible, because it reduces download and container startup time. See the example in Listing 3.9.

Listing 3.9 Example for Dockerfile#
# SPDX-License-Identifier: AGPL-3.0-only
# SPDX-FileCopyrightText: 2024 - 2025 Univention GmbH

ARG BASE_IMAGE_TAG=3.20
ARG BASE_IMAGE=docker.io/alpine
FROM ${BASE_IMAGE}:${BASE_IMAGE_TAG}

# Create system group and system user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

WORKDIR /

# Copy plugins of the packaged integration to the Docker image
COPY plugins /plugins
# Copy the plugin loader to the Docker image
COPY docker/loader.sh /bin/loader

CMD ["/bin/loader"]

See also

Writing a Dockerfile | Docker Docs

for getting started with writing a Dockerfile for container images.

3.6.3. Packaged integration loader#

The packaged integration loader is a script or a binary that runs after the container has started. The loader copies the plugin files of the packaged integration to the /target/ directory, a predefined directory that Nubus for Kubernetes recognizes automatically. Nubus then copies the plugins to the respective Kubernetes pods depending on the plugin type.

You find examples in Listing 3.10 and loader in the openDesk Nubus Customization.

Listing 3.10 Example for loader script#
#!/bin/sh
# SPDX-License-Identifier: AGPL-3.0-only
# SPDX-FileCopyrightText: 2024 - 2025 Univention GmbH

set -eu

echo "Copying the Nubus plugins into the /target volume"
for source in /plugins/*; do
  plugin_type=$(basename "${source}")
  target="/target/${plugin_type}"
  if [ -d "${target}" ]; then
    echo "COPY - Plugin type ${plugin_type} in /target, copying files."
    cp -av "${source}" /target
  else
    echo "SKIP - Plugin type ${plugin_type} not in /target, skipping."
  fi
done

3.6.4. Add plugins#

Copy your plugin to the directory matching its type. The values for PLUGIN_TYPE and PLUGIN_FILE come from the respective plugin type sections, see Plugin types.

$ export PACKAGED_INTEGRATION_PROJECT="ABSOLUTE_PATH_TO_YOUR_PACKAGED_INTEGRATION_PROJECT"

$ cp "$PLUGIN_FILE" "$PACKAGED_INTEGRATION_PROJECT"/plugins/"$PLUGIN_TYPE"/

3.6.5. Build and publish#

With the directory and file structure, the Dockerfile, the loader, and the plugins, you have everything in place and are ready to build the container image. Follow the Docker documentation for building the container image.

Example
$ export REGISTRY_HOST="FQDN and optional port of your container registry"
$ export IMAGE_PATH="PATH to the image on the registry without trailing slash /"
$ export IMAGE_NAME="Your name for the image"
$ export IMAGE_TAG="Your version tag or latest"

$ cd "$PACKAGED_INTEGRATION_PROJECT"
$ docker build -t "$IMAGE_NAME" -f docker/Dockerfile .

# The build process takes some time.

$ docker image tag "$IMAGE_NAME" "$REGISTRY_HOST"/"$IMAGE_PATH"/"$IMAGE_NAME":"$IMAGE_TAG"
$ docker image push "$REGISTRY_HOST"/"$IMAGE_PATH"/"$IMAGE_NAME":"$IMAGE_TAG"

See also

Build, tag, and publish an image | Docker Docs

for getting starting with building and tagging a container image.