You can run Gatling load tests in Docker containers, and the most surprising thing is how much easier it makes managing distributed load generation compared to traditional setups.

Let’s see it in action. Imagine you have a simple Gatling simulation, MySimulation.scala, that hits your application endpoint.

// src/test/scala/simulations/MySimulation.scala
import io.gatling.core.Predef._
import io.gatling.http.Predef._

class MySimulation extends Simulation {

  val httpProtocol = http
    .baseUrl("http://your-app-under-test.local") // Target your application
    .acceptHeader("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
    .doNotTrackHeader("DNT", "1")
    .userAgentHeader("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36")

  val scn = scenario("Homepage Load Test")
    .exec(http("request_1")
      .get("/")
      .check(status.is(200)))

  setUp(scn.inject(rampUsers(1000) during (30 seconds))).protocols(httpProtocol)
}

To run this in Docker, you’ll need a Dockerfile and a docker-compose.yml.

Here’s the Dockerfile:

# Dockerfile
FROM maven:3.8.5-openjdk-11 AS build

WORKDIR /app

COPY pom.xml .
COPY src ./src

RUN mvn clean package -DskipTests

FROM denghong/gatling:3.7.6

COPY --from=build /app/target/scala-2.13/your-project_2.13-1.0.0-SNAPSHOT.jar /opt/gatling/user-files/simulations/

CMD ["gatling", "-s", "simulations.MySimulation"]

This Dockerfile first uses a Maven image to build your Gatling simulation into a JAR file. Then, it copies that JAR into the user-files/simulations/ directory of a Gatling Docker image. The CMD then tells Gatling to run your MySimulation.

And here’s docker-compose.yml:

# docker-compose.yml
version: '3.8'

services:
  gatling:
    build: .
    environment:
      - BASE_URL=http://host.docker.internal:8080 # Example for app running on host
    volumes:
      - ./results:/opt/gatling/results # Mount results directory for persistence
    networks:
      - load_network

  your-app: # Example service for the application under test
    image: your-app-image:latest
    ports:
      - "8080:8080"
    networks:
      - load_network

networks:
  load_network:
    driver: bridge

This docker-compose.yml defines two services: gatling (which builds and runs our simulation) and your-app (a placeholder for your application. You’d replace your-app-image:latest with your actual app image). The volumes mount is crucial; it ensures your Gatling reports are saved outside the container. The networks section creates a custom bridge network, allowing containers to communicate using service names.

To run this:

  1. Save the files as Dockerfile, docker-compose.yml, and src/test/scala/simulations/MySimulation.scala in a directory.
  2. Make sure your pom.xml is set up to package your simulation. A typical Maven pom.xml would include a scala-maven-plugin or similar to compile Scala code.
  3. Run docker-compose up --build in your terminal.

Gatling will start, run your simulation, and generate reports in a results subdirectory. You can then access these HTML reports from your host machine.

The problem Gatling in Docker solves is isolating your load generation environment. Instead of installing Gatling, Java, and dependencies on multiple machines, you define it all in code. This makes your test setup reproducible and portable. You can spin up dozens or hundreds of these Gatling containers on a cluster, each independently generating load, and have them all report back to a central point if needed, or just collect their individual reports.

The BASE_URL environment variable in docker-compose.yml is a common way to configure the target application. When running Gatling inside Docker, http://your-app:8080 would work if your-app is also a service in the same docker-compose.yml and on the same network. If your application is running outside of Docker, on your host machine for example, you’d use host.docker.internal:8080 to reach it. This special DNS name resolves to the internal IP address of the host from within the Docker container.

What most people don’t realize is how effectively Docker simplifies distributed load testing. You can easily scale out by adding more gatling services to your docker-compose.yml or by deploying these containers across a Kubernetes cluster. Each container runs an independent Gatling instance, and you can coordinate them using external orchestrators or by having them all write to a shared network file system for report aggregation. The denghong/gatling image is just one example; many other base images exist, or you can build your own with specific Java versions or Gatling plugins.

The next challenge is aggregating results from multiple distributed Gatling instances into a single, comprehensive report.

Want structured learning?

Take the full Gatling course →