How to Contribute to the LabNow AI Container Image Project: A Complete Guide

Contributing to the LabNow AI container image project involves forking the repository, modifying install-list files or the core Dockerfile in docker_core/, and submitting a pull request that triggers automated CI builds publishing to Quay.io and Docker Hub.

The lab-foundation repository from LabNow AI provides a collection of Docker images bundling complete data-science and AI environments. Built around a modular profile architecture, the project allows contributors to extend the stack by adding new language toolchains, patching existing package lists, or creating entirely new image variants that inherit from the core base image.

Understanding the Lab Foundation Architecture

The project architecture centers on a core base image defined in docker_core/Dockerfile. This foundation extends through profiles—groups of packages tailored to specific languages or toolchains such as NodeJS, Python, R, Java, and Julia.

Each profile is driven by install-list files located under docker_core/work/ (e.g., install_list_PY_datascience.pip, install_list_R_base.apt). The build system consumes these lists via ARG_PROFILE_* variables, iterating through comma-separated values to install apt or pip dependencies dynamically. Additional specialized images—for PostgreSQL, CUDA, or Atom—extend the core using FROM directives and supply their own profile arguments.

The continuous integration pipeline in .github/workflows/build-docker.yml automatically executes builds on both CPU-only and GPU runners, pushing successful images to container registries without manual intervention.

Step-by-Step Contribution Workflow

Follow these steps to submit a successful contribution to the LabNow AI container image project:

  1. Fork and clone the repository to your GitHub account, then run git clone https://github.com/<your-user>/lab-foundation.git locally.

  2. Create a feature branch using git checkout -b my-new-profile to isolate your changes from the main branch.

  3. Extend the core image by adding install-list files under docker_core/work/ and referencing them in the ARG_PROFILE_* blocks within docker_core/Dockerfile (lines 58–94).

  4. Update helper scripts if custom setup logic is required. Add reusable functions to docker_core/work/script-setup.sh and invoke them from the Dockerfile's RUN steps.

  5. Adjust CI configuration (optional) by editing .github/workflows/build-docker.yml to add new matrix entries for additional build variants or CUDA versions.

  6. Test locally by running docker build with the specific --build-arg parameters you intend to ship, such as --build-arg ARG_PROFILE_PYTHON=base,datascience,myutils.

  7. Commit and push your changes using git add . && git commit -m "Add my-new-profile" followed by git push origin my-new-profile.

  8. Open a Pull Request against LabNow-ai/lab-foundation:main through the GitHub UI, filling out the template with descriptions of your new profile and linking to relevant CI runs.

  9. Respond to review feedback by iterating on maintainer comments and pushing additional commits to your feature branch.

  10. Merge occurs automatically after approval; the CI pipeline then builds and publishes your changes to the public container registries.

Practical Example: Adding a Custom Python Package

To add a package like myutils==0.1.0 to the datascience profile, create a new install-list file and wire it into the build arguments.

First, create the install-list:


# docker_core/work/install_list_PY_myutils.pip

myutils==0.1.0  % Custom utility for data pipelines

Next, reference the profile in the Dockerfile. The docker_core/Dockerfile processes profiles through a shell loop that checks for .apt and .pip files:


# In docker_core/Dockerfile (excerpt)

&& for profile in $(echo $ARG_PROFILE_PYTHON | tr "," "\n") ; do (
      [ -f "/opt/utils/install_list_PY_${profile}.apt" ] && install_apt "/opt/utils/install_list_PY_${profile}.apt" || echo "apt install skipped for ${profile}" ;
      [ -f "/opt/utils/install_list_PY_${profile}.pip" ] && install_pip "/opt/utils/install_list_PY_${profile}.pip" || echo "pip install skipped for ${profile}"
    ) ; done \

Build the image locally to verify:

docker build \
  --build-arg ARG_PROFILE_PYTHON=base,datascience,myutils \
  -t labnow/core:myutils .

Key Files and Their Roles

Understanding these critical files ensures your contributions align with the project's modular design:

  • docker_core/Dockerfile — The central orchestrator defining all ARG_PROFILE_* hooks and the main image build logic.

  • docker_core/work/script-setup.sh — Contains shared shell functions (setup_node_*, setup_java_*, setup_R_*) for reusable setup steps across profiles.

  • docker_core/work/*.apt and *.pip — Package list files consumed by the build system; examples include install_list_PY_datascience.pip and install_list_R_base.apt.

  • docker_atom/Dockerfile — Demonstrates extending the core image with editor-specific tooling.

  • docker_db_postgres/postgres-ext.Dockerfile — Shows how database-specific images inherit from the core foundation.

  • .github/workflows/build-docker.yml — The GitHub Actions workflow controlling automated builds, matrix testing, and registry pushes.

Summary

  • The lab-foundation project uses a profile-based architecture centered on docker_core/Dockerfile and install-list files under docker_core/work/.

  • Contributors modify ARG_PROFILE_* variables and create new .pip or .apt lists to add packages without changing core build logic.

  • The script-setup.sh file encapsulates complex setup routines for languages like Java, Node, and R.

  • All changes are validated through GitHub Actions in .github/workflows/build-docker.yml before automatic publication to Quay.io and Docker Hub.

  • Local testing requires running docker build with the exact --build-arg flags specified in the Dockerfile documentation.

Frequently Asked Questions

What is the difference between an install-list file and modifying the Dockerfile directly?

Install-list files (such as install_list_PY_datascience.pip) are plain text lists of packages consumed by the parameterized build loop in docker_core/Dockerfile. This separation allows contributors to add software by creating a new list file and updating the ARG_PROFILE_PYTHON build argument, without touching the core Dockerfile logic. Direct Dockerfile modifications are only necessary when adding new setup functions or changing the build orchestration itself.

How do I test my changes before submitting a pull request?

Run docker build locally using the same --build-arg flags defined in the CI pipeline, such as --build-arg ARG_PROFILE_PYTHON=base,datascience. For comprehensive validation, use the act tool or the GitHub Actions runner Docker image to execute .github/workflows/build-docker.yml locally, which catches missing dependencies that manual builds might miss.

Can I add a completely new programming language profile to the project?

Yes. Create a new install-list file following the naming convention install_list_<LANG>_<name>.apt or .pip, add any required setup functions to docker_core/work/script-setup.sh, and expose the profile through a new ARG_PROFILE_<LANG> variable in docker_core/Dockerfile. Reference existing profiles like R or Julia in the source code as templates for structure.

Where are the container images published after my PR is merged?

The CI pipeline in .github/workflows/build-docker.yml automatically pushes successful builds to both Quay.io and Docker Hub registries. The exact repository paths and tagging conventions are defined in the workflow file and project README, ensuring your contributions become immediately available to users consuming the LabNow AI stack.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →