Running Universal Agents in Docker Containers
In this article we examine a sample dockerfile, entrypoint script, and the docker build and run commands needed to implement and use the image.
Stonebranch enjoys a full integration with Docker, meaning that Stonebranch and Docker products and solutions work seamlessly together. Below is an example use case for running the Stonebranch Universal Agent within a Docker container.
To operate successfully within a Docker container, there are several considerations to bear in mind when designing and implementing a Universal Agent Docker image. In this article, we examine a sample dockerfile, entrypoint script, and the docker build and run commands needed to implement and use the image.
Example Dockerfile and Entrypoint Script
Here is our example dockerfile:
#
# Dockerfile to build Universal Agent images
# - UA will run in console mode with any user
#
# Set the base image to redhat
FROM registry.access.redhat.com/ubi8/ubi
#
MAINTAINER "Colin Cocksedge "
#
# Install ua
ARG ua_version
ADD /install-files/sb-${ua_version}-linux-2.6-x86_64.tar.Z /tmp
RUN zcat /tmp/sb-${ua_version}-linux-2.6-x86_64.tar.Z | tar xvf - && \
sed -ri 's/\$UNV_DIR\/ubroker\/ubrokerd restart.*/
# Do Not Start Ubroker During Install/g'
./unvinst && \
./unvinst --network_provider oms --oms_servers 7878@localhost --opscli yes
--python yes --oms_port 7878 && \
rm unvinst *.rpm *.tar upimerge.sh upimerge.log usrmode.inc
/tmp/sb-${ua_version}-linux-2.6-x86_64.tar.Z
EXPOSE 7887 7878
#
# Set Permissions for Arbitrary ID Support
RUN sed -ri 's/security.*/security NONE/g' /etc/universal/uags.conf && \
sed -ri 's/security.*/security NONE/g' /etc/universal/udms.conf && \
sed -ri 's/security.*/security NONE/g' /etc/universal/ucmds.conf && \
sed -ri 's/security.*/security NONE/g' /etc/universal/uctls.conf && \
sed -ri 's/security.*/security NONE/g' /etc/universal/uems.conf && \
chgrp -R 0 /etc/universal && \
chmod -R g=u /etc/universal && \
chgrp -R 0 /opt/universal && \
chmod -R g=u /opt/universal && \
chgrp -R 0 /var/opt/universal && \
chmod -R g=u /var/opt/universal && \
chmod g=u /etc/passwd
#
# Add entrypoint script and because it's from Windows remove CRLF
COPY ./ua_entrypoint /
#
# Set Default userid
USER 10010
#
# Entry Point
ENTRYPOINT [ "./ua_entrypoint" ]
Let’s break this down:
FROM registry.access.redhat.com/ubi8/ubi
Set the base image. In this example we are using a RedHat linux image, but you can choose a different base image based upon you own preferences.
ARG ua_version
Accept a build argument to specify the Universal Agent version to be installed within the Docker image. Add the Universal Agent installation file to the Docker image.
Add the Universal Agent installation file to the Docker image.
ADD /install-files/sb-${ua_version}-linux-2.6-x86_64.tar.Z /tmp
RUN zcat /tmp/sb-${ua_version}-linux-2.6-x86_64.tar.Z | tar xvf - && \
sed -ri 's/\$UNV_DIR\/ubroker\/ubrokerd restart.*/
# Do Not Start Ubroker During Install/g' ./unvinst
&& \
./unvinst --network_provider oms --oms_servers 7878@localhost
--opscli yes --python yes --oms_port
7878 && \
rm unvinst *.rpm *.tar upimerge.sh upimerge.log usrmode.inc /tmp/sb-${ua_version}
-linux-2.6-
x86_64.tar.Z
The following runs several commands concatenated together, this is because each invocation of the RUN command adds a layer to the image, this method helps to minimize the image size.
RUN zcat /tmp/sb-${ua_version}-linux-2.6-x86_64.tar.Z | tar xvf - && \ sed -ri 's/\$UNV_DIR\/ubroker\/ubrokerd restart.*/ # Do Not Start Ubroker During Install/g' ./unvinst && \ ./unvinst --network_provider oms --oms_servers 7878@localhost --opscli yes --python yes --oms_port 7878 && \ rm unvinst *.rpm *.tar upimerge.sh upimerge.log usrmode.inc /tmp/sb-${ua_version}-linux-2.6- x86_64.tar.Z
- The zcat command extracts the Universal Agent installation package.
- The sed command updates the unvinst script to prevent the ubroker from being started during the install.
- Run the Universal Agent Install script. You should review which options suit your needs.
- Remove the temporary installation files.
EXPOSE 7887 7878
Expose the Universal Agent ports. This is mostly documentational as depending on your requirements as the container ports would typically be mapped to the host system via the --publish option of the docker run command.
In some container orchestration environments (e.g. OpenShift) the Docker container's runtime User ID will be set to an arbitrary value by the environment. In order to support running the Universal Agent as any user the following commands are required.
- Set the security option for the ubroker components to none. This means that these components will inherit the ubroker user to execute workload, i.e. no identity switching will be performed.
- Set the group ownership of the installation files to gid 0 and set the group permissions for the installation files to match the user permissions. Arbitrary users assigned at container run time will belong to gid 0. This allows any user to start the Universal Broker.
RUN sed -ri 's/security.*/security NONE/g' /etc/universal/uags.conf && \ sed -ri 's/security.*/security NONE/g' /etc/universal/udms.conf && \ sed -ri 's/security.*/security NONE/g' /etc/universal/ucmds.conf && \ sed -ri 's/security.*/security NONE/g' /etc/universal/uctls.conf && \ sed -ri 's/security.*/security NONE/g' /etc/universal/uems.conf && \ chgrp -R 0 /etc/universal && \ chmod -R g=u /etc/universal && \ chgrp -R 0 /opt/universal && \ chmod -R g=u /opt/universal && \ chgrp -R 0 /var/opt/universal && \ chmod -R g=u /var/opt/universal && \ chmod g=u /etc/passwd
Set the default user for containers run from this image. In the event that a user is not assigned or specified via the docker run command, this prevents the container from running as uid 0.
USER 10010
When the container is run an entrypoint script is provided to override the Universal Agent configuration, start the Universal Agent, and ensure it terminates cleanly when the container is stopped.
- Add the entrypoint script to the container.
- Define the entrypoint
“ COPY ./ua_entrypoint / ENTRYPOINT [ "./ua_entrypoint" ]
Here is our example entrypoint script:
#!/bin/bash
# Handle Docker Stop and Terminate Ubroker Cleanly
shutdown() {
kill -TERM "$ubroker"
wait "$ubroker"
exit 0
}
# Recognize Terminaton
trap 'shutdown' SIGINT SIGTERM
# Support Arbitrary User IDs
if ! whoami &> /dev/null; then
if [ -w /etc/passwd ]; then
echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default}
user:${HOME}:/sbin/nologin" >> /etc/passwd
fi
fi
# Set netname
if [ ! -z "$UAG_NETNAME" ]; then
sed -ri "s/^netname.*/netname $UAG_NETNAME/g" /etc/universal/uags.conf
else
sed -ri "s/^netname.*/netname $HOSTNAME/g" /etc/universal/uags.conf
fi
# Set oms_servers
if [ ! -z "$UAG_OMS_SERVERS" ]; then
sed -ri "s/^oms_servers.*/oms_servers $UAG_OMS_SERVERS/g"
/etc/universal/uags.conf
fi
# Set Agent Clusters
if [ ! -z "$UAG_AGENT_CLUSTERS" ]; then
sed -ri "s/^agent_clusters.*/agent_clusters
\"$UAG_OMS_SERVERS\"/g" /etc/universal/uags.conf
fi
# Set enable_ssl
if [ ! -z "$UAG_ENABLE_SSL" ]; then
grep -q '^enable_ssl' /etc/universal/uags.conf && sed
-i 's/^enable_ssl.*/enable_ssl yes/' /etc/universal/uags.conf
|| echo 'enable_ssl yes' >> /etc/universal/uags.conf
fi
# Run OMS Server
if [ ! -z "$OMS_AUTOSTART" ]; then
sed -ri "s/^auto_start.*/auto_start yes/g" /etc/universal/comp/oms
sed -ri "s/^restart.*/restart yes/g" /etc/universal/comp/oms
fi
# Start the Agent
/opt/universal/ubroker/bin/ubroker &
ubroker=$!
wait "$ubroker"
Again, let’s break this down: The docker stop command attempts to stop a running container first by sending a SIGTERM signal to the root process (PID 1) in the container. If the process hasn't exited within the timeout period a SIGKILL signal will be sent. The following code implements a function to forward the sigterm to the ubroker process to ensure it is terminated cleanly.
# Handle Docker Stop and Terminate Ubroker Cleanly shutdown() { kill -TERM "$ubroker" wait "$ubroker" exit 0 } # Recognize Terminaton trap 'shutdown' SIGINT SIGTERM
During startup the Universal Broker performs a check to confirm that the userid starting the ubroker daemon exists in the /etc/passwd. In order to allow the ubroker to run with an arbitrary user id we need to dynamically add the user id to the /etc/passwd file.
# Support Arbitrary User IDs if ! whoami &> /dev/null; then if ! whoami &> /dev/null; then if [ -w /etc/passwd ]; then echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:${HOME}:/sbin/nologin" >> /etc/passwd fi fi
Configuration overrides to the container will be specified using environment variables specified via the docker run command. Alternatively, you can mount a preconfigured configuration from the docker hosts file system via the docker run --env option.
# Set netname if [ ! -z "$UAG_NETNAME" ]; then sed -ri "s/^netname.*/netname $UAG_NETNAME/g" /etc/universal/uags.conf else sed -ri "s/^netname.*/netname $HOSTNAME/g" /etc/universal/uags.conf fi # Set oms_servers if [ ! -z "$UAG_OMS_SERVERS" ]; then sed -ri "s/^oms_servers.*/oms_servers $UAG_OMS_SERVERS/g" /etc/universal/uags.conf fi # Set Agent Clusters if [ ! -z "$UAG_AGENT_CLUSTERS" ]; then sed -ri "s/^agent_clusters.*/agent_clusters \"$UAG_OMS_SERVERS\"/g" /etc/universal/uags.conf fi # Set enable_ssl if [ ! -z "$UAG_ENABLE_SSL" ]; then grep -q '^enable_ssl' /etc/universal/uags.conf && sed -i 's/^enable_ssl.*/enable_ssl yes/' /etc/universal/uags.conf || echo 'enable_ssl yes' >> /etc/universal/uags.conf fi # Run OMS Server if [ ! -z "$OMS_AUTOSTART" ]; then sed -ri "s/^auto_start.*/auto_start yes/g" /etc/universal/comp/oms sed -ri "s/^restart.*/restart yes/g" /etc/universal/comp/oms
In order to avoid writing log files and to make the logs (unv and uag) accessible to docker you should run the ubroker in console mode.
# Start the Agent /opt/universal/ubroker/bin/ubroker & ubroker=$! wait "$ubroker"
Building the Image
The following command can be used to build and tag the Universal Agent docker image. This command expects the example dockerfile and ua_entrypoint script to be in the current directory (notice the that the “.” at the end of the command denotes the build context as the current directory), it also expects the Universal Agent installation package to be in the “install-files” subdirectory. Replace the “v.r.m.m” with the Universal Agent version being used for the image.
docker build -t ua-redhat:v.r.m.m --build-arg ua_version=v.r.m.m .
Running the Image
Docker Environment Variables
When you create a Universal Agent container, you can configure the Universal Agent by specifying the following environment variables:
Environment Variable | Description | Example |
UAG_NETNAME | Set the Agent ID to be used when the Universal Agent registers/connects to a Universal Controller Instance. Default=OPSAUTOCONF | UAG_NETNAME=UADKR001 |
UAG_OMS_SERVERS | Specifies one or more OMS server addresses. Default=7878@localhost | UAG_OMS_SERVERS=7878@omsserver1,7878@omsserver2 |
UAG_AGENT_CLUSTERS | The list of Universal Controller Agent Clusters to join automatically. Default='Opswise Default Linux/Unix Cluster, Opswise - Default Windows Cluster' | UAG_AGENT_CLUSTER='Agent Cluster 1,Agent Cluster 2' |
UAG_ENABLE_SSL | Specifies whether the SSL protocol is used for network communication between UAG and OMS. Default = no | UAG_ENABLE_SSL=yes |
OMS_AUTOSTART | Specifies whether the Universal Broker starts an OMS server. Default = no | OMS_AUTOSTART=yes |
Docker Container Ports
The following ports may need to be mapped when running containers from the Universal Agent image.
Port | Description |
7887 | Universal Broker listening port |
7878 | OMS Server listening port |
Universal Agent Logs
The Universal Agent image configures the Universal Broker service to start in console mode, which writes all log data (unv.log and agent.log) to stdout. To view the log of a specific container, run the following command:
docker logs ua-redhat:v.r.m.m
Persisting Configuration Changes
Docker containers are ephemeral, and any data or configuration changes are expected to be lost if the container is deleted. One method to persist a custom configuration or apply a license key is to bind-mount a host directory using the --mount option when creating the container.
Docker Run Examples
The following command can be used run the Universal Agent docker image, mapping port 7887 to the docker host port 9987 and mounting a local UDM manager configuration file.
docker run --detach --publish 9987:7887 --mount type=bind,src=/path-on -host-machine/udm.conf,dst=/etc/universal/udm.conf --name udm-manager ua -redhat:v.r.m.m
The above is just one of many possibilities for integrating Docker and Stonebranch Universal Agent. To learn more about our partnership and Docker integration capabilities see our solution section.
Start Your Automation Initiative Now
Schedule a Live Demo with a Stonebranch Solution Expert