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 type in…

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

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

# Configuration file for Docker
target.id = docker

docker.endpoint = http://localhost:4243
docker.image = 0f3087570887fdgf14dfg1dd4f
docker.user = guest
docker.password = guest

Here is a complete description of the parameters for Docker.

Property Description Default Mandatory
target.id Determines the target handler to use. none, must be “docker” yes
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.agent.package 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. The generated image is based on Ubuntu. none 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.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… It is your responsibility to verify this image is available locally (either you created it, or you pulled it from Docker’s hub). If the base image does not exist, an error will be thrown. ubuntu no
docker.command.line A command line to pass to the Docker container when it is created. /usr/local/roboconf-agent/start.sh no
docker.command.use A boolean to indicate whether Roboconf should pass a command when it creates a new Docker container. Set it to false if you added a CMD instruction in your Dockerfile. true 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.

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.

Running Docker in a VM

There are two options to manage Docker containers in a VM with Roboconf.
The first one relies on the idea that a Roboconf agent will manage them. This solution is not yet implemented.

The other option relies on the DM.
It implies you have a hierarchy of instances that looks like…


instance of VM {
	instance of Docker {
		instance of MyApp {
			#...
		}
	}
}

Roboconf will create all these instances, the VM, the Docker container and the application.
The secret here relies on the fact that both VM and Docker are components associated with the target installer. From Roboconf’s point of view, it is all about nested scoped instances (or nested containers).

VM can match any target in general (including EC2, Openstack or even Docker).
Let’s assume it is EC2 (Amazon Web Services).

To have such a use case work, you must have Docker installed on the VM.
It means your virtual image (appliance or AMI) must have Docker installed. And your Docker properties (those you pass to Roboconf in the target.properties file) must reference the IP address of the VM. Since this IP address is not known at modeling time, you will use a variable that will be expanded by Roboconf at runtime.

Here is a sample target.properties for Docker in this use case.

# Configuration file for Docker
target.id = docker

docker.endpoint = http://{{ ip }}:4243
docker.image = gen
docker.agent.package = http://maven.../roboonf-agent.tar.gz

The end-point will be completed with the right IP address when the container is created.
Only ip is supported at the moment.

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).