Development Containers and k6 - grafana/devcontainer-features GitHub Wiki
Introduction
Development usually requires different tools. Often, a specific version of a given tool is required. It may also happen that two different development projects require two different versions of the same tool.
It can be said that creating a reproducible development environment is vital for development. This allows contributors to use exactly the same development environment.
Development Containers are an implementation of a reproducible development environment. Using it can make the work of k6 extension developers and contributors much easier. A playground for writing k6 tests can also be easily created using Development containers.
This post is about two k6-related use cases of Development Containers.
What are Development Containers?
Development containers, or dev containers, is an open specification for enriching containers with development specific content and settings.
From containers.dev:
A development container (or dev container for short) allows you to use a container as a full-featured development environment. It can be used to run an application, to separate tools, libraries, or runtimes needed for working with a codebase, and to aid in continuous integration and testing. Dev containers can be run locally or remotely, in a private or public cloud, in a variety of supporting tools and editors.
The Development Container Specification seeks to find ways to enrich existing formats with common development specific settings, tools, and configuration while still providing a simplified, un-orchestrated single container option – so that they can be used as coding environments or for continuous integration and testing. Beyond the specification's core metadata, the spec also enables developers to quickly share and reuse container setup steps through Features and Templates.
That means that we can use development containers to define a file in a repository that includes the exact libraries, tools, and settings we want, including a specific version of k6, or a VS Code extension and configuration settings. The Docker container will contain exactly the versions of the development tools that are defined in the JSON file.
Development containers are supported by many popular IDEs, including Visual Studio Code, JetBrains IDEs, and zed. Part of the IDE runs locally and provides a local editing experience, while a small server part of the IDE runs inside a Docker container.
As it relates to k6, there are two ways I believe we can use dev containers:
- Using dev containers to quickly set up a k6 playground, using any k6 version.
- Using dev containers to develop and test k6 extensions.
Using dev containers for k6 test development
These are some of the benefits of using dev containers to develop k6 test scripts:
- Instant playground for trying out k6 (e.g. using CodeSandbox or GitHub Codespaces)
- Consistent, reproducible development environment (e.g. k6 version)
- Easy automated setup, no manual installation required (e.g. k6)
- Automatic development environment update after configuration change.
- Support for remote development via SSH.
- Full-featured k6 test development environment in GitHub Codespaces.
Set up with GitHub Codespaces
The easiest way to try out a k6 test environment in dev containers is to fork the grafana/devcontainer-feature-demo-k6 repository. After the fork, a codespace should be created automatically.
The codespace only needs to be created for the first time, which may take a while. After that, accessing the codespace is much faster.
The codespace will automatically contain the environment defined in devcontainer.json
, which includes the k6 executable. After opening the codespace, you can type in the terminal window:
k6 run script.js
That'll run the k6 test in the repository, with the k6 version that's defined in the devcontainer.json
file.
Define the dev container k6 version
In the fork of the repository, you can find a file named .devcontainer/devcontainer.json
. For the fork, these are the contents of it:
{
"name": "devcontainer-feature-demo-k6",
"image": "mcr.microsoft.com/devcontainers/base:0-alpine",
"features": {
"ghcr.io/grafana/devcontainer-features/k6:1": { "version": "1.0.0" }
}
}
This is a minimal dev container configuration for using k6. In addition to the container name and the Alpine base image reference, it only contains the k6 dev container feature. If you'd like to change the k6 version, all you have to do is update the version property.
Using dev containers to develop k6 extensions
k6 extensions are a way for users to extend the functionality of k6. For example, we have k6 extensions that let users generate random fake data, or push logs to Loki.
To develop a new k6 extension, there are a few requirements and nice-to-haves:
- Go toolkit - Extensions are developed using the Go programming language
- xk6 - A CLI tool that helps users make custom builds of k6.
- golangci-lint - A static analysis tool for Go code.
- TypeDoc - A tool that helps generate documentation from TypeScript source code. Requires Node.js to be installed.
Installing all these tools can discourage developers from developing or contributing to k6 extensions.
In addition to having these tools installed, another challenge is making sure that developers have the same environment, and same version of these tools, installed on their systems. The golangci-lint project version, for example, is constantly updated, and it’s not always compatible. Certain extensions can also require a specific version of Go to work correctly.
Dev containers can help guarantee that developers have the same environment, and the same tools when developing k6 extensions:
- Consistent, reproducible development environment.
- Easy automated setup.
- A secure development environment isolated from the host.
- Automatic development environment update after configuration change.
- Support for remote development via SSH.
- Full-featured k6 extension development environment in GitHub Codespaces.
Example devcontainer.json setup
The following is an example of a devcontainer.json
file with the recommended requirements to develop a k6 extension:
{
"name": "devcontainer-feature-demo-xk6",
"image": "mcr.microsoft.com/devcontainers/base:1-bookworm",
"features": {
"ghcr.io/devcontainers/features/go:1": {
"version": "1.23",
"golangciLintVersion": "1.63.4"
},
"ghcr.io/grafana/devcontainer-features/xk6:1": { "version": "0.14.0" },
"ghcr.io/devcontainers/features/node:1": { "version": "22" }
}
}
You can find the example file in the grafana/devcontainer-feature-demo-xk6 repository.
That's a relatively minimal dev container configuration for developing k6 extensions. In addition to the container name and the Debian base image reference, it only contains the following Dev Container feature references:
- Go - The latest
1.23.x
version of the Go toolkit withgolangci-lint
version1.63.4
. - xk6 - The
xk6
tool version0.14.0
. - Node.js - Node.js version
22
for generating documentation with TypeDoc.
Set up with GitHub Codespaces
The quickest way to try out the k6 extension development setup using dev containers is to fork the grafana/devcontainer-feature-demo-xk6 repository. After the fork, a codespace should be created automatically.
The codespace only needs to be created for the first time, which may take a while. After that, accessing the codespace is much faster.
The codespace will automatically contain the environment defined in devcontainer.json
, which includes the Go toolkit and xk6 tool. After opening the codespace, you can type in the terminal window:
xk6 run script.js
The command will build k6 with the extension and also run script.js
with the newly built k6. This means that both the Go toolkit and xk6 are available.
Set up with VS Code
You can develop k6 extensions in VS Code using the Dev Containers extension.
The quickest way to try out the k6 extension development environment in Visual Studio Code is to fork the grafana/devcontainer-feature-demo-xk6 repository. After forking, clone the repository and open it with VS Code. When opening the extension's working directory, VS Code automatically detects the dev containers configuration and shows a popup to open the project in a dev container. After you accept it, it opens the project in dev containers and rebuilds the container image if necessary.
The development environment defined in `devcontainer.json` will be automatically available. Just type in the terminal window:
xk6 run script.js
The command will build k6 with the extension and also run script.js
with the newly built k6. This means that both the Go toolkit and xk6 are available.
Set up with other tools
In addition to GitHub Codespace and Visual Studio Code, several other tools support dev containers. It’s worth highlighting DevPod, which provides a convenient way to manage Dev Containers from the command line.
Real-world example set up
The following is the complete dev containers configuration of the xk6-faker k6 extension. It contains all the tools that may be needed during development. The primary maintainer of the extension uses dev container exclusively for its development.
{
"name": "xk6-faker",
"image": "mcr.microsoft.com/devcontainers/base:1-bookworm",
"features": {
"ghcr.io/devcontainers/features/go:1": {
"version": "1.23",
"golangciLintVersion": "1.63.4"
},
"ghcr.io/grafana/devcontainer-features/xk6:1": { "version": "0.20.1" },
"ghcr.io/michidk/devcontainers-features/bun:1": { "version": "1.2.1" },
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/szkiba/devcontainer-features/cdo:1": { "version": "0.1.2" },
"ghcr.io/szkiba/devcontainer-features/mdcode:1": { "version": "0.2.0" },
"ghcr.io/szkiba/devcontainer-features/bats:1": { "version": "1.11.1" }
},
"remoteEnv": {
"GH_TOKEN": "${localEnv:GH_TOKEN}",
"GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}"
},
"customizations": {
"vscode": {
"settings": {
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"],
"go.buildTags": "codegen"
},
"extensions": [
"EditorConfig.EditorConfig",
"esbenp.prettier-vscode",
"github.vscode-github-actions",
"github.vscode-pull-request-github",
"jetmartin.bats",
"mads-hartmann.bash-ide-vscode",
"foxundermoon.shell-format"
]
}
}
}
Customize the dev container
You can customize the tools that are automatically set up in dev containers. For example:
{
"customizations": {
"vscode": {
"settings": {
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"]
},
"extensions": [
"EditorConfig.EditorConfig"
]
}
}
}
The devcontainers.json
file above is used in the grafana/xk6-faker repository. It installs the EditorConfig extension in VSCode, and sets the golanci-lint as the linter tool with the --fast
flag.
You can also use dotfiles to customize the development environment inside of dev containers.
If you have a dotfiles repository (if you're using a tool like chezmoi) with your preferred configuration files, you can:
- Specify it in the GitHub Codespaces user settings
- Specify it in the VS Code settings