# Setting Up Node.js Environments with pnpm or bun in LabNow AI Docker Images

> Quickly set up Node.js environments with pnpm or bun in LabNow AI Docker images. LabNow AI simplifies your development workflow with modular shell helpers for dynamic installation.

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

---

**LabNow AI provides modular shell helpers in [`docker_atom/work/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/docker_atom/work/script-setup.sh) that install pnpm or bun dynamically during Docker builds based on the `ARG_PROFILE_NODEJS` build argument.**

The labnow-ai/lab-foundation repository delivers Docker images optimized for AI/ML workflows requiring modern JavaScript tooling. Setting up Node.js environments with pnpm or bun in LabNow AI Docker images relies on a parameterized build system that installs package managers on-demand through shell utilities rather than static Dockerfile layers.

## How LabNow AI Installs Node.js Package Managers

The foundation images use a centralized utility architecture to keep Dockerfiles clean and avoid layer duplication. All language runtime installers reside in shell scripts that the build system sources dynamically at image creation time.

### Base Image Architecture and Utility Scripts

The base image definition in `docker_atom/Dockerfile` copies the entire `work/` directory into `/opt/utils/` during the build process. This directory contains [`script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/script-setup.sh), which houses the installation logic for both package managers. The CI pipeline invokes these utilities indirectly through [`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh), a wrapper script that sources [`/opt/utils/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main//opt/utils/script-setup.sh) and dispatches the appropriate setup routine based on build-time parameters.

### The Core Setup Helper Functions

Two specific functions in [`docker_atom/work/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/docker_atom/work/script-setup.sh) handle Node.js package manager installation:

- **`setup_node_pnpm`** (lines 59-71): Detects the host OS and architecture, downloads the latest pnpm release from GitHub, installs the binary to `/usr/local/bin/pnpm`, and adds `PNPM_HOME` to the system PATH. The function concludes by executing `pnpm --version` to log the installed version in the Docker build output.

- **`setup_node_bun`** (lines 73-87): Detects the host OS and architecture, retrieves the latest bun release from GitHub, unpacks the zip to `/opt/bun`, symlinks `bun` into `/usr/bin/`, and extends the PATH. The function verifies the installation with `bun -v`.

Both helpers fetch the latest release at build time, ensuring images always contain current versions without requiring manual Dockerfile updates.

## Configuring Docker Builds for pnpm or bun

The system uses a single Dockerfile with build arguments to support multiple Node.js ecosystems without creating separate image variants or duplicating layers.

### Build Arguments and CI Integration

The [`.github/workflows/build-docker.yml`](https://github.com/labnow-ai/lab-foundation/blob/main/.github/workflows/build-docker.yml) pipeline passes `ARG_PROFILE_NODEJS` to the `build_image` function defined in [`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh). Valid values are `npm`, `pnpm`, or `bun`. For example, the bun job explicitly sets `--build-arg "ARG_PROFILE_NODEJS=bun"`, which triggers `setup_node_bun` during the build process.

```yaml

# .github/workflows/build-docker.yml (excerpt)

- name: bun
  runs-on: ubuntu-latest
  steps:
    - run: source ./tool.sh && \
           build_image bun latest docker_core/Dockerfile \
           --build-arg "ARG_PROFILE_NODEJS=bun" && \
           push_image

```

This design allows the same `docker_core/Dockerfile` to serve three different Node.js ecosystems without duplicating layers or maintaining separate Dockerfiles for each package manager.

### Manual Installation in Running Containers

For debugging or custom builds, you can invoke the setup helpers directly inside a running container:

```bash

# Inside a LabNow AI container

source /opt/utils/script-setup.sh

# Install pnpm

setup_node_pnpm
pnpm --version

```

```bash

# Inside a LabNow AI container

source /opt/utils/script-setup.sh

# Install bun

setup_node_bun
bun -v

```

## Practical Implementation Examples

You can extend the existing patterns to build application-specific images or custom CI jobs that leverage these package managers.

### Adding Custom CI Jobs for pnpm

To build a dedicated pnpm image, extend [`.github/workflows/build-docker.yml`](https://github.com/labnow-ai/lab-foundation/blob/main/.github/workflows/build-docker.yml):

```yaml

# Add a new job to .github/workflows/build-docker.yml

build-pnpm:
  name: 'pnpm'
  runs-on: ubuntu-latest
  steps:
    - name: Build image with pnpm
      run: |
        source ./tool.sh
        build_image pnpm latest docker_core/Dockerfile \
          --build-arg "ARG_PROFILE_NODEJS=pnpm"
        push_image

```

### Multi-Stage Dockerfiles with Package Managers

When building Node.js applications, use the setup helpers in your Dockerfile to ensure the correct package manager is available:

```dockerfile
FROM labnow/docker-atom:latest AS builder
ARG ARG_PROFILE_NODEJS=pnpm   # can be pnpm or bun

ARG NODE_ENV=production

# Run the helper that installs the requested Node.js package manager

RUN source /opt/utils/script-setup.sh && \
    if [ "$ARG_PROFILE_NODEJS" = "pnpm" ]; then \
      setup_node_pnpm; \
    elif [ "$ARG_PROFILE_NODEJS" = "bun" ]; then \
      setup_node_bun; \
    fi

WORKDIR /app
COPY package.json pnpm-lock.yaml* ./
RUN pnpm install --prod   # or `bun install` if ARG_PROFILE_NODEJS=bun

```

## Summary

- **LabNow AI images** use a modular setup system located in [`docker_atom/work/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/docker_atom/work/script-setup.sh) to install Node.js tooling dynamically.
- **`setup_node_pnpm`** and **`setup_node_bun`** fetch the latest releases from GitHub and configure system PATHs during the build process.
- The **`ARG_PROFILE_NODEJS`** build argument controls which package manager gets installed, enabling a single Dockerfile to support npm, pnpm, and bun without duplication.
- The **[`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh)** wrapper and [`.github/workflows/build-docker.yml`](https://github.com/labnow-ai/lab-foundation/blob/main/.github/workflows/build-docker.yml) demonstrate how to trigger these installations in CI pipelines using the `build_image` function.
- Both pnpm and bun installations include automatic version verification that appears in build logs, ensuring reproducibility and easy debugging.

## Frequently Asked Questions

### How does LabNow AI determine which Node.js package manager to install?

The system checks the `ARG_PROFILE_NODEJS` build argument passed during the Docker build. When set to `pnpm` or `bun`, the `build_image` function in [`tool.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/tool.sh) sources [`/opt/utils/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main//opt/utils/script-setup.sh) and invokes `setup_node_pnpm` or `setup_node_bun` respectively. If the argument is omitted or set to another value, the image defaults to standard npm.

### Where are pnpm and bun binaries installed in LabNow AI images?

According to the source code in [`docker_atom/work/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/docker_atom/work/script-setup.sh), pnpm installs to `/usr/local/bin/pnpm` with `PNPM_HOME` added to the system PATH, while bun unpacks to `/opt/bun` and creates a symlink at `/usr/bin/bun`. Both locations are globally accessible within the container environment.

### Can I install both pnpm and bun in the same image?

Yes, though the standard CI jobs configure one package manager per image. You can manually source [`/opt/utils/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main//opt/utils/script-setup.sh) in a Dockerfile or running container and execute both `setup_node_pnpm` and `setup_node_bun` to install both tools side-by-side for projects that require multiple package managers.

### Does LabNow AI pin specific versions of pnpm or bun?

No, both `setup_node_pnpm` and `setup_node_bun` fetch the latest release from GitHub at build time. This ensures images always use current stable versions without manual intervention. If you require version pinning for reproducibility, you must modify the helper functions in [`docker_atom/work/script-setup.sh`](https://github.com/labnow-ai/lab-foundation/blob/main/docker_atom/work/script-setup.sh) to accept and use specific version parameters.