Background

This is the second post in a series where I’m looking at using Locust with Docker to do some load testing against an Apache HTTP Server web server.

Posts in this Series

Part 2 - Testing the Locust Docker Image

The Locust File

Before we can test the image we have built, we need to create a Locust file. This file is a fairly straight forward piece of Python that defines the load test. In the ~/loadtest/ directory we create locust.py as:

import locust
import resource
import urllib3
from locust.contrib.fasthttp import FastHttpUser

class MyUser(FastHttpUser):

    resource.setrlimit(resource.RLIMIT_NOFILE, (999999, 999999))
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

    @task
    def do_get(self):
        self.client.verify = False
        self.client.get("/")

    wait_time = between(0.1, 2)

This is a simple Locust file, tweaked to use the FastHttpUser task and additionally to ignore any TLS certificate warnings. You can read more about Locust files here and here.

Testing the Locust Container

Having built a Locust Docker image, the next step is to try it out and make sure it actually works. We can do that with a docker command:

sudo docker run --rm --name standalone --hostname standalone \
    --volume /home/user/loadtest:/locust \
    --publish 8089:8089 \
    --env targetHost="https://somebox.somedomain.sometld" \
    --detach debian:locust

run means simply run a Docker container.

--rm tells docker to remove the container when it has stopped running, so we can keep things relatively tidy.

--name sets the name of the container and --hostname gives it a hostname. We are using Locust in standalone mode, so that’s what we will call the container.

--volume is used to mount a location (usually a directory) on the host to a location within the container in the format <host directory path>|<container mount location>

--publish tells Docker to bind a port on the container to a port available on the host, in the format <host port>:<container port>. This is explained in more detail in the Docker documentation, but essential with a bit of extra cli-fu you can bind container ports for different protocols (TCP, UDP) and to alternate IP addresses on the host.

--env sets an environment variable that will be available within the docker container. This will be used by the shell script embedded in the Locust Docker image that we created in part 1.

--detach means runs run the container in the background. Sometimes it can be useful to not do this and run the container in the foreground, which will display its standard output on the console.

Finally, debian:locust tells Docker which image to use in order to create the container.

The above command can be slightly more succinctly written as:

sudo docker run --rm --name standalone --h standalone \
    -v /home/user/loadtest:/locust -p 8089:8089 \
    -e targetHost="https://somebox.somedomain.sometld" \
    -d debian:locust

If the command works, it will return a long hex string (the container id), e.g.:

993d2272fac7aec1bfc8e6623a5fb4e94b522317a33964e9a4717b181f6d2d8d

With the Docker container started, you should be able to access the running standalone Locust instance via http://<IP Address or hostname of Docker host>:8089, e.g. http://192.168.1.21:8089 and run a load test against the target host.

In part 3 I will look to work out how we can use the power of Docker to get the Locust containers to bind to specific IP addresses, for the purpose of issuing requests to a web server.