Default configuration is a great place to start with a project. We at JBoss try
to make our projects (and
products too!) usable out-of-box for as
many use cases as we can, but there is no way that one configuration could
satisfy everyone’s needs. For example, we ship 4 flavors of the standalone.xml
configuration file with WildFly since there are so
many different deployment scenarios. But this is still not enough. We need to be able to
tweak it at any point. The jboss/wildfly
image is not an exception here.
Following the Docker recreate — do not modify principle we do change the
configuration by creating a new image (in most cases). This allows us to reuse
the images (consider the jboss/wildfly
image itself).
Of course this is not the only way to modify the WildFly configuration, so let’s iterate over available options.
Update 24.07.2014
One of the readers brought up that I forgot to mention one great tool: Augeas. I’ve added it now to the list and summary.
TL;DR;
See summary.
Boot time configuration
Using command line parameters (or environment variables) is the simplest way to modify the default configuration. This does not require rebuilding the image but is not persistent. Still, in many cases it is the best approach.
There is one obvious limitation: only a limited set of things
can be modified. WildFly allows us to customize parameters with the switches for
the standalone.sh
or domain.sh
startup scripts. The
WildFly
documentation has a great summary of the available options.
Command line parameters
With the jboss/wildfly
image it’s easy to use command line parameters. Just
override the default command when launching the container, for example:
docker run -it jboss/wildfly /opt/wildfly/bin/domain.sh -b 0.0.0.0 -Djboss.management.http.port=8888
This launches WildFly in
domain
mode (instead of standalone), binds the public endpoint to every
interface, and exposes the management endpoint on port 8888
(by
default bound to 127.0.0.1
).
Note
|
You can create your own image which overrides only the command to run. Use the CMD instruction in Dockerfile .
|
Environment variables
Specifying environments variables with Docker is easy too:
docker run -it -e JBOSS_LOG_DIR=/opt/wildfly/logs jboss/wildfly
And now all logs will be saved to the /opt/wildfly/logs
directory.
Note
|
You can modify environment variables in Docker images too. Use the ENV instruction in Dockerfile .
|
Explore the --env-file
parameter of docker run
if you want to set many
environment variables.
sed
Note
|
This example is available on GitHub. |
The sed
command may be used in your Dockerfile
to modify some (small) parts of
the configuration. Please note that WildFly stores configuration in XML format
so you will need to be careful when using sed
:)
There are possible use cases for sed
, for example when you want to disable the coloring on the console:
sed -i 's|named-formatter name="COLOR-PATTERN"|named-formatter name="PATTERN"|' /opt/wildfly/standalone/configuration/standalone.xml
In general no, I do not recommend using sed
because using regular expressions may
be tricky, especially if you’re not familiar with them.
xmlstarlet
Note
|
This example is available on GitHub. |
The xmlstarlet
tool is a set of commands that can be helpful when interacting
with XML files. In our case one command is especially useful: xmlstarlet ed
which is used to modify XML documents.
Let’s say we want to change the root-logger
level to DEBUG
:
xmlstarlet ed -L -u "//*[local-name()='root-logger']/*/@name" -v "DEBUG" /opt/wildfly/standalone/configuration/standalone.xml
You can place the above in your Dockerfile
and call it done.
Although xmlstarlet
is nice at finding (using XPath) and editing attributes
or elements, it’s not a great tool to add complex elements. It can become
easily very verbose. If you don’t trust sed
but still want to tweak some
elements, use xmlstarlet
instead!
The jboss/wildfly
image contains the xmlstarlet
utility installed by default (as of July 23rd).
XSLT transformations
Note
|
This example is available on GitHub. |
XSLT transformations are a nice way to execute conditional modifications of the WildFly application server configuration. The WildFly team provides examples of xsl files. You can use Saxon to execute the transformation:
java -jar /usr/share/java/saxon.jar -s:/opt/wildfly/standalone/configuration/standalone.xml -xsl:/opt/wildfly/customization/changeIPAddresses.xsl -o:/opt/wildfly/standalone/configuration/standalone.xml publicIPAddress=0.0.0.0
In this example we change the default binding address of the server for public ports.
For more information about using the Saxon utility from the CLI, please refer to the documentation.
The jboss/wildfly
image contains the saxon
package installed by default (as of July 23rd).
Using jboss-cli.sh
Note
|
This example is available on GitHub. |
WildFly ships with a powerful CLI. The documentation contains a few examples of how the CLI can be used. Of course the CLI is perfect to modify the server configuration.
To be able to modify the configuration the WildFly server needs to be
running. Since at the build time of a Docker image based on jboss/wildfly
(in most cases) we do not start WildFly, this can be a problem.
One solution is to boot WildFly, execute the CLI commands and shutdown the
server. I used this approach in
my
example. It adds a new ExampleMySQLDS
datasource to the server. The main file that does
the job is the
execute.sh
script:
#!/bin/bash JBOSS_HOME=/opt/wildfly JBOSS_CLI=$JBOSS_HOME/bin/jboss-cli.sh JBOSS_MODE=${1:-"standalone"} JBOSS_CONFIG=${2:-"$JBOSS_MODE.xml"} function wait_for_server() { until `$JBOSS_CLI -c "ls /deployment" &> /dev/null`; do sleep 1 done } echo "=> Starting WildFly server" $JBOSS_HOME/bin/$JBOSS_MODE.sh -c $JBOSS_CONFIG >dev/null & echo "=> Waiting for the server to boot" wait_for_server echo "=> Executing the commands" $JBOSS_CLI -c --file=`dirname "$0"`/commands.cli echo "=> Shutting down WildFly" if [ "$JBOSS_MODE" = "standalone" ]; then $JBOSS_CLI -c ":shutdown" else $JBOSS_CLI -c "/host=*:shutdown" fi
The script is general purpose and can be reused in some other images. It can modify the configuration for any WildFly operating mode and for any configuration.
The
commands.cli
file contains commands executed in the CLI.
# Mark the commands below to be run as a batch batch # Add MySQL driver /subsystem=datasources/jdbc-driver=mysql:add(driver-name=mysql,driver-module-name=com.mysql.jdbc,driver-xa-datasource-class-name=com.mysql.jdbc.jdbc2.optional.MysqlXADataSource) # Add the datasource data-source add --name=UnifiedPushDS --driver-name=mysql --jndi-name=java:jboss/datasources/ExampleMySQLDS --connection-url=jdbc:mysql://localhost:3306/sample?useUnicode=true&characterEncoding=UTF-8 --user-name=user --password=password --use-ccm=false --max-pool-size=25 --blocking-timeout-wait-millis=5000 --enabled=true # Execute the batch run-batch
The CLI approach is very powerful and flexible. The only caveat is that WildFly needs to be running to use the CLI.
Using custom configuration files
Note
|
This example is available on GitHub. |
The last approach is to simply maintain a separate configuration file for
WildFly. Just ADD
your configuration to the
/opt/wildfly/{standalone|domain}/configuration
directory and override the
default boot command. You can for example remove some subsystems like I did in
the
example.
This is the simplest and cleanest approach. This way you have full control over the configuration at any time. The bad thing is that you need to maintain the file yourself. If a new version of WildFly will be released — you need to manually apply the changes to the configuration.
Augeas
Note
|
This example is available on GitHub. |
Augeas is a general purpose configuration editing tool. It has plugins (lenses) for many configuration files. If your file isn’t on the list — don’t worry — you can use some generic lenses. In our case it’ll be the Xml lens.
Augeas builds a tree of the file loaded. Just take a look at the example where
we change the root-logger
(and cosnole-handler
) level to DEBUG
.
augtool -LA -e <<EOF set /augeas/load/Xml/lens Xml.lns set /augeas/load/Xml/incl[2] /opt/wildfly/standalone/configuration/standalone.xml load defvar subsystem "/files/opt/wildfly/standalone/configuration/standalone.xml/server/profile/subsystem[#attribute/xmlns='urn:jboss:domain:logging:2.0']" set $subsystem/console-handler/level/#attribute/name "DEBUG" set $subsystem/root-logger/level/#attribute/name "DEBUG" save EOF
It looks like XPath, but is much simpler. In previous exmaple we modified the
attribute but it’s easy to add new elements too. Let’s add a TRACE
log level
for our pl.goldmann.example
category:
set $subsystem/logger[last()+1]/#attribute/category "pl.goldmann.example" set $subsystem/logger[last()]/level/#attribute/name "TRACE"
The first command adds a new <logger/>
element with pl.goldmann.example
as
the category
attribute and the next line adds a new <level/>
element under
the previously created <logger/>
and sets the name
atrtibute to TRACE
.
Isn’t nice?
Augeas is definitely a project worth to become familiar with. Above was just a tiny example of what it can do.
The jboss/wildfly
image contains the augeas
utility installed by default (as of July 24rd).
Summary
Every approach has pros and cons. Boot time configuration is great if you want
to change some exposed parameters. The sed
and xmlstarlet
options are
similar providing a simple way to change some parts of the configuration. But
this is not flexible. XSLT transformations are very powerful, but they require
some amount of work to write the stylesheets properly. The jboss-cli.sh
aproach is very good if you don’t mind starting and stopping WildFly at the
build time. Maintaining own configuration file at the first glance looks like a
best solution and probably it is in some cases. If you want to do have a
powerful yet simple way of changing the configuration — use Augeas.
What’s your approach?