Refactoring Cortex: Parameterizing Docker Image Builds
· Categories: cortex, docker, make, refactoring, ci, 100hellos
The Challenge: Hardcoded Image Prefixes
The cortex directory, responsible for building Docker images for various programming language environments (originally part of the โ100 Hello Worldsโ project), had a small limitation: the Docker image prefix was hardcoded as 100hellos/ throughout its Makefiles, utility scripts, and even Dockerfiles.
While this worked perfectly for its original purpose โ building and publishing images under the 100hellos namespace โ it presented a challenge when integrating cortex into a larger project (agentt). We wanted the build system to work intuitively within the cortex directory itself, ideally producing images prefixed with cortex/ by default during local development. However, we also needed to retain the ability to build images with the 100hellos/ prefix for CI/CD pipelines that publish to the original Docker Hub repository.
The Goal: Flexibility and Consistency
Our goal was twofold:
- Local Development: Allow developers working within the
cortexdirectory to runmake <language>and get an image namedcortex/<language>:localby default. - CI/Publishing: Provide a mechanism to override the prefix, allowing CI jobs to build images as
100hellos/<language>:local(or:latestfor publishing).
The Solution: Introducing TAG_PATH_ROOT
We addressed this by introducing a Make variable, TAG_PATH_ROOT, to control the image prefix.
- Default Behavior: In the main
cortex/Makefile, we setTAG_PATH_ROOT ?= $(shell basename ${PWD}). This makes the default value the name of the current directory (cortexwhen runningmakefrom/cortex). - Override Mechanism: Users can override this default in several ways:
make TAG_PATH_ROOT=100hellos <target>(The explicit way)make P=100hellos <target>(A shorter alias)make PREFIX=100hellos <target>(Another alias)
- Propagation: This
TAG_PATH_ROOTvariable is now consistently passed down through:- Recursive
makecalls to language subdirectories. - Arguments to the
.utils/build_image.shscript. - Arguments to the
.utils/functions.shscript (for dependency resolution). - Docker build arguments (
--build-arg TAG_PATH_ROOT=...).
- Recursive
- Dockerfile Adaptation: All relevant
Dockerfiles were updated:ARG TAG_PATH_ROOTwas added at the top.FROM 100hellos/...:locallines were changed toFROM ${TAG_PATH_ROOT}/...:local.
- Dependency Fix: The dependency resolution logic in
.utils/functions.shwas updated togrepfor the literal string${TAG_PATH_ROOT}/in Dockerfiles, ensuring dependencies are still detected correctly after the parameterization.
The Outcome
This refactoring provides the desired flexibility:
- Running
make javainsidecortexnow correctly buildscortex/100-java11:localand thencortex/java:local. - Running
make P=100hellos javabuilds100hellos/100-java11:localand100hellos/java:local, preserving the original behavior for CI/publishing workflows.
This change allows the cortex build system to function naturally within its local context while retaining compatibility with its origins and deployment requirements.
This article was originally created in commit 46166f8b1f344533bce5ce0ffbc3de0e3068d027, prompted by commit 46166f8b1f344533bce5ce0ffbc3de0e3068d027.