Friday, July 01, 2016

More tips and tricks for running Gatling in Docker containers

This post is a continuation of my previous one on "Running Gatling tests in Docker containers via Jenkins". As I continued to set up Jenkins jobs to run Gatling tests, I found the need to separate those tests for different environments - development, staging and production. The initial example I showed contained a single setup, which is not suitable for multiple environments.

Here is my updated Gatling directory structure


Note that I created a separate directory under simulations for each environment (development, staging, production), each with its own simulation files.

I also created a data directory under user-files, because that is the default location for CSV files used by Gatling feeders.

Most importantly, I created a separate configuration directory (staging, production) under gatling/conf, each directory containing its own customized gatling.conf file. I started by copying the gatling-defaults.conf file from GitHub to gatling/conf/staging/gatling.conf and gatling/conf/production/gatling.conf respectively.

Here is what I customized in staging/gatling.conf:

mute = true # When set to true, don't ask for simulation name nor run description
simulations = user-files/simulations/staging

I customized production/gatling.conf in a similar way:

mute = true # When set to true, don't ask for simulation name nor run description
simulations = user-files/simulations/production

Setting mute to true is important because without it, running Gatling in a Docker container was segfaulting while waiting for user input for the simulation ID:

Select simulation id (default is 'gatlingsimulation'). Accepted characters are a-z, A-Z, 0-9, - and _ 
Exception in thread "main" java.lang.NullPointerException
at$Selector.loop$1(Selection.scala:127) at$Selector.askSimulationId(Selection.scala:135) at$Selector.selection(Selection.scala:50) at$.apply(Selection.scala:33) at at at$.start(Gatling.scala:57) at$.fromArgs(Gatling.scala:49) at$.main(Gatling.scala:43) at

The other customization was to point the simulations attribute to the specific staging or production sub-directories.

Since the CSV files containing URLs to be load tested are also environment-specific, I modified the Simulation.scala files to take this into account. I also added 2 JAVA_OPTS variables that can be passed at runtime for HTTP basic authentication. Here is the new Crawl object (compare with the one from my previous post):

object Crawl {
  val feeder = csv("staging-urls.csv").random

  val userName = System.getProperty("username")
  val userPass = System.getProperty("password")

  val crawl = exec(feed(feeder)
    .get("${loc}").basicAuth(userName, userPass)

One more thing is needed: to make Gatling use a specific configuration file instead of its default one, which is conf/gatling.conf. To do that, I set GATLING_CONF as an ENV variable in the Dockerfile, so it can be passed as a 'docker run' command line parameter. Here is the Dockerfile:

# Gatling is a highly capable load testing tool.
# Documentation:
# Cheat sheet:

FROM java:8-jdk-alpine

MAINTAINER Denis Vazhenin

# working directory for gatling

# gating version

# create directory for gatling install
RUN mkdir -p gatling

# install gatling
RUN apk add --update wget && \
  mkdir -p /tmp/downloads && \
  wget -q -O /tmp/downloads/gatling-$ \$GATLING_VERSION/gatling-charts-highcharts-bundle-$ && \
  mkdir -p /tmp/archive && cd /tmp/archive && \
  unzip /tmp/downloads/gatling-$ && \
  mv /tmp/archive/gatling-charts-highcharts-bundle-$GATLING_VERSION/* /opt/gatling/

# change context to gatling directory
WORKDIR  /opt/gatling

# set directories below to be mountable from host
VOLUME ["/opt/gatling/conf", "/opt/gatling/results", "/opt/gatling/user-files"]

# set environment variables
ENV PATH /opt/gatling/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV GATLING_HOME /opt/gatling
ENV GATLING_CONF /opt/gatling/conf


Finally, here is how I invoke 'docker run' to tie everything together:

docker run --rm -v ${WORKSPACE}/gatling/conf:/opt/gatling/conf -v ${WORKSPACE}/gatling/user-files:/opt/gatling/user-files -v ${WORKSPACE}/gatling/results:/opt/gatling/results -e GATLING_CONF="/opt/gatling/conf/staging" -e JAVA_OPTS="-Dusers=$USERS -Dduration=$DURATION -Dusername=myusername -Dpassword=mypass" /PATH/TO/DOCKER/REGISTRY/gatling

Note the GATLING_CONF parameter passed with -e with the value of /opt/gatling/conf/staging. Also note the username and password JAVA_OPTS parameters.

Happy load testing!

1 comment:

Arkka Dhiratara said...

Hi Grig,

I'm very new on load testing using gatling.

Just wondering, do you prefer to run this docker-gatling as a single container on each host/node (we could maximize the throughput for each gatling script) on each host/node,

or it is better to use multiple (hundreds) of containers on each host/node, but with more smaller gatling's load?

how about the saturation?