# LabNow AI Image Versioning and Tagging Strategy: A Complete Technical Guide

> Explore the LabNow AI image versioning and tagging strategy. Learn how Docker tags, GitHub Actions, and helper scripts ensure efficient image management in the lab-foundation repository.

- Repository: [LabNow.ai/lab-foundation](https://github.com/labnow-ai/lab-foundation)
- Tags: how-to-guide
- Published: 2026-03-05

---

**LabNow AI employs a systematic Docker tagging convention that combines explicit runtime versions in image names (e.g., `python-3.12:latest`) with generic alias tags (e.g., `python:latest`), all orchestrated through GitHub Actions and helper scripts in the `lab-foundation` repository.**

LabNow AI maintains a comprehensive image versioning and tagging strategy within the `labnow-ai/lab-foundation` repository to ensure reproducible environments while providing convenient access to latest stable builds. This approach leverages explicit version identifiers in image names alongside `latest` tags and generic aliases, all automated through continuous integration pipelines. Understanding this strategy enables developers to select precise runtime versions or trust the most recent stable releases with confidence.

## Base Image Versioning with Runtime-Specific Tags

LabNow AI encodes the exact runtime version directly into the image name using the pattern `<name>-<runtime-version>:latest`.

In [`.github/workflows/build-docker.yml`](https://github.com/labnow-ai/lab-foundation/blob/main/.github/workflows/build-docker.yml), the `build_image` function constructs these tags by passing version arguments to the Docker build context. For example, Python images are built with explicit version parameters:

```bash

# .github/workflows/build-docker.yml

build_image python-3.12 latest docker_base/Dockerfile --build-arg "PYTHON_VERSION=3.12"

```

The `docker_base/Dockerfile` consumes these arguments through `ARG` directives, ensuring the installed runtime matches the tag:

```dockerfile

# docker_base/Dockerfile

ARG PYTHON_VERSION="3.12"
RUN setup_conda_with_mamba ${PYTHON_VERSION}

```

This pattern applies consistently across JDK, Node.js, and CUDA variants, where `VERSION_JDK`, `VERSION_NODE`, or `CUDA_VERSION` arguments drive the installation of specific versions.

## Generic Alias Tags for Convenience

To simplify image references, LabNow AI employs an aliasing strategy that maps version-specific images to generic names using the `alias_image` utility defined in [`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh).

After building a version-specific image such as `jdk-11:latest`, the workflow creates a generic alias:

```bash

# .github/workflows/build-docker.yml

alias_image jdk-11 latest jdk latest && push_image jdk

```

This command tags the `jdk-11:latest` image as `jdk:latest`, allowing users to pull `labnow/jdk:latest` and automatically receive the most recent JDK major version without knowing the specific release number. The same pattern applies to Python stacks, where `python-3.12:latest` can be aliased to `python:latest`.

## Stack Image Tagging Strategy

Composite stack images follow a simplified tagging approach using `docker_core/Dockerfile`, which accepts multiple `PROFILE_*` build arguments to assemble full environments.

These stack images—such as `full-stack`, `data-science-stack`, and `jupyter-stack`—receive only a `latest` tag directly, without version suffixes in the name:

```bash

# .github/workflows/build-docker.yml

build_image full-stack latest docker_core/Dockerfile \
  --build-arg "PROFILE_DEV=true" \
  --build-arg "PROFILE_DS=true"

```

The `docker_core/Dockerfile` uses these profile flags to layer additional tools atop base images, producing tagged releases like `full-stack:latest` that represent complete, ready-to-use development environments.

## Multi-Registry Mirror Strategy

The tagging system supports multi-registry deployments through environment variables defined in the CI workflow. Images are pushed to a destination registry (default `quay.io`) using `REGISTRY_DST`, with optional mirroring to secondary registries.

The `docker_docker_kit/Dockerfile` builds an image-syncer tool that facilitates this mirroring process, ensuring that tags like `python-3.12:latest` and their generic aliases remain synchronized across infrastructure boundaries. The workflow references `REGISTRY_SRC` and `REGISTRY_DST` variables to determine push targets for all `push_image` operations.

## Build Automation via tool.sh

Underlying the entire versioning strategy is [`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh), a helper script that implements the `build_image`, `alias_image`, and `push_image` functions used throughout the CI pipeline.

These functions standardize tag construction and registry operations across different image types. For instance, `build_image` automatically applies the `latest` tag specified in the second argument, while `alias_image` creates symbolic tag references without rebuilding layers. This abstraction ensures consistent tagging behavior whether building base language runtimes or complex stacked environments.

## Summary

- LabNow AI uses explicit runtime versions in image names (e.g., `python-3.12:latest`) to ensure reproducibility across development environments.
- Generic alias tags (e.g., `python:latest`, `jdk:latest`) point to the most recent stable versions via the `alias_image` command in [`.github/workflows/build-docker.yml`](https://github.com/labnow-ai/lab-foundation/blob/main/.github/workflows/build-docker.yml).
- Stack images like `full-stack:latest` are tagged directly without version suffixes, representing complete pre-configured environments built from `docker_core/Dockerfile`.
- Build-time `ARG` parameters in Dockerfiles (such as `PYTHON_VERSION` and `VERSION_JDK`) guarantee that tagged images contain the exact specified runtime versions.
- The [`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh) script provides standardized `build_image`, `alias_image`, and `push_image` functions that enforce consistent tagging across the CI pipeline.
- Multi-registry support via `REGISTRY_DST` and the image-syncer in `docker_docker_kit/Dockerfile` ensures tags remain available across distributed infrastructure.

## Frequently Asked Questions

### How does LabNow AI handle multiple versions of the same language runtime?

LabNow AI builds separate images for each runtime version using distinct name suffixes (e.g., `python-3.12`, `python-3.11`) while applying the `latest` tag to the most recent build. The `alias_image` command then creates generic pointers (e.g., `python:latest`) that reference the preferred default version, allowing teams to pin to specific releases or follow the latest stable iteration.

### What is the difference between base images and stack images in the tagging strategy?

Base images (built from `docker_base/Dockerfile`) include explicit version identifiers in their names, such as `jdk-11:latest` or `python-3.12:latest`, and correspond to single language runtimes. Stack images (built from `docker_core/Dockerfile`) combine multiple profiles and tools into unified environments like `full-stack:latest` or `data-science-stack:latest`, receiving only generic `latest` tags without version suffixes.

### How can I pull a specific version rather than the latest alias?

Specify the full image name including the runtime version and the `latest` tag, such as `labnow/python-3.12:latest` or `labnow/jdk-11:latest`. This references the explicit version build rather than the generic alias (e.g., `labnow/python:latest`), ensuring you receive the exact runtime environment encoded in the image name.

### Where are the image tagging commands defined in the repository?

The core tagging logic resides in [`.github/workflows/build-docker.yml`](https://github.com/labnow-ai/lab-foundation/blob/main/.github/workflows/build-docker.yml), which orchestrates calls to `build_image`, `alias_image`, and `push_image`. These helper functions are implemented in [`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh) at the repository root, while version arguments are defined in `docker_base/Dockerfile` and `docker_core/Dockerfile` through `ARG` directives.