Claude-skill-registry docker-development

Local Docker development workflow for the Orient. Use when asked to build Docker images, run containers locally, debug container issues, optimize builds, use docker-compose, or troubleshoot containerization problems. Covers per-package Dockerfiles, compose layering, build optimization, and local debugging.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/docker-development" ~/.claude/skills/majiayu000-claude-skill-registry-docker-development && rm -rf "$T"
manifest: skills/data/docker-development/SKILL.md
source content

Docker Development

Quick Reference

# Development mode (hot-reload, uses local code)
./run.sh dev              # Start dev environment
./run.sh dev stop         # Stop services
./run.sh dev logs         # View logs
./run.sh dev status       # Show service status

# Testing mode (full Docker stack)
./run.sh test             # Build and start containers
./run.sh test pull        # Use pre-built images
./run.sh test status      # Check health
./run.sh test stop        # Stop containers
./run.sh test clean       # Remove volumes (fresh start)

Instance Naming Conventions

ModeContainer NamesPorts
Dev (instance 0)
orienter-*-0
80, 9000, 9001
Test
orienter-*
80, 9000, 9001
Instance N
orienter-*-N
80+N*1000, etc.

Compose File Layering

# Base configuration
docker-compose.v2.yml           # Service definitions

# Environment overlays
docker-compose.local.yml        # Local builds
docker-compose.prod.yml         # Production images
docker-compose.staging.yml      # Staging config

# Usage
docker compose -f docker-compose.v2.yml -f docker-compose.local.yml up

Database: SQLite (File-Based)

The Orient uses SQLite for all database operations. No separate database container is needed.

Database location:

  • Dev mode:
    .dev-data/instance-N/orient.db
  • Docker:
    /app/data/orient.db
    (volume-mounted)

Environment variables:

DATABASE_TYPE=sqlite
SQLITE_DATABASE=/app/data/orient.db

Container Lifecycle

Starting Containers

# With build (slow, may hang on metadata)
docker compose --env-file ../.env -f docker-compose.v2.yml -f docker-compose.local.yml --profile slack up -d

# Without build (use existing images)
docker compose --env-file ../.env -f docker-compose.v2.yml -f docker-compose.local.yml --profile slack up -d --no-build

Stopping Containers

# Stop test stack
./run.sh test stop

# Stop specific containers (dev instance 0)
docker stop orienter-nginx-0 orienter-minio-0
docker rm orienter-nginx-0 orienter-minio-0

Viewing Logs

docker logs orienter-opencode --tail 100 -f    # Follow logs
docker logs orienter-bot-slack 2>&1 | tail -50 # Last 50 lines

Health Checks

./run.sh test status    # Quick health overview
docker ps               # Container status
docker inspect --format='{{.State.Health.Status}}' orienter-opencode

Common Issues

1. Port Conflicts

Symptom:

Bind for 0.0.0.0:9000 failed: port is already allocated

Fix: Stop conflicting containers:

# Find what's using the port
lsof -i :9000

# Stop dev containers before starting test
docker stop orienter-nginx-0 orienter-minio-0
docker rm orienter-nginx-0 orienter-minio-0

2. Build Hangs on Metadata Loading (macOS)

Symptom:

./run.sh test
hangs at "load metadata for docker.io/library/node:20-alpine"

Cause: Docker buildx slow to fetch from Docker Hub.

Workarounds:

# Option 1: Pre-pull images
docker pull node:20-alpine
docker pull node:20-slim

# Option 2: Use existing local images
docker compose ... up -d --no-build

# Option 3: Use ghcr.io images (requires auth)
./run.sh test pull

3. ECONNRESET During Tests

Symptom: E2E tests fail with

fetch failed
/
ECONNRESET

Cause: Container crashed or restarted during test run.

Debug:

# Check container status
docker ps -a | grep opencode

# Check if recently restarted
# Look for "Up X seconds" when tests ran for minutes

# View crash logs
docker logs orienter-opencode 2>&1 | tail -100

4. Container Won't Start

Debug steps:

# Check exit code
docker ps -a --filter "name=orienter-opencode"

# Check logs for errors
docker logs orienter-opencode 2>&1

# Check if image exists
docker images | grep docker-opencode

# Rebuild single service
docker compose ... build opencode

5. ghcr.io Authentication

Symptom:

./run.sh test pull
fails with 401 Unauthorized

Fix:

# Authenticate to GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

6. SQLite Database Issues

Symptom: Database not persisting or permission errors

Fix:

# Check volume mount
docker inspect orienter-dashboard | grep -A 5 Mounts

# Ensure data directory exists with correct permissions
mkdir -p .dev-data/instance-0
chmod 755 .dev-data/instance-0

# Verify database schema
sqlite3 .dev-data/instance-0/orient.db ".tables"

Switching Between Stacks

Always stop one stack before starting another:

# From dev to test
./run.sh dev stop
./run.sh test

# From test to dev
./run.sh test stop
./run.sh dev

Building Images

# Build all services
docker compose -f docker-compose.v2.yml -f docker-compose.local.yml build

# Build single service
docker compose -f docker-compose.v2.yml -f docker-compose.local.yml build dashboard

# Build with no cache
docker compose ... build --no-cache opencode

# Build with progress output
docker compose ... build dashboard --progress=plain

Environment Variables

Compose files use

--env-file ../.env
to load environment. Required vars:

  • MINIO_ROOT_USER
    ,
    MINIO_ROOT_PASSWORD
  • ANTHROPIC_API_KEY
  • DASHBOARD_JWT_SECRET
  • ORIENT_MASTER_KEY
  • SLACK_BOT_TOKEN
    ,
    SLACK_SIGNING_SECRET
    (for Slack profile)

Services Architecture

The Docker stack includes:

ServicePurposePort(s)
dashboardDashboard API + WhatsApp routes4098
opencodeOpenCode API4099
bot-slackSlack bot (profile-activated)-
minioObject storage9000, 9001
nginxReverse proxy80

Note: WhatsApp functionality is integrated into the Dashboard service (single port 4098).