Docker Support

Roboconf has a target implementation for Docker.
From the Roboconf perspective, Docker is seen as a kind of IaaS. Roboconf may create and manage docker containers, that run Roboconf agents (just like VMs) and can be used as deployment targets.

To install it, open the DM’s interactive mode and use one of the following options.
With the roboconf:target command:

# The version will be deduced automatically by the DM
roboconf:target docker

Or with the native Karaf commands:

# Here in version 0.7
bundle:install --start mvn:net.roboconf/roboconf-target-docker/0.7

Sample target.properties.
Just copy / paste and edit.

# Configuration file for Docker
id = <to set>
handler = docker

# Provide a meaningful description of the target
name = 
description = 

# Docker API
docker.endpoint = http://localhost:4243
docker.image = 

#docker.user = guest
#docker.password = guest
#docker.email = guest@something.com
#docker.version = 
#docker.run.exec = 

# Image Generation

#docker.generate.image = 
#docker.agent.package.url = 
#docker.agent.jre-packages = 
#docker.additional.packages =  
#docker.additional.deploy = 

# docker.base.image = ubuntu:latest
# docker.download.base-image = true
# docker.image.registry = registry.hub.docker.com

Here is a complete description of the parameters for Docker.
Let’s begin with general parameters.

Property Description Default Mandatory
id The target’s ID. none, must be set yes
handler Determines the target handler to use. none, must be “docker” yes
name A human-readable name for the target - no
description A description of the target. - no
docker.endpoint The end-point URL of Docker (requires Docker to be setup to use a TCP port). http://localhost:4243 no
docker.image The ID or tag (name) of the docker image used as a template for the VM (as shown by “docker images”, for example). If the image is not found, Roboconf will try to generate one, using “<docker.image>:<docker.image>” as its tag: if so, the docker.agent.package property is required so that Roboconf knows where to find the Roboconf agent to install on the generated image. If it is an image ID, it must be the full ID, that can be retrieved with docker images –no-trunc. “generated.by.roboconf” no
docker.user The name of the user to connect. none no
docker.password The password of the user to connect. none no
docker.email The email of the user to connect. none no
docker.version The Docker version (for API compatibility). This version supports versions until Docker v1.17. none no
docker.run.exec The command line to run in the created Docker container. See dedicated The docker.run.exec property section below See the section below no

Let’s now take a look at parameters related to image generation.

Property Description Default Mandatory
docker.generate.image A boolean value that indicate whether a Docker image for Roboconf should be generated. Disabled by default. false no
docker.agent.package.url If you want this extension to generate a Docker image for you, this parameter is an URL that points to the ZIP or TAR.GZ file of a Roboconf agent distribution. If not specified, Roboconf will try to guess it. The guess process is described in this section below. See below no
docker.agent.jre-packages If you want this extension to generate a Docker image for you, this parameter indicates the JRE to install (as a system package), as well as other optional packages, separated by spaces. The package name(s) must be understandable by the apt package manager (Debian-based Linux distributions). openjdk-7-jre-headless no
docker.additional.packages Additional packages to install on the generated image, using apt-get install. The package name(s) must be understandable by the apt package manager (Debian-based Linux distributions). none no
docker.base.image If Roboconf generates an image for you, this property is used to determine the base image to use. The generated Dockerfile will begin with FROM docker.base.image… If the base image does not exist, it can be downloaded if docker.download.base-image is set to true. Otherwise, an error will be thrown. Examples: ubuntu, ubuntu:latest ubuntu no
docker.additional.deploy A list of URLs that point to additional elements you would like to deploy in Karaf / the Roboconf agent. Example: bundles. Local and remote URLs are supported (http, file…). URLs should be separated by spaces. If you have several ones, we suggest you put one URL per line, each line ending with ` \`, except the last one. This will keep your target.properties file readable. none no
docker.download.base-image If set to true, and that the base image does not exist, then it will be downloaded from a Docker registry. false no
docker.image.registry If the base image must be downloaded, then it will be retrieved from this Docker registry. registry.hub.docker.com no

At least one of docker.image or docker.agent.package must be specified.

As a good practice, docker.image should always be specified.
Even when Roboconf generates the image.

The docker.run.exec property

This target property holds a command line to pass to the Docker container when it is started.
By default, a Roboconf agent is started, but it is possible to specify another command to do special things before/while the Roboconf agent is started.

The value of this property must be formatted using the JSON string array syntax.

The default value for this property is…

[
  "/usr/local/roboconf-agent/start.sh",
  "etc/net.roboconf.messaging.$messagingType$.cfg",
  "agent.application-name=$applicationName$",
  "agent.scoped-instance-path=$instancePath$",
  "agent.messaging-type=$messagingType$",
  "$msgConfig$"
]

The parameter values prefixed and suffixed by the dollar symbol are replaced at runtime by Roboconf. Indeed, a Roboconf agent needs some configuration before it can run.
The docker.run.exec property allows to use several markers, that will be substituted by the actual configuration for the agent.

Marker Description
$applicationName$ The name of the application
$instancePath$ The path of the scoped instance
$messagingType$ The type of the messaging factory
$msgConfig$ The messaging configuration properties

There is one more thing about the $msgConfig$ marker, which is a bit more special than the other ones. As it expands to several arguments, it can only be used alone verbatim, in its own argument. This marker is substituted by each one of the Roboconf agent messaging configuration property, in a separated argument, prefixed with msg..

According to the substitution rules explained above, and for…

… then the command line will be substituted and expanded to…

/usr/local/roboconf-agent/start.sh \
    "etc/net.roboconf.messaging.telegraphy.cfg" \
    "agent.application-name=app" \
    "agent.scoped-instance-path=/path/to/instance" \
    "agent.messaging-type=telegraphy" \
    "msg.code=morse" \
    "msg.medium=wire"

Notice that parameters injection only works when variables are in their own argument.
Said differently, if you override the default value, the JSon array cannot mix a variable with something else.

# OK! will expand to "msg.property1=value1", "msg.property2=value2", …
"$msgConfig$"

# Not OK! $msgConfig$ can only be used alone in its own argument.
"msgParam:$msgConfig$"

# Not OK! Same as above, only usable alone.
"$messagingType$ $msgConfig$"

# OK! Used in separated arguments.
"type=$messagingType$", "$msgConfig$"

The docker.agent.package.url property

This property holds an URL that points to a Roboconf agent distribution (either a ZIP or a tar.GZ file).
If not specified, Roboconf tries to guess it. First, it assumes the agent’s version should be the same that the DM’s one. By introspecting its configuration, the DM can find it (provided it runs in an OSGi environment). Then, it tries to find a Maven artifact that will match the agent’s distribution for this version.

Here is the resolution order:

  1. Try to find it in the local Maven repository.
  2. If it is not found locally, contact Sonatype’s web service API to find it.

Sonatype is the Maven provider/intermediate Roboconf uses for snapshots builds hosting and releases management.
Snapshot versions resolution will use the latest build. Released versions are hosted by public Maven repositories, including Maven Central.

Notice that it is not possible to download snapshots of released versions. As soon as a version is released, all the snapshots are deleted.

Docker Configuration

See Roboconf’s Docker tips for details about installing and preparing docker for Roboconf.
You will also find a reminder about basic Docker commands.

Docker Options

Docker CLI and Docker’s remote API allows you to pass various options.
Some of these options can also be passed via Roboconf to create a new container (i.e. docker run…).

These options are only used when Roboconf creates a container.
Other operations, like creating an image, cannot use them.

Since these options are passed with the Java REST API, Roboconf only supports a subset of options.
Only those of type int, long, boolean, string, array of string and array of capabilities are supported.
These options must be prefixed with docker.option.run..

Let’s take a look at examples.

# Set the host name
docker.option.run.hostname = some host name

# Set the CPU share
docker.option.run.cpushares = 512
docker.option.run.cpu-shares = 512

# Attach the standard error with the container
# (probably useless with Roboconf but this is for the example)
docker.option.run.attachstderr = true
docker.option.run.attach-stderr = true

# Add capacilities
docker.option.run.capadd = SYS_PTRACE, AUDIT_CONTROL
docker.option.run.cap-add = SYS_PTRACE, AUDIT_CONTROL

# Remove capabilities
docker.option.run.capdrop = MKNOD, AUDIT_CONTROL
docker.option.run.cap-drop = MKNOD, AUDIT_CONTROL

Options can be found in the remote API’s guide.
Given the way Roboconf passes these options to the REST clients, it is possible some options fail to be set. Complex ones are not supported at all (e.g. ExposedPorts).

If you need support for new options, or if one does not work, please submit a feature request and/or a bug report.

Docker RUN with Roboconf

This section clarified the way Roboconf creates Docker containers.
Here is what it executes, if docker.command.use is set to true (or not set at all).

docker run <docker.image> <docker.command.line>

With default values, and assuming id is the ID of an image tagged with generated-by-roboconf, then the previous command is equivalent to…

docker run id /usr/local/roboconf-agent/start.sh

Docker options (for the RUN) can be set.
Read the previous section about this.

Privileges

docker.option.run.cap-add can be used to change privileges.
Indeed, some Software component cannot be installed with the default configuration.
As an example, if set to SYS_PTRACE, then Roboconf will execute…

docker run --cap-add SYS_PTRACE id /usr/local/roboconf-agent/start.sh

Such permissions are sometimes necessary.
See these discussions on Github for additional information.

Preparing your own Docker image

This is NOT necessary if the image is generated by Roboconf,
i.e. if docker.agent.package was specified in the target.properties file.

Start a Docker container using a docker system image (e.g. Ubuntu):

docker run -v /tmp:/roboconf -t -i ubuntu /bin/bash

Note: the container started above shares the local /tmp as /roboconf under Docker (using the -v option).
This can be useful to share files between the local file system and the Docker container (e.g. to install the Roboconf agent).

Let’s assume you have copied the Roboconf agent in the shared /roboconf directory (here, the local /tmp).
In the Docker container, execute the following commands.

apt-get update
apt-get install openjdk-7-jre-headless
cd /usr/local
tar xvzf /roboconf/roboconf-karaf-dist-agent.tar.gz
ln -s roboconf-karaf-dist-agent/ roboconf-agent

Now, you have to add a start.sh executable script in the /usr/local/roboconf-agent directory.
Set the following content (the script is mainly used to complete the agent setup at startup time).

#!/bin/bash"
# Startup script for a Roboconf agent on Docker
# Find the file containing the messaging configuration
msgConfigFile=$1

# Prepare configuration files
cd /usr/local/roboconf-agent
echo "# Agent configuration - DO NOT EDIT: Generated by Roboconf" > etc/net.roboconf.agent.configuration.cfg
echo "# Messaging configuration - DO NOT EDIT: Generated by Roboconf" > $msgConfigFile

# And update them
for p in \"$@\"
do
	if [[ $p == msg.* ]] ;
		echo ${p:4} >> $msgConfigFile
	else [[ $p == agent.* ]] ;
		echo ${p:6} >> etc/net.roboconf.agent.configuration.cfg
	fi
done

# Start Karaf
cd bin
./karaf

The container is now ready to become a Docker image.
Outside docker, keep track of its ID, that will be useful to build the image.

Now, your image is created.
Retrieve its image ID using docker images, and use it as docker.image in the Roboconf configuration (target.properties).