Get the FREE Ultimate OpenClaw Setup Guide →

convert-to-docker

Use Caution
npx machina-cli add skill crypdick/pynchy/convert-to-docker --openclaw
Files (1)
SKILL.md
9.9 KB

Convert to Docker

This skill migrates NanoClaw from Apple Container (macOS-only) to Docker for cross-platform support (macOS and Linux).

What this changes:

  • Container runtime: Apple Container → Docker
  • Mount syntax: --mount type=bind,...,readonly-v path:path:ro
  • Startup check: container system statusdocker info
  • Build commands: container build/rundocker build/run

What stays the same:

  • Dockerfile (already Docker-compatible)
  • Agent runner code
  • Mount security/allowlist validation
  • All other functionality

Prerequisites

Verify Docker is installed before starting:

docker --version && docker info >/dev/null 2>&1 && echo "Docker ready" || echo "Install Docker first"

If Docker is not installed:

1. Update Container Runner

Edit src/container-runner.ts:

1a. Update module comment (around line 3)

// Before:
 * Spawns agent execution in Apple Container and handles IPC

// After:
 * Spawns agent execution in Docker container and handles IPC

1b. Update directory mount comment (around line 88)

// Before:
    // Apple Container only supports directory mounts, not file mounts

// After:
    // Docker bind mounts work with both files and directories

1c. Update env workaround comment (around line 120)

// Before:
  // Environment file directory (workaround for Apple Container -i env var bug)

// After:
  // Environment file directory (keeps credentials out of process listings)

1d. Update buildContainerArgs function

Replace the entire function with Docker mount syntax:

function buildContainerArgs(mounts: VolumeMount[]): string[] {
  const args: string[] = ['run', '-i', '--rm'];

  // Docker: -v with :ro suffix for readonly
  for (const mount of mounts) {
    if (mount.readonly) {
      args.push('-v', `${mount.hostPath}:${mount.containerPath}:ro`);
    } else {
      args.push('-v', `${mount.hostPath}:${mount.containerPath}`);
    }
  }

  args.push(CONTAINER_IMAGE);

  return args;
}

1e. Update spawn command (around line 204)

// Before:
    const container = spawn('container', containerArgs, {

// After:
    const container = spawn('docker', containerArgs, {

2. Update Startup Check

Edit src/index.ts:

2a. Replace the container system check function

Find ensureContainerSystemRunning() and replace entirely with:

function ensureDockerRunning(): void {
  try {
    execSync('docker info', { stdio: 'pipe', timeout: 10000 });
    logger.debug('Docker daemon is running');
  } catch {
    logger.error('Docker daemon is not running');
    console.error('\n╔════════════════════════════════════════════════════════════════╗');
    console.error('║  FATAL: Docker is not running                                  ║');
    console.error('║                                                                ║');
    console.error('║  Agents cannot run without Docker. To fix:                     ║');
    console.error('║  macOS: Start Docker Desktop                                   ║');
    console.error('║  Linux: sudo systemctl start docker                            ║');
    console.error('║                                                                ║');
    console.error('║  Install from: https://docker.com/products/docker-desktop      ║');
    console.error('╚════════════════════════════════════════════════════════════════╝\n');
    throw new Error('Docker is required but not running');
  }
}

2b. Update the function call in main()

// Before:
  ensureContainerSystemRunning();

// After:
  ensureDockerRunning();

3. Update Build Script

Edit container/build.sh:

3a. Update build command (around line 15-16)

# Before:
# Build with Apple Container
container build -t "${IMAGE_NAME}:${TAG}" .

# After:
# Build with Docker
docker build -t "${IMAGE_NAME}:${TAG}" .

3b. Update test command (around line 23)

# Before:
echo "  echo '{...}' | container run -i ${IMAGE_NAME}:${TAG}"

# After:
echo "  echo '{...}' | docker run -i ${IMAGE_NAME}:${TAG}"

4. Update Documentation

Update references in documentation files:

FileFindReplace
CLAUDE.md"Apple Container (Linux VMs)""Docker containers"
README.md"Apple containers""Docker containers"
README.md"Apple Container""Docker"
README.mdRequirements sectionUpdate to show Docker instead
docs/REQUIREMENTS.md"Apple Container""Docker"
docs/SPEC.md"APPLE CONTAINER""DOCKER CONTAINER"
docs/SPEC.mdAll Apple Container referencesDocker equivalents

Key README.md updates:

Requirements section:

## Requirements

- macOS or Linux
- Node.js 20+
- [Claude Code](https://claude.ai/download)
- [Docker](https://docker.com/products/docker-desktop)

FAQ - "Why Docker?":

**Why Docker?**

Docker provides cross-platform support (macOS and Linux), a large ecosystem, and mature tooling. Docker Desktop on macOS uses a lightweight Linux VM similar to other container solutions.

FAQ - "Can I run this on Linux?":

**Can I run this on Linux?**

Yes. NanoClaw uses Docker, which works on both macOS and Linux. Just install Docker and run `/setup`.

5. Update Skills

5a. Update .claude/skills/setup/SKILL.md

Replace Section 2 "Install Apple Container" with Docker installation:

## 2. Install Docker

Check if Docker is installed and running:

\`\`\`bash
docker --version && docker info >/dev/null 2>&1 && echo "Docker is running" || echo "Docker not running or not installed"
\`\`\`

If not installed or not running, tell the user:
> Docker is required for running agents in isolated environments.
>
> **macOS:**
> 1. Download Docker Desktop from https://docker.com/products/docker-desktop
> 2. Install and start Docker Desktop
> 3. Wait for the whale icon in the menu bar to stop animating
>
> **Linux:**
> \`\`\`bash
> curl -fsSL https://get.docker.com | sh
> sudo systemctl start docker
> sudo usermod -aG docker $USER  # Then log out and back in
> \`\`\`
>
> Let me know when you've completed these steps.

Wait for user confirmation, then verify:

\`\`\`bash
docker run --rm hello-world
\`\`\`

Update build verification:

Verify the build succeeded:

\`\`\`bash
docker images | grep nanoclaw-agent
echo '{}' | docker run -i --entrypoint /bin/echo nanoclaw-agent:latest "Container OK" || echo "Container build failed"
\`\`\`

Update troubleshooting section to reference Docker commands.

5b. Update .claude/skills/debug/SKILL.md

Replace all container commands with docker equivalents:

BeforeAfter
container rundocker run
container system statusdocker info
container builder prunedocker builder prune
container imagesdocker images
--mount type=bind,source=...,readonly-v ...:ro

Update the architecture diagram header:

Host (macOS/Linux)                    Container (Docker)

6. Build and Verify

After making all changes:

# Compile TypeScript
npm run build

# Build Docker image
./container/build.sh

# Verify image exists
docker images | grep nanoclaw-agent

7. Test the Migration

7a. Test basic container execution

echo '{}' | docker run -i --entrypoint /bin/echo nanoclaw-agent:latest "Container OK"

7b. Test readonly mounts

mkdir -p /tmp/test-ro && echo "test" > /tmp/test-ro/file.txt
docker run --rm --entrypoint /bin/bash -v /tmp/test-ro:/test:ro nanoclaw-agent:latest \
  -c "cat /test/file.txt && touch /test/new.txt 2>&1 || echo 'Write blocked (expected)'"
rm -rf /tmp/test-ro

Expected: Read succeeds, write fails with "Read-only file system".

7c. Test read-write mounts

mkdir -p /tmp/test-rw
docker run --rm --entrypoint /bin/bash -v /tmp/test-rw:/test nanoclaw-agent:latest \
  -c "echo 'test write' > /test/new.txt && cat /test/new.txt"
cat /tmp/test-rw/new.txt && rm -rf /tmp/test-rw

Expected: Both operations succeed.

7d. Full integration test

npm run dev
# Send @AssistantName hello via WhatsApp
# Verify response received

Troubleshooting

Docker not running:

  • macOS: Start Docker Desktop from Applications
  • Linux: sudo systemctl start docker
  • Verify: docker info

Permission denied on Docker socket (Linux):

sudo usermod -aG docker $USER
# Log out and back in

Image build fails:

# Clean rebuild
docker builder prune -af
./container/build.sh

Container can't write to mounted directories: Check directory permissions on the host. The container runs as uid 1000.

Summary of Changed Files

FileType of Change
src/container-runner.tsMount syntax, spawn command, comments
src/index.tsStartup check function
container/build.shBuild and run commands
CLAUDE.mdQuick context
README.mdRequirements, FAQ
docs/REQUIREMENTS.mdArchitecture references
docs/SPEC.mdArchitecture diagram, tech stack
.claude/skills/setup/SKILL.mdInstallation instructions
.claude/skills/debug/SKILL.mdDebug commands

Source

git clone https://github.com/crypdick/pynchy/blob/main/docs/_archive/old-nanoclaw-skills/convert-to-docker/SKILL.mdView on GitHub

Overview

Converts NanoClaw from Apple Container to Docker to enable cross-platform deployment and Linux support. It updates the container runtime, mount syntax, startup checks, and build/run commands while preserving Dockerfile compatibility and core functionality.

How This Skill Works

The migration replaces Apple Container usage with Docker across code paths, updating mounts from Apple-style binds to Docker -v binds with an optional :ro suffix, and switching startup and build/run logic to Docker. It also changes the startup check to verify Docker is running via docker info and updates the spawn command to invoke Docker instead of the Apple Container runtime.

When to Use It

  • You need Linux support or cross-platform deployment for NanoClaw.
  • You want to replace Apple Container with Docker in your development or CI/CD workflows.
  • You're migrating from Apple Container to Docker to simplify tooling and environment parity.
  • Your deployment environment standardizes on Docker for container runtimes.
  • You want to preserve existing Dockerfile while enabling Docker-based execution for NanoClaw.

Quick Start

  1. Step 1: Ensure Docker is installed and Docker daemon is running on your host.
  2. Step 2: Update your codebase according to the migration notes (switch container-runner, mounts, and startup checks to Docker).
  3. Step 3: Run and validate NanoClaw inside Docker, confirming mounts, commands, and agent behavior are correct.

Best Practices

  • Verify Docker is installed and accessible with docker --version and docker info before running migration steps.
  • Review changes in src/container-runner.ts and src/index.ts to ensure mount and spawn logic reflect Docker usage.
  • Test both file and directory mounts, using -v with :ro for readonly mounts as described in the migration notes.
  • Keep Dockerfile and core agent runner logic intact to minimize behavioral drift.
  • Document Docker prerequisites, startup checks, and migration steps for your team to follow.

Example Use Cases

  • Deploy NanoClaw agents on Linux servers by migrating from Apple Container to Docker for cross-platform compatibility.
  • In a multi-OS CI pipeline, replace Apple Container runs with Docker to standardize builds across macOS and Linux runners.
  • Migrate an existing macOS-only workflow to Docker for easier cross-platform distribution.
  • Set up a local Docker-based development environment for NanoClaw to mirror production behavior.
  • Use docker build/run in your deployment scripts to replace container build/run commands.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers