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 Dockerfile
s.
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!