Container-based development with toolboxcutter

Container-based development with toolboxcutter

James Reed's photo
James Reed
·Nov 6, 2022·

4 min read

Toolbx is a tool for Linux systems, and specifically Fedora, that creates and manages development environment containers. Its purpose is to group development dependencies in a mutable container separate from the base operating system both for the benefit of separating concerns and allowing dev. environments to be reused and shared.

Note: toolbx was originally named toolbox.

Typical usage might look like this:

[user@hostname ~]$ toolbox create
Created container: fedora-toolbox-36
Enter with: toolbox enter
[user@hostname ~]$ toolbox enter

While this may provide the foundation to a compelling development workflow, I felt something was missing. From my perspective, a development environment is specific to the project being developed.

So, you could use toolbox like this:

[user@hostname ~]$ cd my-project
[user@hostname my-project]$ toolbox create my-project-toolbox
[user@hostname my-project]$ toolbox enter my-project-toolbox

And proceed to install dev. dependencies in your container, but I want a toolbox that can be created and recreated on-demand, from a Dockerfile, for example. It then makes sense to commit this dev. environment manifest to your project so that your environment's specifications follow your project's development. Ultimately, what I sought was a means to more easily manage per-project toolboxes, which prompted the creation of toolboxcutter.

toolboxcutter

toolboxcutter (invoked as tb) is a script that manages the lifecycle of per-project development containers using Dockerfiles.

It began life as a zsh function, but as its feature set expanded, I realized it had become a project of its own, so I ported it to a standalone bash script.

It's designed to be easy to use. Within a directory containing a toolbox-based Dockerfile, simply run tb and your toolbox will be entered, creating the container if necessary.

A complete overview of its functionality is given in its command-line usage message:

usage: tb [command]

With no command, enter toolbox.

commands:
  init IMAGE      Initialize Dockerfile based on IMAGE
  create [IMAGE]  Create container (from IMAGE if provided)
  recreate        Remove and recreate container
  build           Build image
    options:
      -n NAME       Name of image
      -c            Build without cache
  rebuild         Remove container and rebuild image
    options:
      -n NAME       Name of image
      -c            Build without cache
  stop            Stop container
  rm              Remove container
  rmi             Remove image
  rpkg            Build rpm via rpkg
    options:
      -n NAME       rpkg spec template name
      -e EXT        rpkg spec template extension
  rpkg-install    Build and install rpm via rpkg
    options:
      -n NAME       rpkg spec template name
      -e EXT        rpkg spec template extension
      -r NAME       Name of produced rpm to install
  run COMMAND     Run COMMAND in toolbox
  version         Show version

As tb is largely a wrapper around toolbox, most of its commands translate directly to their toolbox equivalents. These are supplemented with image and container management commands that would otherwise require invoking podman.

Building RPM packages

Unique to toolboxcutter is its ability to build RPM packages from rpkg .spec template files. This feature has been instrumental in the development, testing, and dogfooding of my own projects while using Fedora. I believe it elevates tb to a truly powerful developer tool for these reasons:

  • Build dependencies need only exist in your project's container, minimizing pollution of your workstation's environment;
  • Most importantly, the development-packaging cycle is combined into a single fluid process, providing interactivity benefits similar to that of a read-eval-print loop.

This functionality depends on the availability of rpkg in the toolbox container itself, so your project's Dockerfile should install it. Below is the Dockerfile for base image I use:

FROM registry.fedoraproject.org/fedora-toolbox:36

RUN dnf install -y git-subtree
RUN dnf install -y make
RUN dnf install -y neovim
RUN dnf install -y rpkg # Install rpkg
RUN dnf install -y rpmdevtools
RUN dnf install -y zsh

CMD /usr/bin/zsh

Any images or containers derived from this can be used to build RPM packages provided a .spec template. By default, tb looks for this file at spec/*.rpkg.spec in your project's root directory.

Here is toolboxcutter's own .spec template file:

%global cli_cmd tb

Name: {{{ git_cwd_name name="toolboxcutter" }}}
Version: {{{ git_cwd_version lead="$(git tag | sed -n 's/^v//p' | sort --version-sort -r | head -n1)" }}}
Release: 1%{?dist}
Summary: A script to automate use of toolbox

License: MIT
URL: https://github.com/jcrd/toolboxcutter
VCS: {{{ git_cwd_vcs }}}
Source0: {{{ git_cwd_pack }}}

BuildArch: noarch

BuildRequires: perl

Requires: bash
Requires: dnf
Requires: toolbox

%global debug_package %{nil}

%description
toolboxcutter automates use of toolbox using per-project Dockerfiles.

%prep
{{{ git_cwd_setup_macro }}}

%build
%make_build PREFIX=/usr

%install
%make_install PREFIX=/usr

%files
%license LICENSE
%doc README.md
/usr/bin/%{cli_cmd}
/usr/share/man/man1/%{cli_cmd}.1.gz

%changelog
{{{ git_cwd_changelog }}}

Documentation about the format of these templates is sparse and much of my knowledge was gleaned from existing files. Nevertheless—perhaps with a bit of trial and error—it is possible to run tb rpkg-install in your project's directory to produce an installable RPM package with your latest changes!

 
Share this