Working with dev containers in CLion
by Mike Przybylski
Previously
Creating a build environment for libbpf-based programs
Let my people code
One of my pet peeves as a software engineer is a project that requires a litany of manual steps before I can produce a working binary, or make full use of CLion’s powerful code indexing and navigation features. So one of the things I try really hard to do when structuring a project’s build system is to minimize the number of manual steps required between cloning its source files and coding, building, and testing.
Docker has always been wonderfully helpful in this regard. It provides a language for creating repeatable, tailored environments for building software, and excellent utilities for interacting with those environments. CLion’s support for Development Containers makes Docker containers even more powerful by using them as the basis for easily provisioned, repeatable, development environments.
The bpf-iotrace
development container
The most fundamental component of the bpf-iotrace
development container is
its Dockerfile,
which automates the creation of development environment described in my
previous post.
Next,
there is devcontainer.json
which references the Dockerfile, and defines additional runtime options for the container including --privileged
,
and the sysfs
mounts
needed to interact with the kernel’s eBPF subsystem.
Those options allow a developer to run gentoo emerge
commands with all of their sandbox features enabled,
and to run eBPF code directly from the container.
Dockerfile
and devcontainer.json
also define an unprivileged user in the container
to minimize file ownership issues with the project source files on the host.
Finally,
there is toolchain.cmake
which tells CMake the names of compilers in container’s custom toolchain.
CLion and development containers in action
CLion can work with development containers in two modes: cloning a project directly into a container, or mounting a local project in a container. I prefer the latter because it makes it easier to throw away a container after a failed experiment without losing work.
So far,
the only way I’ve found to launch a development container with local sources mounted in it from a JetBrains product is
to open the project’s devcontainer.json
in a local instance of CLion…
…and then click the button in the editor’s left-hand gutter.
I then select “Create Dev Container and Mount Sources…”
This builds the development container. The process can take a significant amount of time since it has to build GCC, Clang, and other associated tooling and libraries from source. (I have plans to speed up this process by building most of the development container in GitHub Actions and hosting its image in GitHub’s Container Registry.)
Once the build is complete, I make sure CLion is selected in the drop-down menu at the top of the window, and click the “Continue” button. This launches the CLion remote development backend in the development container and connects to it with an instance of JetBrains Client running on my laptop. Note the bpf-iotrace source code mounted in my container from my home directory.
Reopening a CLion project in an existing development container
After a workstation restart or similar event, there are two ways to reopen a CLion project in an existing development container.
Via JetBrains Gateway
Open the JetBrains Gateway application
Select “Dev Containers” in the right-hand column.
Click on the menu item for the development container you want to open.
Via CLion
Select “Remote Development…” from the File menu.
Select “Dev Containers” in the left-hand column.
Click on the development container you wish to use.
Another development container use case: software packaging for non-native Linux distributions
My daily driver for this work is an x86_64 laptop running Debian 12.
This made it challenging to work on gentoo packages
because part of the workflow involves running commands
like ebuild ./foo-1.2.3-r4.ebuild manifest
to update checksums in package manifest files.
By defining a simple development container in my rescued-ebuilds
overlay,
I can easily launch a properly configured environment for working on ebuilds any time I need it.
Up Next
Managing dependencies in vcpkg
Additional references
CMake toolchains
Development Containers
Development Containers in CLion
- https://www.jetbrains.com/help/clion/prerequisites-for-dev-containers.html