Jan's Gutter

Introducing clidev

13 Oct 2019

I’ve been using clidev to manage a set of development environments on my macOS laptop. Currently it is a thin set of bash scripting around Docker, but it can easily be adapted to other container runtimes.

Origin Story

My main development laptop has been running macOS for the last five years. It’s the product of me being curious, and the fact that most of my work happens remotely, and the tools are mostly compatible.

I started by hosting my local development environments that require Linux inside VM’s. That worked until the sheer amount of different environments became a pain to manage. Not to mention memory usage, disk footprint and VirtualBox’s drivers that need constant updating.

At that point, I could have switched to Vagrant, but then I decided to try out Docker.

What Docker is doing behind the scenes

Docker CE on macOS runs containers in a linuxkit VM inside a hypervisor called hyperkit. If you want to see more technical details, I recommend reading this blog post.

You do drop quite a bit of flexibility by not running a fully virtualised OS, but what you gain in management, latency and resource sharing is well worth it.

You only pay the cost of running the VM once, and Docker runs containers inside a shared environment. The VM adds a bit of isolation between macOS and the containers. That said, the many, many security implications of untrusted containers still apply. Running untrusted containers on your laptop is just slightly less hazardous that piping curl’s output into sudo bash.

This model neatly covers my use case.

First steps

This is probably the simplest way to get an ephemeral container based on a distribution:

docker run -it --rm centos:centos7 /bin/bash -l

This command spawns a new container, runs bash as if it had been invoked as a login and deletes the container on exit. However, there were a number of common tasks that soon started to accumulate.


I soon found out I needed scripts and files to organise the following tasks:

I had more than 8 different single-line bash scripts just for running and building the containers. At this point I really should have investigated Docker Compose but, I was not interested in building a container-based application, I was more interested in collating my runtime environments.

I wanted to apply a healthy dose of “Don’t Repeat Yourself” to the scripts, but keep most of the flexibility. And more importantly, I’d like to replace docker with podman when I eventually switch to a CentOS 8 desktop.

clidev quick setup

In your home directory (or where convenient), run the following:

git clone https://github.com/jangutter/clidev.git
git clone https://github.com/jangutter/clidev-env.git
mkdir dockermount # optional

In the clidev directory, you could edit the config.sh script if you wish to place the clidev-env directory somewhere else, or you wish to experiment with other container runtimes.

At the minimum you should edit clidev-conf/conf.d/default-config.sh and clidev-conf/conf.d/default-mounts.sh to set the default namespace, volume and temporary filesystem mounts for the dev environments.

Basic operation

clidev’s config is very much code. It’s bash scripts running other bash scripts. Do not import untrusted environments. During normal operation, clidev sources the common scripts in the conf.d directory, and scans through all the directories in the env directory. Each subdirectory there corresponds to an environment that can be built and run.

clidev.sh is not meant to be put on a system path. Normal operation assumes that you change your working directory to the clidev directory and run the script from there.

Listing available environments

On my system, the available environments show up like this:

[jangutter@laptop ~]$ cd clidev
[jangutter@laptop clidev]$ ./clidev.sh list
Environment          : Description
bionic               : Ubuntu 18.04 + Development Tools
centos7              : systemd enabled CentOS 7 + Development Tools
centos8              : CentOS 8 + Development Tools
f30                  : Fedora 30 + Development Tools
f31                  : Fedora 31 + Development Tools
jekyll               : Jekyll build environment for jangutter.com
kolla-ansible        : Kolla-ansible CLI
nova-queens-build    : CentOS 7 + Nova Queens Dev
osc-queens           : CentOS 7 + OpenStack Queens CLI
sf-3.1               : Software Factory 3.1 CLI
sf-3.2               : Software Factory 3.2 CLI
sf-3.3               : Software Factory 3.3 CLI
trusty               : Ubuntu 14.04 + Development Tools
ubi7                 : RHEL UBI 7

Building the image for an environment

To build the docker image for an environment, use the build parameter:

[jangutter@laptop clidev]$ ./clidev.sh build centos7

Running the environment

And finally, the environment can be run with:

[jangutter@laptop clidev]$ ./clidev.sh run centos7

If you want to peek under the hood, you can add -d as the first parameter to enable tracing:

[jangutter@laptop clidev]$ ./clidev.sh -d run centos7

Note that the centos7 environment is a special systemd enabled container. To exit it you should use the poweroff command, or stop it externally by using docker stop.

What next?

I’ll gradually update clidev with better documentation and more examples. At this moment it’s the fastest way for me to enter an environment to test something specific to a distribution, or to run a specific build or install environment.

Creative Commons License
Introducing clidev by Jan Gutter is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.