Skip to content

Instantly share code, notes, and snippets.

@javaducky
Last active December 8, 2022 16:16
Show Gist options
  • Save javaducky/6954ae9f67ec0b0420bfc21f9e8017b3 to your computer and use it in GitHub Desktop.
Save javaducky/6954ae9f67ec0b0420bfc21f9e8017b3 to your computer and use it in GitHub Desktop.
How-to and resources to build and run a custom k6 binary with xk6 extensions using Docker. Go(lang) setup not required.

Build and run k6 with xk6 extensions using Docker

Not everyone loves the Go programming language as myself...I get that. If you're just looking to be able to use k6 OSS with some available extensions and don't want to mess with setting up a Go(lang) environment, then this gist is for you!

🎅 What will this do for me?

This will provide a couple resources to make it simple to create your own customized version of k6 and execute tests all within Docker.

It should come as no surprise that you will need Docker installed!

💁 Why do I want this?

The extension ecosystem for k6 requires building a custom executable binary containing the extended functionality you desire. As the k6 engine is written with the Go programming language, you would typically need to have a Go compiler installed in your system to create the new version of k6. Not a Herculean effort, but not something everyone wants to mess with. Docker provides the opportunity to have an ephemeral build environment to do the specialized work so you can just focus on your load tests written in Javascript.

🙋 How do I use this?

Pull down the attached Dockerfile, script_vars.env, and docker-run.sh files into your project directory. This project directory is expected to contain your *.js Javascript file(s) either either in the same directory or any child directory.

Once you've gone through the available extensions and decided which features you'd like to include, open the Dockerfile to begin updating the --with ... selections. Official Grafana extensions will start with github.com/grafana/ then the extension name, e.g. xk6-sql. Community extensions will be similar, but will have a different organization name, e.g. github.com/szkiba/xk6-dashboard for the xk6-dashboard.

The fiddly part will be modifying the Dockerfile---I'm sorry, there's really no way around it, but it should be straightforward. We'll be changing, or adding more lines like the --with .... You'll see that the section has been called out.

Even better, you can easily create this command using the bundle builder!

Congratulations! You're ready build. From same directory containing your Dockerfile, open the Terminal and run the following Docker command:

docker build -t k6-extended:latest .

This may take a couple (or few) minutes initially, but this will download the Go environment within a Docker image, then install the xk6 utility and your desired extensions, compiles the whole thing, then builds a Docker image containing your custom k6 binary.

Now you can run scripts from your local project using your extended version of k6 via Docker. The docker-run.sh script makes this easy-peasy if you're on a Mac or Linux system. If you're on Windows, I'm afraid I don't have a docker-run.bat version for you at this time.

Just run ./docker-run.sh <RELATIVE PATH TO YOUR SCRIPT>.

🚀 Happy load testing!

#!/usr/bin/env zsh
set -e
if [ $# -ne 1 ]; then
echo "Usage: ./docker-run.sh <SCRIPT_NAME>"
exit 1
fi
# By default, we're assuming you created the extended k6 image as "k6-extended:latest".
# If not, override the name on the command-line with `IMAGE_NAME=...`.
IMAGE_NAME=${IMAGE_NAME:="k6-extended:latest"}
# Define the environment file containing variables to be passed along to the k6 container.
ENV_FILE=${ENV_FILE:="script_vars.env"}
# Each execution is provided a unique `testid` tag to differentiate discrete test runs.
# (Not required, but provided for convenience)
SCRIPT_NAME=$1
TAG_NAME="$(basename -s .js $SCRIPT_NAME)-$(date +%s)"
# This is a basic wrapper to run a clean docker container
# --env-file : filename providing environment variables for use by k6 and extensions
# -v : we're allowing scripts to be located in the current directory, or any of its children
# -it : running interactively
# --rm : once the script completes, the container will be removed (good housekeeping, you'll thank me)
#
# Anything after the $IMAGE_NAME are passed along for the k6 binary.
docker run --env-file $ENV_FILE -v $PWD:/scripts -it --rm $IMAGE_NAME \
run /scripts/$SCRIPT_NAME --tag testid=$TAG_NAME
# Multi-stage build to generate custom k6 with extension
# Stage 1 - download xk6 and desired extensions, then compile a new binary.
#
FROM golang:1.19-alpine as builder
WORKDIR $GOPATH/src/go.k6.io/k6
ADD . .
RUN apk --no-cache add build-base git
RUN go install go.k6.io/xk6/cmd/xk6@latest
#
# 1) Copy the following `--with ...` line, modifying the module name for additional extension(s).
# 2) CGO_ENABLED will ideally be '0' (disabled), but some extensions require it be enabled. (See docs for your extensions)
#
RUN CGO_ENABLED=1 xk6 build \
--with github.com/grafana/xk6-sql \
--output /tmp/k6
# Stage 2 - Copy our custom k6 for use within a minimal linux image.
#
FROM alpine:3.16
RUN apk add --no-cache ca-certificates \
&& adduser -D -u 12345 -g 12345 k6
COPY --from=builder /tmp/k6 /usr/bin/k6
USER 12345
WORKDIR /home/k6
ENTRYPOINT ["k6"]
# Place your environment variables in this file.
# See https://k6.io/docs/using-k6/environment-variables/ for more information and recall
# that environment variables have a higher order of precedence than configuration values
# within your scripts! (https://k6.io/docs/using-k6/k6-options/how-to/#order-of-precedence)
#
#K6_VUS=5
#K6_ITERATIONS=15
#K6_DURATION=10s
# Example configuration options for using xk6-output-prometheus-remote
#
#K6_PROMETHEUS_RW_USERNAME=
#K6_PROMETHEUS_RW_PASSWORD=
#K6_PROMETHEUS_RW_SERVER_URL=
#K6_OUT=xk6-prometheus-rw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment