Docker Guide - Code Graph Knowledge System

Docker Deployment Guide

Comprehensive guide for deploying Code Graph Knowledge System using Docker and Docker Compose.

Overview

The system provides three Docker images: - royisme/codebase-rag:minimal - Code Graph only (smallest) - royisme/codebase-rag:standard - Code Graph + Memory - royisme/codebase-rag:full - All features (largest)

Two-Port Architecture

The system uses a two-port architecture for clear separation of concerns:

  • Port 8000 (PRIMARY): MCP SSE Service - AI-to-application communication
  • Port 8080 (SECONDARY): Web UI + REST API - Status monitoring and management

This design prioritizes MCP as the core service, with the Web UI serving as a secondary interface for monitoring and administration.

Docker Compose Files

Location

  • docker-compose.yml - Default (points to minimal)
  • docker/docker-compose.minimal.yml - Minimal mode
  • docker/docker-compose.standard.yml - Standard mode
  • docker/docker-compose.full.yml - Full mode with optional Ollama

Common Structure

All compose files include:

services:
  neo4j:
    image: neo4j:5-enterprise  # or neo4j:5-community
    environment:
      - NEO4J_AUTH=neo4j/password
      - NEO4J_PLUGINS=["apoc"]
    volumes:
      - neo4j-data:/data
    ports:
      - "7474:7474"  # HTTP
      - "7687:7687"  # Bolt

  mcp:
    image: royisme/codebase-rag:MODE
    ports:
      - "${MCP_PORT:-8000}:8000"      # MCP SSE Service (PRIMARY)
      - "${WEB_UI_PORT:-8080}:8080"   # Web UI + REST API (SECONDARY)
    environment:
      - NEO4J_URI=bolt://neo4j:7687
      - DEPLOYMENT_MODE=MODE
      - MCP_PORT=8000        # MCP SSE Service
      - WEB_UI_PORT=8080     # Web UI + REST API
    volumes:
      - ./repos:/repos
      - ./data:/data
    depends_on:
      - neo4j

Accessing Services:

# MCP SSE endpoint (for Claude Desktop, Cline, etc.)
http://localhost:8000/sse

# Web UI (status monitoring)
http://localhost:8080/

# REST API
http://localhost:8080/api/v1/

Building Custom Images

Prerequisites

Frontend Build (Required before Docker build):

# Install bun (>= 1.3.1)
curl -fsSL https://bun.sh/install | bash

# Build frontend
./scripts/build-frontend.sh

This pre-builds the React frontend and generates static files in frontend/dist/, which are then copied into the Docker image. The production image does not include Node.js, npm, or any frontend build tools (~405MB savings).

Build from Source

# Clone repository
git clone https://github.com/royisme/codebase-rag.git
cd codebase-rag

# Build frontend first (REQUIRED)
./scripts/build-frontend.sh

# Build minimal
docker build -f docker/Dockerfile.minimal -t my-codebase-rag:minimal .

# Build standard
docker build -f docker/Dockerfile.standard -t my-codebase-rag:standard .

# Build full
docker build -f docker/Dockerfile.full -t my-codebase-rag:full .

Dockerfile Optimizations: - Uses ghcr.io/astral-sh/uv:python3.13-bookworm-slim base image (uv pre-installed) - BuildKit cache mounts for faster rebuilds - Pre-compiled frontend (no Node.js in production image) - Minimal Python dependencies (373 packages, 0 CUDA packages)

Build with Buildx (Multi-Platform)

# Create builder
docker buildx create --name mybuilder --use

# Build for multiple platforms
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -f docker/Dockerfile.minimal \
  -t my-codebase-rag:minimal \
  --push \
  .

Volume Management

Important Volumes

1. Neo4j Data (neo4j-data)

volumes:
  neo4j-data:
    driver: local

Contains all graph database data. Must be backed up regularly.

2. Repository Mount (./repos:/repos)

volumes:
  - ./repos:/repos:ro  # Read-only recommended

Mount local repositories for ingestion.

3. Application Data (./data:/data)

Temporary files, logs, and processing data.

Backup Volumes

# Backup Neo4j data
docker run --rm \
  -v codebase-rag_neo4j-data:/data \
  -v $(pwd)/backup:/backup \
  alpine \
  tar czf /backup/neo4j-backup-$(date +%Y%m%d).tar.gz /data

# Restore from backup
docker run --rm \
  -v codebase-rag_neo4j-data:/data \
  -v $(pwd)/backup:/backup \
  alpine \
  tar xzf /backup/neo4j-backup-20241106.tar.gz -C /

Network Configuration

Default Network

networks:
  default:
    name: codebase-rag-network

Custom Network

networks:
  codebase-rag:
    driver: bridge
    ipam:
      config:
        - subnet: 172.28.0.0/16

services:
  neo4j:
    networks:
      codebase-rag:
        ipv4_address: 172.28.0.10

External Services

Connect to external Ollama:

services:
  mcp:
    environment:
      - OLLAMA_BASE_URL=http://host.docker.internal:11434
    extra_hosts:
      - "host.docker.internal:host-gateway"

Environment Variables

Port Configuration

# Two-Port Architecture (NEW)
MCP_PORT=8000          # MCP SSE Service (PRIMARY)
WEB_UI_PORT=8080       # Web UI + REST API (SECONDARY)

# Legacy (deprecated, but maintained for backward compatibility)
PORT=8000

Custom Port Example:

# Use custom ports
MCP_PORT=9000 WEB_UI_PORT=9001 docker-compose up -d

# Access:
# - MCP SSE: http://localhost:9000/sse
# - Web UI:  http://localhost:9001/

Core Variables

# Neo4j Connection
NEO4J_URI=bolt://neo4j:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=<secure_password>
NEO4J_DATABASE=neo4j

# Deployment Mode
DEPLOYMENT_MODE=minimal|standard|full
ENABLE_KNOWLEDGE_RAG=true|false
ENABLE_AUTO_EXTRACTION=true|false

LLM Configuration

# Provider Selection
LLM_PROVIDER=ollama|openai|gemini|openrouter
EMBEDDING_PROVIDER=ollama|openai|gemini|huggingface

# Ollama
OLLAMA_BASE_URL=http://host.docker.internal:11434
OLLAMA_MODEL=llama3.2
OLLAMA_EMBEDDING_MODEL=nomic-embed-text

# OpenAI
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o
OPENAI_EMBEDDING_MODEL=text-embedding-3-small

# Gemini
GOOGLE_API_KEY=AIza...
GEMINI_MODEL=gemini-1.5-flash
GEMINI_EMBEDDING_MODEL=models/embedding-001

Performance Tuning

# Timeouts (seconds)
CONNECTION_TIMEOUT=30
OPERATION_TIMEOUT=300
LARGE_DOCUMENT_TIMEOUT=600

# Neo4j Memory
NEO4J_server_memory_heap_initial__size=2G
NEO4J_server_memory_heap_max__size=4G
NEO4J_server_memory_pagecache_size=2G

Docker Profiles

Use profiles to optionally include services:

services:
  ollama:
    profiles:
      - with-ollama
    image: ollama/ollama:latest
# Start without Ollama
docker-compose up -d

# Start with Ollama
docker-compose --profile with-ollama up -d

Health Checks

All images include health checks on the Web UI port (8080) where the REST API lives:

services:
  mcp:
    healthcheck:
      # Note: Health check uses Web UI port, not MCP port
      test: ["CMD", "curl", "-f", "http://localhost:8080/api/v1/health"]
      interval: 30s
      timeout: 10s
      start_period: 40s
      retries: 3

Check health:

# View health status
docker ps

# Check specific container
docker inspect --format='{{.State.Health.Status}}' codebase-rag-mcp

# View health logs
docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' codebase-rag-mcp

# Manual health check
curl http://localhost:8080/api/v1/health

# Test MCP SSE endpoint
curl http://localhost:8000/sse

Resource Limits

Memory Limits

services:
  mcp:
    deploy:
      resources:
        limits:
          memory: 4G
        reservations:
          memory: 2G

CPU Limits

services:
  mcp:
    deploy:
      resources:
        limits:
          cpus: '2.0'
        reservations:
          cpus: '1.0'

Logging

Configure Logging Driver

services:
  mcp:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

View Logs

# Follow logs
docker-compose logs -f mcp

# Last 100 lines
docker-compose logs --tail=100 mcp

# Since timestamp
docker-compose logs --since 2024-11-06T10:00:00 mcp

Multi-Stage Deployment

Development

# docker-compose.dev.yml
services:
  mcp:
    build:
      context: .
      dockerfile: docker/Dockerfile.minimal
    volumes:
      - .:/app  # Mount source code
    environment:
      - DEBUG=true

Production

# docker-compose.prod.yml
services:
  mcp:
    image: royisme/codebase-rag:minimal
    restart: unless-stopped
    logging:
      driver: "syslog"
    deploy:
      resources:
        limits:
          memory: 4G

Security Best Practices

1. Use Secrets

services:
  mcp:
    secrets:
      - neo4j_password
      - openai_api_key

secrets:
  neo4j_password:
    file: ./secrets/neo4j_password.txt
  openai_api_key:
    file: ./secrets/openai_api_key.txt

2. Non-Root User

All images run as non-root user appuser (UID 1000).

3. Read-Only Filesystem

services:
  mcp:
    read_only: true
    tmpfs:
      - /tmp
      - /app/temp

4. Network Isolation

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # No external access

services:
  mcp:
    networks:
      - frontend
  neo4j:
    networks:
      - backend

Updating Images

Pull Latest

# Pull latest image
docker pull royisme/codebase-rag:minimal

# Recreate containers
docker-compose up -d --force-recreate mcp

Zero-Downtime Update

# Scale up new version
docker-compose up -d --scale mcp=2 --no-recreate

# Remove old container
docker stop codebase-rag-mcp-1
docker rm codebase-rag-mcp-1

# Scale back to 1
docker-compose up -d --scale mcp=1

Troubleshooting

Container Won't Start

# Check logs
docker logs codebase-rag-mcp

# Check health
docker inspect codebase-rag-mcp

# Try recreating
docker-compose down
docker-compose up -d

Network Issues

# Test connectivity
docker exec -it codebase-rag-mcp ping neo4j

# Check network
docker network inspect codebase-rag-network

# Recreate network
docker-compose down
docker network prune
docker-compose up -d

Performance Issues

# Check resource usage
docker stats

# Check Neo4j performance
docker exec -it codebase-rag-neo4j cypher-shell -u neo4j -p password
# Run: CALL dbms.listQueries();

# Increase resources in docker-compose.yml

Advanced Patterns

Using Docker Swarm

# Initialize swarm
docker swarm init

# Deploy stack
docker stack deploy -c docker-compose.yml codebase-rag

# Scale service
docker service scale codebase-rag_mcp=3

Using Kubernetes

See separate Kubernetes deployment guide (coming soon).

Next Steps