Virgo recipe "Create a Custom Virgo Runtime with Dockerizor"

Virgo Homepage

Create a Custom Virgo Runtime with Dockerizor

This recipe shows how to create your own custom Virgo runtime.

Shopping list

  • Docker Build, Ship, Run

  • Gradle Build Automation

  • Groovy A multi-faceted language for the Java platform

  • Bundlor Create OSGi Metadata

  • Dockerizor - Gradle plug-in to create a Docker image that includes an Eclipse Virgo container


  • Dockerizor configuration

  • Custom Gradle build tasks


Get the code

Clone the code from the Git repository: Sample Git repository:

$ cd ~/MyAwesomeProjectDirectory/
$ git clone git://
$ cd org.eclipse.virgo.samples
$ cd recipe-custom-runtime

Once inside the source directory of this recipe - your are good to go.

Create Eclipse Project Metadata

Create the Eclipse IDE metadata with:

$ ./gradlew eclipse

Prepare the Virgo Tooling

Download Eclipse IDE for Java EE Developers e.g. Eclipse Mars.2 (4.5.2).

Start your Eclipse IDE and add the Virgo Tooling to your Eclipse IDE.

Optionally add the Docker Tooling to your Eclipse IDE.

Import the code into your Eclipse IDE

Now you can Import ▸ Gradle ▸ Gradle Project into your IDE. The project folder is called recipe-custom-runtime and lies directly in the "Sample Applications" folder you created previously with the Git clone command. (org.eclipse.virgo.samples).


Before you can drag’n’drop the project onto your freshly created Virgo Server you might have to execute Virgo ▸ Run Generation of META-INF/MANIFEST.MF (via a right click on the project) within your Eclipse IDE.

A closer look

This section describes the internal tools and configuration options available for creating a custom Virgo runtime.

Shared Dockerizor configuration

The build script settings.gradle includes two Gradle projects for two Virgo runtimes:

include 'recipe-custom-virgo-runtime'
include 'recipe-custom-virgo-app'

First: recipe-custom-virgo-runtime used during development time - without the application bundles. And a 2nd one: recipe-custom-virgo-app with the complete application packaged ready for production deployment.

For convenience the shared configuration is done in the root Gradle build script: build.gradle:

configure(dockerProjects) {

	apply plugin: 'base' (1)
	apply plugin: 'com.eclipsesource.dockerizor' (2)

	dockerizor {
		maintainer = 'Florian Waibel <>'

		javaImage = 'java:8u92-jre-alpine' (3)

		virgoVersion = 'latest'
		hudsonJobName = 'gradle-build'

		removeAdminConsole =[''] != 'true'

		virgoFlavour = 'VTS'
		virgoVersion = 'latest'

	dockerize.dependsOn configurations.repositoryExt
	dockerize.dependsOn configurations.repositoryUsr
  1. Adds the build task clean

  2. Adds the build task dockerize

  3. Docker base image

Create the development time variant

dockerizor {
	repository = 'virgo-recipe/custom-virgo-runtime' (1)
	description = 'Virgo Recipe Custom Virgo (runtime-only) created with Gradle Plugin: com.eclipsesource.dockerizor'

	createLocalCopy = true (2)
  1. Name of the generated Docker image

  2. Creates local copy ${buildDir}/virgo-\{timestamp\}.tar

In the dependencies section the provisioning of repository/ext and repository/usr takes place. The following sample demonstrates how to add:

  • an OSGi-ready library and

  • a library bundled during the custom runtime build.

dependencies {
    repositoryExt("org.mongodb:mongo-java-driver:${mongoJavaDriverVersion}") (1)
    repositoryUsr files("com.rabbitmq.amqp.client-${rabbitmqAmqpClientVersion}/build/com.rabbitmq.amqp.client-${rabbitmqAmqpClientVersion}.jar") (2)
  1. Adds OSGi-ready MongoDB driver available from Maven Central

  2. Adds bundled RabbitMQ client from local build

The task startVirgoRuntime defined in the few Groovy lines:

task startVirgoRuntime(type:Exec, dependsOn: unzipRuntime) {
    workingDir "${buildDir}/virgo"

    //on Uni*
    commandLine './bin/'

allow to test drive the Virgo runtime

$ ./gradlew :recipe-custom-virgo-runtime:startVirgoRuntime

Bundle and deploy non OSGi-ready dependencies

To be able to create and verify non OSGi-ready dependencies we need to

  • create OSGi metadata and

  • deploy the bundled jar file.

Thus we added the tasks bundlor…​

task bundlor(type: JavaExec, dependsOn: createBuildDir) {

    classpath = configurations.bundlorRuntime

    main = 'org.eclipse.virgo.bundlor.commandline.Bundlor'
    args '-D', "version=${artifactVersion}"
    args '-i', "${->configurations.sourceBundle[0]}" // lazy GString to resolve the configuration at runtime
    args '-m', "${artifactName}.mf"
    args '-o', outputFile

and deploy.

The bundlor task creates OSGi metadata for a library specified via sourceBundle inside the corresponding build.gradle. Let’s say you want to bundle the RabbitMQ AMQP Client 3.5.5 available from Maven Central:

dependencies {
  sourceBundle 'com.rabbitmq:amqp-client:3.5.5'

from a MANIFEST.MF template file:
Bundle-SymbolicName: com.rabbitmq.amqp.client
Bundle-Name: RabbitMQ Java AMQP client library
Bundle-Vendor: Eclipse Virgo
Bundle-Version: ${version}
Bundle-ManifestVersion: 2

For more details about the Bundlor syntax please see the Bundlor User Guide.

The deploy task performs the deployment via JMX with a small portion of Groovy code:

task('deploy', dependsOn: bundlor) << {
	def virgoHome = project.parent.buildDir.absolutePath + "/virgo"
	System.getProperties().put("", virgoHome + "/configuration/keystore") (1)
	def client = new JmxBuilder().connectorClient(port: 9875, properties:[])
	client.connect([ 'jmx.remote.credentials' :  ['admin', 'admin' ] as String[] ]) (2)
	MBeanServerConnection server = client.getMBeanServerConnection()
	ObjectName deployer = new ObjectName("org.eclipse.virgo.kernel:category=Control,type=Deployer"); (3)
	Object deploymentResult = server.invoke(deployer, "deploy", [outputFile.toURI().toString() ] as Object[],
	[String.class.getName() ] as String[])
  1. Configure SSL trust store

  2. Create JMX client with Virgo default credentials

  3. Create Virgo JMX deployer

To deploy the generated bundle into a running sample runtime you can run the Gradle task deploy like this:

$ ./gradlew :recipe-custom-virgo-runtime:com.rabbitmq.amqp.client-3.5.5:deploy

Dockerise the Application

We use Gradle and Dockerizor to build the application. Instead of running the sample within the Eclipse IDE you can build a Docker image:

$ ./gradlew dockerize

and run the application with:

$ docker run --rm -it --name custom-runtime --publish 8080:8080 virgo-recipe/custom-runtime-app

Virgo plan are a proven way to add the application bundles to a Virgo runtime. The snippet below shows the Gradle build file (Dockerizor configuration) needed to add such a plan file.

dockerizor {
	repository = 'virgo-recipe/custom-virgo-app' (1)
    description = 'Virgo Recipe custom Virgo created with Gradle Plugin: com.eclipsesource.dockerizor'

	pickupFiles = ['recipe-custom-virgo.plan'] (2)
  1. Name of the generated Docker image

  2. Adds Virgo plan file to the Docker image

Once the image is built with ./gradlew dockerize it can be started with Docker:

$ docker run -it --rm virgo-recipe/custom-virgo-app

Congratulations. You’ve successfully containerized your Virgo applications.