Skip to content

Docker Deployment

Rina edited this page May 12, 2026 · 1 revision

Docker Deployment

Image

The official Docker image is published to GitHub Container Registry:

ghcr.io/aomkoyo/claude-tmux-discord

Tags

Tag Description
latest Latest push to main branch
v1.0.0 Specific version tag
v1.0 Minor version tag
main Branch tag
sha-abc1234 Commit SHA

Multi-Stage Build

The Dockerfile uses a two-stage build:

Stage 1: Builder (node:22-bookworm-slim)

  1. Installs pnpm via corepack
  2. Copies workspace files and installs dependencies
  3. Runs prisma generate to create the Prisma client
  4. Compiles TypeScript (tsc)
  5. Copies generated Prisma client from src/generated/ to dist/generated/

Stage 2: Runtime (node:22-bookworm-slim)

  1. Installs system dependencies: tmux, git, curl, tini, openssl
  2. Installs Claude Code globally: curl -fsSL https://claude.ai/install.sh | bash
  3. Copies built artifacts from builder stage
  4. Copies node_modules from builder (avoids pnpm workspace protocol conflicts)
  5. Runs as node user via tini (proper signal handling)

Docker Compose

Production (docker-compose.yml)

services:
  bot:
    image: ghcr.io/aomkoyo/claude-tmux-discord:latest
    # or build: .
    env_file: .env
    volumes:
      - ./workspace:/workspace         # Per-channel workspaces
      - ./data:/data                    # SQLite database
      - ${HOME}/.claude:/home/node/.claude  # Claude auth (read-write)
    restart: unless-stopped

Development (docker-compose.dev.yml)

services:
  bot:
    build: .
    env_file: .env
    environment:
      LOG_LEVEL: debug
    volumes:
      - ./workspace:/workspace
      - ./data:/data
      - ${HOME}/.claude:/home/node/.claude
      - ./src:/app/src                  # Source mount for hot-reload
      - ./cli/src:/app/cli/src
      - ./prisma:/app/prisma
    command: pnpm dev                   # tsx watch
    restart: unless-stopped

Claude Authentication

Option A: Mount Host Config (Recommended)

If you've already logged into Claude Code on the host:

volumes:
  - ${HOME}/.claude:/home/node/.claude

This shares your existing Claude session with the container. The volume is read-write so Claude can refresh its auth tokens.

Option B: Login Inside Container

docker compose exec bot claude login

Follow the browser-based authentication flow. The session is persisted in the mounted volume.

Volumes

Mount Purpose Required
./workspace:/workspace Per-channel Claude workspaces Yes
./data:/data SQLite database file Yes
~/.claude:/home/node/.claude Claude Code auth session Yes

CI/CD

The GitHub Actions workflow (.github/workflows/docker-publish.yml) automatically builds and pushes to GHCR on:

  • Push to main branch
  • Version tags (v*.*.*)

It uses docker/metadata-action for tag generation and docker/build-push-action for multi-platform builds.

Health Check

The container doesn't expose HTTP ports. To check health:

docker compose exec bot tmux list-sessions    # list active Claude sessions
docker compose logs bot --tail 50             # check recent logs

Troubleshooting Docker

Issue Solution
Claude auth fails Run docker compose exec bot claude login
Permission denied on volumes Ensure ./workspace and ./data are owned by UID 1000 (node user)
tmux not found Rebuild the image — docker compose build --no-cache
Prisma migration error Check ./data directory permissions, ensure SQLite file is writable
discord-send can't find token The bot injects env vars via exportEnvToSession() — check logs for errors

Clone this wiki locally