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.
DRY
I soon found out I needed scripts and files to organise the following tasks:
- Customise the images by adding new repos, packages and tweaking config.
- Set up volume mounts, both common and specific to different environments.
- Tweak command-line options slightly for different runtimes.
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.