Skip to content

Repository files navigation

dock.ai

dock.ai logo

What it is and why

dock.ai builds a Docker image from an existing base image and adds selected AI-assisted development tools for the normal user inside the container.

The goal is to keep the base image separate from the AI tooling. You start with a base image that already contains your development environment, and dock.ai creates a derived image that adds a Node.js toolchain and any selected AI tools. The available optional tools include GitHub Copilot CLI, Codex CLI, Claude CLI, context-mode, context7-mcp, markitdown-mcp, and RTK.

This avoids installing the same tools by hand in every container and makes the resulting environment easier to reproduce.

Description

This repository contains these files:

  • Dockerfile: defines the derived image and runs the installation as root. User-owned commands are executed through gosu so their files are created under the selected user's HOME.
  • build-ai-image.sh: runs docker buildx build with the required build arguments and optional tool flags.
  • install-ai-tools.sh: prepares the shared Node.js runtime and then selects which tool-specific installers to run.
  • install-node-runtime.sh: installs or reuses Node.js, prepares Corepack and pnpm, disables npm and pnpm lifecycle scripts, and configures user-level global commands under ${HOME}/.local/bin.
  • The remaining install-*.sh files each own one AI tool. Download-based tools keep their official installer logic separate. The two pnpm-based tools share only the Node.js runtime prepared above. The context-mode installer also installs Bun under ${HOME}/.local/bin because context-mode uses it for faster JavaScript and TypeScript execution.
  • .pre-commit-config.yaml: configures standard checks, shell formatting with shfmt, and Conventional Commits validation.

Requirements

You need Docker with buildx available on the machine that builds the image.

The base image must contain the non-root user for whom the tools will be installed. The --tools-user option selects that account; its default value is dev.

By default, the resulting image also uses that account in its final Dockerfile USER instruction. Use --runtime-user when the image must instead start as a different existing account. The runtime user may be root, but the tools user must remain non-root.

Node.js 22.5 or newer, npm, Corepack, and pnpm are prepared for every resulting image. Optional tool flags only control the additional AI tools. If the base image already contains a compatible Node.js, dock.ai preserves it and checks that npm is also available. An older inherited Node.js causes a clear build error instead of being replaced silently, because replacing it could break software supplied by the base image.

dock.ai deliberately preserves the base image's WORKDIR, ENTRYPOINT, and CMD. It must explicitly set a final USER because the installation phase temporarily switches to root. Dockerfile does not provide a variable containing the previous USER, so --runtime-user provides that value when it differs from --tools-user.

When these users differ, tools installed under the tools user's home are not automatically placed in the runtime user's PATH, and the runtime user does not load the tools user's shell configuration. This is intentional. Use different accounts only when the base entrypoint later switches users, the tools will be used through docker exec --user, or another part of the image handles that separation.

Codex CLI is the only currently supported tool that requires bubblewrap. When --codex-cli is selected, install-codex-cli.sh installs bubblewrap and enables setuid mode for /usr/bin/bwrap so Codex can build its Linux sandbox inside dev containers. Other tool installers do not install bubblewrap unless they add their own requirement in the future.

When --context-mode-mcp is selected, dock.ai installs Bun with the official Bun installer and places it at ${HOME}/.local/bin/bun. Bun is not part of the shared Node.js runtime because no other dock.ai tool currently requires it. context-mode detects it automatically and uses it to run JavaScript and TypeScript workloads faster. The image also receives the unzip package required by Bun's Linux installer.

Shell startup files

The --rcfile option is interpreted inside the image as a path relative to the selected user's HOME. It is not a path on the host machine and it is not resolved by build-ai-image.sh.

The installers do not write their full PATH or environment setup directly into the selected shell rc file. They write small .rc fragments under ${HOME}/.ai_tools.d. The orchestrator creates a companion file by appending _ai to the rc file name. For example, if the selected rc file is ${HOME}/.bashrc, the orchestrator creates ${HOME}/.bashrc_ai.

The selected rc file must already exist inside the image. The installer fails if it is missing, and it also fails if the generated _ai companion file already exists.

That generated _ai file sources every *.rc fragment in ${HOME}/.ai_tools.d. Each tool fragment decides which variables and PATH entries it needs.

The selected rc file only receives one source line:

[ -f "${HOME}/.bashrc_ai" ] && . "${HOME}/.bashrc_ai"

This setup is loaded by the selected interactive shell. A generic base image does not automatically expand $HOME/.local/bin for a command that bypasses that shell, such as docker run IMAGE context-mode. In that case, use the absolute command path or start the command through the configured shell. Images generated by robotics_dockers already load $HOME/.env.rc in their user entrypoint, and that environment includes $HOME/.local/bin before executing the requested command.

Step by step

  1. Enter the project directory:

    cd dock.ai
  2. Build a derived image with the tools you want:

    ./build-ai-image.sh --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai <base_image> <target_image>
  3. Select the existing account that must receive the tools. For example, ubuntu:24.04 contains a non-root user named ubuntu:

    ./build-ai-image.sh --tools-user ubuntu --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai ubuntu:24.04 my-ai-image:latest

    If the resulting image must start as another user, specify it separately:

    ./build-ai-image.sh --tools-user ubuntu --runtime-user root ubuntu:24.04 my-ai-image:latest
  4. Run the resulting image:

    docker run --rm -it my-ai-image:latest
  5. Inside the container, run the checks that apply to the tools you selected:

    node --version
    pnpm --version
    codex --version
    claude --version
    rtk --version
    context-mode --version
    markitdown-mcp --help

Examples

Build an image with the Node.js toolchain and no optional AI tools:

./build-ai-image.sh my-base:latest my-base-ai:latest

Build an image with context-mode, context7-mcp, MarkItDown MCP, and RTK:

./build-ai-image.sh --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai my-base:latest my-base-ai:latest

Build an image with GitHub Copilot CLI as well:

./build-ai-image.sh --copilot-cli --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai my-base:latest my-base-ai:latest

Build an image with Codex CLI as well:

./build-ai-image.sh --codex-cli --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai my-base:latest my-base-ai:latest

Build an image with Claude CLI as well:

./build-ai-image.sh --claude-cli --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai my-base:latest my-base-ai:latest

Build an image and install the tools for the user named developer:

./build-ai-image.sh --tools-user developer --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai my-base:latest my-base-ai:latest

Pass an explicit rc file, relative to the selected user's HOME inside the image, if you want to state the startup file explicitly:

./build-ai-image.sh --tools-user developer --rcfile .bashrc --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai my-base:latest my-base-ai:latest

Use a different build context:

./build-ai-image.sh --tools-user developer --context-path /path/to/dock.ai --context-mode-mcp --context7-mcp --markitdown-mcp --rtk-ai my-base:latest my-base-ai:latest

Force a fresh installation when you intentionally want to refresh packages or remote installers that use latest:

./build-ai-image.sh --no-cache --tools-user developer my-base:latest my-base-ai:latest

Normal builds reuse BuildKit's cache and still use --pull for the base image. The wrapper also uses --load, so a successful single-platform build is available immediately to docker run on the build machine.

Verification

The fast tests replace the Docker command with a local recorder. They verify argument handling and the Dockerfile contract without downloading packages or building an image:

python3 -m unittest discover -s tests

Before committing changes, also run the shell and repository checks:

bash -n ./*.sh
shellcheck ./*.sh
pre-commit run --all-files

A real Docker build is still required after changing an upstream installer or its dependencies. Such a build performs network downloads and is intentionally not part of the fast test suite.

Tool configuration

When selected, Codex CLI, Claude CLI, RTK, and context-mode still need their own configuration files and usage instructions. dock.ai installs the context-mode binary but does not run context-mode upgrade or install agent-specific hooks during the image build. Configure context-mode later for the agent you actually use. MarkItDown MCP is installed as the portable markitdown-mcp command; configure each MCP client that should use it to launch that command. Read the upstream projects before deciding which files to mount and where they should live inside the container:

A practical way to run the resulting image is through a docker-compose.yml file that mounts configuration files from the host into the container. The host paths in this example use ${XDG_CONFIG_HOME} only as one possible layout; adapt them to your machine. The container paths show where the tools or editors would see those files when the default user is dev.

services:
  dock-ai:
    image: my-base-ai:latest
    working_dir: /home/dev/<workspace>
    volumes:
      - ${XDG_CONFIG_HOME}/codex:/home/dev/.codex
      - ${XDG_CONFIG_HOME}/claude:/home/dev/.claude
      - ${XDG_CONFIG_HOME}/rtk:/home/dev/.config/rtk
      - ${XDG_CONFIG_HOME}/copilot/hooks:/home/dev/.github/hooks
      - ${XDG_CONFIG_HOME}/copilot/copilot-instructions.md:/home/dev/.github/copilot-instructions.md
      - ${XDG_CONFIG_HOME}/vscode/mcp.json:/home/dev/<workspace>/.vscode/mcp.json

The example maps configuration files from known locations on the host into the locations expected inside the container. The exact container paths depend on the tools you use, the container user, and the workspace directory, so check the RTK and context-mode documentation before treating these mounts as final.

About

Docker image layer that adds AI development tools such as RTK, context-mode, context7-mcp, Bun, and pnpm to an existing base image.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages