Docker-Printer
docker-printer
is a CLI for easily managing multistep and branching dockerfiles.
Regular multi-stage dockerfiles and docker build
commands are incredibly powerful and useful; however, they are designed for building a single image. Multistage builds can be used to define multiple related images, but this quickly results in complicated dockerfiles, possibly duplicated instructions, and complicated collections of build commands.
docker-printer
addresses this in two main ways:
By allowing dockerfiles to be composed from re-usable modules.
By building bake files for use by
docker buildx bake
that consolidate the build processes of multiple images in multiple environments into a single configuration file.
Example
Consider trying to build two related Python images with just a few dependencies or files differing between the two, then both a development and production version of each. You might have something like the following:
FROM python:latest AS base
COPY requirements.txt /requirements.txt
RUN pip install -r requirements.txt
FROM base AS dev_matplotlib
RUN pip install matplotlib
FROM base AS dev_plotly
RUN pip install plotly
FROM dev_matplotlib AS prod_matplotlib
WORKDIR /app
COPY app /app
CMD ['flask', '/app/app.py']
FROM dev_plotly AS prod_plotly
WORKDIR /app
COPY app /app
CMD ['flask', '/app/app.py']
And you now need to manage at least four different build commands, one for each target. Additionally, if this begins to branch beyond just a couple of variations, the dockerfile can quickly get unwieldy, and the code duplication can quickly get problematic.
Existing solutions include:
Using Docker Compose to point at each build target, consolidating the build command into a single compose file.
Consolidating re-used setup commands into a bash file, and executing that in each duplicate stage
Writing scripts for developers that enumerate all the build commands
Docker Printer provides another option that relies on nothing more than multistage builds and, if desired, docker buildx
, while providing no-duplication, high-speed, templatable, branching, and self-arranging dockerfiles. It also provides an easy way to share best practices for accomplishing common tasks in a dockerfile, such as how to cache downloads while installing packages with apt-get
or pip
.
Getting Started
To get started, install docker-printer
:
pip install docker-printer
Then initialize the printer configuration in your repository:
docker-printer init
This will create the folders and files necessary to use docker-printer
.
Next, you’ll define the following for your particular dockerfile needs:
Define templates, which are Jinja2 template files that represent stages (or parts of stages) in your build process.
Define modules, which populate templates to represent a particular re-usable stage in a dockerfile.
Specify your final desired targets, which define the output images from your dockerfile.
Define one or more build configurations that describe which targets will be built and where they’ll be stored
In summary, your dockerfile is defined as a collection of linked stages, each of which are generated by a module filling in a template, with the final arrangement of stages being defined and named by the desired targets. The build commands for this dockerfile are provided in an easy JSON format compatible with docker buildx bake
.
Once you have your definitions laid out, you can synthesize your final Dockerfile and, if desired, your bake files.