The mess that is a development setup

You might be running something like openSUSE Tumbleweed, Leap or MicroOS for your day to day development. Traditionally the workflow involves installing all sorts of tools you might need, enabling fun development repos like devel-perl or app-specific repos and tweaking the system configuration to your liking. Sooner or later you will learn about the existence of --allow-vendor-change and how priorities work. And as you wonder how to avoid breaking your system with conflicting packages somebody drops the containers buzzword on you! 🤓🚀

Containers all the way

Enter toolbox. This nice little project is actually doing a really simple job with a big impact. Behind the scenes podman containers are created with the right knobs set to do get you going without having to figure out all of the little details of setting up a container, mounting files or user setup.

sudo zypper in toolbox

Installation is just a command away!

A word about IDs and namespaces

This is something that you shouldn’t care about but unfortunately you need to take a minute to take in the principle before you can get started. If you’ve used rootless podman you can probably skip this section, though.

There is two magic files called /etc/subuid and /etc/subgid which declare ID mappings on the host system. Since we want to run a container that may use different groups, run as a different user or elevate priviledges within the container something has to translate IDs of users and groups.

The most convenient way to ensure you have IDs mapped is to run the following command as the user you want to development with:

sudo usermod --add-subuids 524288-1878523903 --add-subgids 524288-1878523903 $USER
grep $USER /etc/sub{u,g}id
podman system migrate

This is analogous to editing the files /etc/subuid and /etc/subgid by hand. The range we are choosing here is a particular range reserved for containers by systemd, which is especially relevant when dynamic users such as managed by systemd-homed come into play.

So how do I use this toolbox?

The default I’m going to recommend is really easy:

toolbox enter

Note: Do not use sudo or other measures that might seem like they would enhance your experience. You want to run your toolbox, and by extension your podman container behind the scenes, as your user.

The first time you use it, this will fetch you a fresh container image of openSUSE Tumbleed and as such may take a moment. Grab a cup of tea, coffee or perhaps a glass of water whilst the download is on-going - it’s important to stay hydrated 🍵👍

This looks exactly the same

Not much is going to look different once you’re in. Your ~/.bashrc will be used by the default bash shell. Chances are it looks the same as it did before. You may want to tweak your prompt to reveal wether you’re inside a container. The variable $container makes that straightforward:

[ -n "$container" ] && PS1=$PS1'🐋'

There is no host

If we go a little further, though, we will quickly find that there are some differences:

cat /etc/os-release
zypper lr
gcc --help

Depending on your setup you’ll be noticing some unexpected outputs. I won’t spoil it here. 😏

Exploring even more, we find that we’re definitely not working on the host anymore:

systemctl status postgresql
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

You may want to disagree with that last part of the output. What’s going on here is expected, though. The container is not running systemd at all!

Can I haz root?

So far we’ve used toolbox as a regular user. Thanks to the toolbox enter invocation which I would recommend as the default way of using it we get passwordless sudo out of the box:

sudo zypper in gcc

At this point you can install your development packages as usual. What’s great about this, though, is that you’re still inside the container so everything you’re doing here doesn’t affect the host at all.

Toolboxes go beyond Tumbleweed

It turns out since we’re just using containers here, we can run other distros, too. For example Fedora!

toolbox enter -i fedora -t fedora
sudo dnf in vim

What I’ve done here is I’ve used the shortname for the latest Fedora image. And since it’s not openSUSE anymore I use dnf to install packages.

The -i switch I’ve used above specifies the image whilst the -t switch specifies the tag. Both are identical above. If you want to use multiple containers for different purposes you can indeed give them separate names very easily:

toolbox enter -t sandbox
gcc

Notice how this one doesn’t have gcc even though we installed it earlier? That’s because it is a different container!

Meanwhile outside of the toolbox

Toolboxes are basically containers:

toolbox list
CONTAINER ID  IMAGE                                   COMMAND     CREATED      STATUS                    PORTS   NAMES
e0d97864d49e  registry.opensuse.org/opensuse/toolbox  sleep +Inf  3 minutes ago   Exited (143) About a minute ago          toolbox-kalikiana-user-sandbox
ee43e0841272  docker.io/library/fedora:latest         sleep +Inf  9 minutes ago  Exited (143) 4 minutes ago          toolbox-kalikiana-user-fedora
6ee693742b77  registry.opensuse.org/opensuse/toolbox  sleep +Inf  12 days ago  Up About an hour ago              toolbox-kalikiana-user

Since this is implemented based on podman you can even use podman ps -a to inspect your toolboxes or podman rm to delete containers you no longer use. Naming generally follows the pattern of toolbox-$USER-user-$TAG where the tag defaults to the image name if it’s not the default image.

I want more flexibility than this!

If this did wet your appetite and you want even more, I recommend reading the official docs. You may want to create a ~/.toolboxrc for maximum satisfaction and dive into the -r switch for non-development use cases. Perhaps you even want to make toolbox your login shell.