Running Service in Docker
Using the pre-built Service image
Note
Pre-built images are currently available for Cisco internal users only. We hope to be able to provide Docker images externally for download at some point in the future.
Pre-built RADKit Service Docker images for Linux x86_64
and aarch64
can be found in this
repository, with the latest
tag pointing to the latest stable external release. You need to be connected to the Cisco network in
order to access the repository and pull images.
Warning
If you use these pre-built images, remember to replace radkit-service:latest
with
containers.cisco.com/radkit/radkit-service:latest
in the docker run
commands in the
following sections.
Building your own Service image
Extracting the wheels
The sample Dockerfile
below assumes that the RADKit wheels for the target platform have been
extracted from the .tgz
files found in the downloads area into a directory called wheels/
relative to the current directory; for instance (Python 3.11, x86_64
, GNU libc):
$ mkdir -p wheels/
$ tar zxvf cisco_radkit_1.6.0_pip_linux.tgz -C wheels/ '*cp311-none-manylinux1_x86_64*'
x cisco_radkit_service-1.6.0-cp311-none-manylinux1_x86_64.whl
x cisco_radkit_genie-1.6.0-cp311-none-manylinux1_x86_64.whl
x cisco_radkit_common-1.6.0-cp311-none-manylinux1_x86_64.whl
x cisco_radkit_client-1.6.0-cp311-none-manylinux1_x86_64.whl
$ rm -f wheels/cisco_radkit_{client,genie}
Make sure to only include the wheels you need, in order to save space in the final image.
Only cisco_radkit_service
and cisco_radkit_common
are required for RADKit Service.
Dockerfile
Here is a sample Dockerfile
that can be used to build a RADKit Service container image.
This example is based on the official Python image
from Docker. It relies on a startup script, start.sh
, that is shown below.
ARG PYTHON_VERSION=3.11
FROM docker.io/python:${PYTHON_VERSION}-slim
WORKDIR /
ENV RADKIT_DIRECTORY="/radkit"
COPY wheels/ wheels/
COPY start.sh start.sh
RUN apt update && apt upgrade -y && python3 -m pip install -U pip
RUN python3 -m pip install -f wheels/ cisco_radkit_service
RUN chmod +x start.sh
RUN mkdir ${RADKIT_DIRECTORY}
VOLUME ${RADKIT_DIRECTORY}
EXPOSE 8081
# This must be ENTRYPOINT, not CMD, so that there is proper signal handling. Also,
# ENTRYPOINT must be written in the "exec form" (JSON array), not the shell form.
ENTRYPOINT [ "/start.sh" ]
Note
On some platforms such as aarch64
, some dependencies may have to be built from source. If
that is the case for your target platform, use the following RUN
command for
pip install ... cisco_radkit_service
instead of the one shown in the example above:
RUN apt install gcc -y \
&& python3 -m pip install -f wheels/ cisco_radkit_service \
&& apt remove gcc -y \
&& apt autoremove -y \
&& apt clean \
&& rm -rf /var/lib/apt/lists/*
Startup script
The start.sh
script should be copied verbatim from this document:
#!/bin/bash
ARGS=""
RUN_ARGS=""
[ "${RADKIT_SERVICE_CLI_DEBUG}" == 1 ] && ARGS="${ARGS} --debug"
[ "${RADKIT_SERVICE_CLI_TRACE}" == 1 ] && ARGS="${ARGS} --trace"
[ "${RADKIT_SERVICE_CLI_TRACEBACKS}" == 1 ] && ARGS="${ARGS} --tracebacks"
[ -n "${RADKIT_SERVICE_CLI_DOMAIN}" ] && ARGS="${ARGS} --domain ${RADKIT_SERVICE_CLI_DOMAIN}"
[ -n "${RADKIT_SERVICE_CLI_SETTINGS_FILE}" ] && ARGS="${ARGS} --settings-file ${RADKIT_SERVICE_CLI_SETTINGS_FILE}"
[ "${RADKIT_SERVICE_CLI_NO_HEADLESS}" != 1 ] && RUN_ARGS="${RUN_ARGS} --headless"
[ "${RADKIT_SERVICE_CLI_RUN_FORCE}" == 1 ] && RUN_ARGS="${RUN_ARGS} --force"
exec radkit-service ${ARGS} run ${RUN_ARGS}
Build the image
To build the image:
$ docker build . -t radkit-service:latest
Things to know
Ports and volumes
When running in a container, the Service will listen on port 8081 internally and store all its
data under /radkit
. These can be remapped to a specific port and directory on the host machine
as needed, using Docker’s -p
/ ports
and -v
/ volumes
parameters.
Warning
Make sure to mount RADKit’s data directory outside of your container, otherwise all data including certificates, database, logs … will be lost when the container is removed.
Bootstrapping
The Service container must first be bootstrapped, which requires the creation of a superadmin
user, before it can be enrolled and have devices added to its database. Below are the most common
ways to bootstrap and run the Service; if none of these work for your specific use case, please
reach out to the RADKit development team.
Running behind a proxy
If you are running this container behind a proxy, you may have to pass additional
environment variables to docker run
using the -e
option (see Proxy settings),
for instance:
-e RADKIT_CLOUD_CLIENT_PROXY_URL=http://proxy.esl.cisco.com:80/
IPv6 support
Docker containers do not have IPv6 enabled by default. To configure an IPv6 network for your RADKit Service container, please refer to this article.
Docker run
interactive
The first option to bootstrap and run RADKit Service in a container involves entering the
superadmin
password interactively at startup. First run the radkit-service bootstrap
command
in an interactive container (make sure to replace /tmp/radkit
with your own local RADKit Service
data directory):
$ docker run --rm -it --entrypoint radkit-service -v /tmp/radkit:/radkit \
radkit-service:latest bootstrap
19:48:35.290Z INFO | internal | RADKit Service [version='1.6.4']
Set up the superadmin user. You'll be asked to provide a superadmin password.
Keep this password securely stored, as it will be impossible to recover it!
Superadmin password (for new setup): *********
Confirm: *********
19:48:41.582Z INFO | internal | Creating new database file. [path=PosixPath('/radkit/service/service-db.json.encrypted')]
...
19:48:41.664Z INFO | internal | Creating administrator [admin_name='superadmin']
19:48:41.673Z INFO | internal | Database closed. [path=PosixPath('/radkit/service/service-db.json.encrypted')]
Bootstrapping is complete. The next step is to enroll with the RADKit Certificate Authority.
You can now start the Service with 'radkit-service run' and log on to the WebUI as 'superadmin'.
Alternatively, you can enroll through the CLI (see documentation for details).
Once this is done, you can run the container normally (it starts radkit-service run
by default)
and enter the password interactively on startup:
$ docker run --rm -it -p 8081:8081 -e RADKIT_SERVICE_CLI_NO_HEADLESS=1 \
-v /tmp/radkit:/radkit radkit-service:latest
19:50:35.030Z INFO | internal | RADKit Service [version='1.6.4']
...
Superadmin password: ********* [correct]
19:50:38.067Z INFO | internal | Opening database. [path=PosixPath('/radkit/service/service-db.json.encrypted')]
...
19:50:38.552Z INFO | internal | Running on https://0.0.0.0:8081 (CTRL + C to quit)
Note the addition of -p 8081:8081
to allow access to the container’s WebUI and API from the
host, as well as -e RADKIT_SERVICE_CLI_NO_HEADLESS=1
to allow for interactive password input.
Docker run
non-interactive
If entering the superadmin
password interactively is not an option, you can store it in
an environment variable as described in Storing the superadmin password (note that this is not
recommended; only do it if you understand the risks !)
In this case, as the password is readily available, the Service will automatically bootstrap itself and start up.
First store the password in an environment variable, for example (on Linux or macOS):
# !! Please do NOT copy-paste the 'MyPassW0rd!' example in your actual setup !!
% export RADKIT_SERVICE_SUPERADMIN_PASSWORD_BASE64=$( echo -n 'MyPassW0rd!' | base64 )
Then run the container:
without
-it
(non-interactive);with
-p 8081:8081
(to allow access to the container’s WebUI from the host);with
-e RADKIT_SERVICE_SUPERADMIN_PASSWORD_BASE64
(to publish the value of the environment variable into the container);making sure to replace
/tmp/radkit
with your own local RADKit Service data directory.
% docker run --rm -p 8081:8081 -e RADKIT_SERVICE_SUPERADMIN_PASSWORD_BASE64 \
-v /tmp/radkit:/radkit radkit-service:latest
20:00:27.399Z INFO | internal | RADKit Service [version='1.6.4']
...
20:00:27.419Z WARNI | internal | Loading superadmin password from environment ($RADKIT_SERVICE_SUPERADMIN_PASSWORD_BASE64)
20:00:29.155Z INFO | internal | Creating new database file. [path=PosixPath('/radkit/service/service-db.json.encrypted')]
...
20:00:29.772Z INFO | internal | Running on https://0.0.0.0:8081 (CTRL + C to quit)
Note
The interactive and non-interactive methods described in this and the previous section
can be combined, i.e. you can do an interactive bootstrap and then pass the superadmin
password non-interactively, or do a non-interactive bootstrap then suppress the
environment variable in later runs and provide the password interactively. You can
also switch between the interactive and non-interactive way of running the Service as
you see fit.
Docker Compose
To use Docker Compose to manage the Service, copy-paste the following YAML content into your
docker-compose.yml
:
services:
radkit-service:
container_name: radkit-service
image: containers.cisco.com/radkit/radkit-service:latest
environment:
# Set variables here, or pass them with '-e', or don't pass them at all
# Make sure you do NOT enclose the value in double quotes !
- RADKIT_SERVICE_SUPERADMIN_PASSWORD_BASE64=...
- RADKIT_CLOUD_CLIENT_PROXY_URL=...
ports:
# Set the host RADKit port here (syntax: "<host-port>:8081")
- "8081:8081"
volumes:
# Set the host RADKit directory here, or pass RADKIT_DIRECTORY when calling Compose
- "${RADKIT_DIRECTORY}:/radkit"
# To get help on available CLI options, please use:
# docker compose run radkit-service bash -c "radkit-service --help"
# docker compose run radkit-service bash -c "radkit-service run --help"
command: radkit-service run --headless
In this file, you can specify static parameters such as:
proxy settings (see Proxy settings);
which local HTTPS port and directory to use;
the
superadmin
password (see Storing the superadmin password).
See the previous sections about docker run
for an explanation of the different parameters.
Warning
Starting with RADKit 1.4, the --no-cli-app
CLI argument to radkit-service run
has been
deprecated in favor of --headless
with better support for headless mode. Please make sure
you update your Compose file, as --no-cli-app
will be removed in a future release.
Once the docker-compose.yml
file is created and tuned according to your needs, start the
container with docker compose up
. The instructions for interactive and non-interactive
bootstrap from the previous sections still apply; the difference is only in the way you
run the container.
docker compose up
[+] Running 2/2
⠿ Network docker_default Created 0.0s
⠿ Container radkit-service Created 0.0s
Attaching to radkit-service
radkit-service | 20:21:18.610Z INFO | internal | RADKit Service [version='1.6.4']
...
radkit-service | 20:21:18.635Z WARNI | internal | Loading superadmin password from environment ($RADKIT_SERVICE_SUPERADMIN_PASSWORD_BASE64)
...
radkit-service | 20:21:19.134Z INFO | internal | Running on https://0.0.0.0:8081 (CTRL + C to quit)
Passing CLI arguments through the environment
In very specific scenarios (such as CML integration) it may not be possible to provide
any CLI arguments to the RADKit Service entry point when starting it. In such cases it is
still possible to force a few select CLI options by way of an environment variable, thanks
to the start.sh
script:
RADKIT_SERVICE_CLI_DEBUG=1
for--debug
RADKIT_SERVICE_CLI_TRACE=1
for--trace
RADKIT_SERVICE_CLI_TRACEBACKS=1
for--tracebacks
RADKIT_SERVICE_CLI_DOMAIN=...
for--domain ...
RADKIT_SERVICE_CLI_SETTINGS_FILE=...
for--settings-file ...
RADKIT_SERVICE_CLI_NO_HEADLESS=1
to turn offrun --headless
RADKIT_SERVICE_CLI_RUN_FORCE=1
forrun --force
(added in RADKit 1.6.0)