Create custom WildFly container images with S2I toolkit

Source-to-Image (S2I) is a toolkit for building container images from source code. S2I produces ready-to-run images by injecting source code into a container image and letting the container prepare that source code for execution. By creating self-assembling builder images, you can version your images and control your build environments exactly like you use container images to version your runtime environments. In this tutorial we will learn how to create S2I images of WildFly from source code.

To run this tutorial you need to download the S2I toolkit from: https://github.com/openshift/source-to-image

Follow the instruction on the README page of the github repository to install S2I.

Using S2I with WildFly

In its simplest workflow, S2I can be used to build a container image of WildFly from source code. We’ll assume that you have a maven project that builds a simple Web application in the current path:

├── pom.xml
├── README.md
└── src
    └── main
        └── webapp
            └── index.jsp

Next, pull WildFly latest image:

$ docker pull quay.io/wildfly/wildfly-centos7

We will now use the s2i tool to create the S2I WildFly builder image:

$ s2i build . quay.io/wildfly/wildfly-centos7 wildfly-demo

When the build has completed, you can run the image named “wildfly-demo” as follows:

$ docker run --rm -p 8080:8080 --name wildfly wildfly-demo

You will see that the server boots in foreground mode and that the application has been deployed in the Root Web context:

16:53:16,366 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 80) WFLYUT0021: Registered web context: '/' for server 'default-server'
16:53:16,427 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 46) WFLYSRV0010: Deployed "ROOT.war" (runtime-name : "ROOT.war")

S2I build workflow

The s2i build workflow includes a set of steps:

  • Creates a container based on the build image using the application source in src
  • Sets the environment variables from .s2i/environment (optional)
  • Starts the container and runs its assemble script
  • When done, commits the container, setting the CMD for the output image to be the run script and tagging the image with the name provided.

Let’s see how to customize our image of wildfly, by adding a .s2i/bin/assemble file.

Within the assemble file, we need to call the original assemble script for WildFly image and then (or before) we can add our customization. As an example, we will add a sample Web application in the deployments folder after that the original assemble phase has completed:

#!/bin/sh
# Original assemble script
/usr/local/s2i/assemble

mkdir /opt/wildfly/standalone/deployments/hello.war
echo "Hello world" > /opt/wildfly/standalone/deployments/hello.war/index.jsp
touch /opt/wildfly/standalone/deployments/hello.war.dodeploy

If you re-execute the s2i build command, and run again the “wildfly-demo” you will see that the “hello.war” application (created with the assemble script) has been deployed:

16:53:16,366 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 80) WFLYUT0021: Registered web context: '/' for server 'default-server'
16:53:16,366 INFO  [org.wildfly.extension.undertow] (ServerService Thread Pool -- 83) WFLYUT0021: Registered web context: '/hello' for server 'default-server'
16:53:16,427 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 46) WFLYSRV0010: Deployed "ROOT.war" (runtime-name : "ROOT.war")
16:53:16,428 INFO  [org.jboss.as.server] (ServerService Thread Pool -- 46) WFLYSRV0010: Deployed "hello.war" (runtime-name : "hello.war")

Customize server artifacts

With the assemble script, you can execute scripts or create/replace files at the end of the build phase. If you want to perform advanced configuration changes, it is recommended to use CUSTOM_INSTALL_DIRECTORIES. The CUSTOM_INSTALL_DIRECTORIES is a list of comma-separated list of directories used for installation and configuration of artifacts for the image during the S2I process. This information can be included via a custom install.sh script. The location of CUSTOM_INSTALL_DIRECTORIES can be set in the environment file. Let’s put it in practice to show how to execute CLI command during the s2i build.

Start by creating a folder named “extensions” in the root folder of your project:

$ mkdir extensions

Within the extension folder, add a file named install.sh, which launches the install-common.sh to set environment variables and then add in a file named configuration.cli, the list of CLI commands:

#!/usr/bin/env bash
injected_dir=$1
source /usr/local/s2i/install-common.sh

S2I_CLI_SCRIPT="${injected_dir}/configuration.cli"

echo "/system-property=property1:add(value=property1-value)" > "${S2I_CLI_SCRIPT}"

run_cli_script "${S2I_CLI_SCRIPT}"

We just need to define the location of CUSTOM_INSTALL_DIRECTORIES. This can be done in a file named .s2i/environment as follows:

CUSTOM_INSTALL_DIRECTORIES=extensions

Here is the final application tree:

├── extensions
│   └── install.sh
├── pom.xml
├── README.md
├── .s2i
│   ├── bin
│   │   └── assemble
│   └── environment
└── src
    └── main
        └── webapp
            └── index.jsp

Now, rebuild the image:

$ s2i build . quay.io/wildfly/wildfly-centos7 wildfly-demo

Next, run the image:

$ docker run --rm -p 8080:8080 --name wildfly wildfly-demo

If you log into the docker image, you will see that the configuration also includes a System Property named “property1”:

    <system-properties>
        <property name="property1" value="property1-value"/>
    </system-properties>

That’s all. We have covered how to use the S2I tool to create container images of WildFly from source code.

The source code for this tutorial is available at: https://github.com/fmarchioni/mastertheboss/tree/master/openshift/s2i

Found the article helpful? if so please follow us on Socials