F006: Docker Deployment Support
| Field | Value |
|---|---|
| Feature ID | F006 |
| Status | Implemented |
| Priority | P2 |
| Depends On | F001 (Server Infrastructure) |
| Blocks | None |
| Decision | 944b8647 |
Summary
Section titled “Summary”Add Docker support for running the CSTP server as a containerized service, including Dockerfile, docker-compose.yml, and example environment configuration.
- Production-ready Dockerfile with multi-stage build
- docker-compose.yml for local development
- Example environment file with all required variables
- Health check integration
- Documentation for deployment
Non-Goals
Section titled “Non-Goals”- Kubernetes manifests (future)
- Helm charts (future)
- CI/CD pipeline integration (separate task)
Implementation Plan
Section titled “Implementation Plan”Phase 1: Core Docker Files
Section titled “Phase 1: Core Docker Files”1.1 Dockerfile
Section titled “1.1 Dockerfile”# syntax=docker/dockerfile:1FROM python:3.11-slim AS base
# Set environment variablesENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PIP_NO_CACHE_DIR=1 \ PIP_DISABLE_PIP_VERSION_CHECK=1
WORKDIR /app
# Install system dependenciesRUN apt-get update && apt-get install -y --no-install-recommends \ curl \ && rm -rf /var/lib/apt/lists/*
# --- Builder stage ---FROM base AS builder
# Install uv for fast dependency resolutionRUN pip install uv
# Copy dependency filesCOPY pyproject.toml ./
# Install dependenciesRUN uv pip install --system -e ".[a2a]"
# --- Runtime stage ---FROM base AS runtime
# Copy installed packages from builderCOPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packagesCOPY --from=builder /usr/local/bin /usr/local/bin
# Copy application codeCOPY . .
# Create non-root userRUN useradd --create-home --shell /bin/bash appuser && \ chown -R appuser:appuser /appUSER appuser
# Expose portEXPOSE 8100
# Health checkHEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8100/health || exit 1
# Default commandCMD ["python", "-m", "a2a.server", "--host", "0.0.0.0", "--port", "8100"]1.2 docker-compose.yml
Section titled “1.2 docker-compose.yml”version: "3.8"
services: cstp-server: build: context: . dockerfile: Dockerfile container_name: cstp-server ports: - "8100:8100" env_file: - .env environment: - CHROMA_URL=http://chromadb:8000 volumes: - ./config:/app/config:ro - ./guardrails:/app/guardrails:ro depends_on: chromadb: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8100/health"] interval: 30s timeout: 10s retries: 3 restart: unless-stopped
chromadb: image: chromadb/chroma:latest container_name: chromadb ports: - "8000:8000" volumes: - chroma_data:/chroma/chroma environment: - ANONYMIZED_TELEMETRY=false healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/heartbeat"] interval: 30s timeout: 10s retries: 3 restart: unless-stopped
volumes: chroma_data:1.3 .env.example
Section titled “1.3 .env.example”# =============================================================================# CSTP Server Configuration# =============================================================================# Copy this file to .env and fill in the values
# --- Required ---
# Gemini API key for embeddings (text-embedding-004)GEMINI_API_KEY=your_gemini_api_key_here
# --- Server Configuration ---
# Server bind address (default: 0.0.0.0)CSTP_HOST=0.0.0.0
# Server port (default: 8100)CSTP_PORT=8100
# --- ChromaDB Configuration ---
# ChromaDB URL (default: http://chromadb:8000)CHROMA_URL=http://chromadb:8000
# ChromaDB auth token (optional)# CHROMA_TOKEN=
# --- Authentication ---
# Comma-separated list of agent:token pairs for authentication# Format: agent1:token1,agent2:token2CSTP_AUTH_TOKENS=emerson:your_secret_token_here
# --- Guardrails Configuration ---
# Colon-separated paths to guardrail directories (optional)# GUARDRAILS_PATHS=/app/guardrails:/custom/guardrails
# --- Logging ---
# Log level (DEBUG, INFO, WARNING, ERROR)LOG_LEVEL=INFO
# --- Optional: Agent Card ---
# Agent name for discoveryCSTP_AGENT_NAME=cognition-engines
# Agent descriptionCSTP_AGENT_DESCRIPTION=Decision Intelligence Service
# Agent URL (for agent card)CSTP_AGENT_URL=http://localhost:8100Phase 2: Configuration Updates
Section titled “Phase 2: Configuration Updates”2.1 Update config.py to read from environment
Section titled “2.1 Update config.py to read from environment”# Support environment variable overridesimport os
def from_env() -> Config: """Create config from environment variables.""" return Config( server=ServerConfig( host=os.getenv("CSTP_HOST", "0.0.0.0"), port=int(os.getenv("CSTP_PORT", "8100")), ), agent=AgentConfig( name=os.getenv("CSTP_AGENT_NAME", "cognition-engines"), description=os.getenv("CSTP_AGENT_DESCRIPTION", "Decision Intelligence"), version="0.7.0", url=os.getenv("CSTP_AGENT_URL", "http://localhost:8100"), ), auth=AuthConfig( enabled=True, tokens=_parse_auth_tokens(os.getenv("CSTP_AUTH_TOKENS", "")), ), )
def _parse_auth_tokens(tokens_str: str) -> list[AuthToken]: """Parse CSTP_AUTH_TOKENS env var.""" tokens = [] for pair in tokens_str.split(","): if ":" in pair: agent, token = pair.split(":", 1) tokens.append(AuthToken(agent=agent.strip(), token=token.strip())) return tokens2.2 Update server.py entrypoint
Section titled “2.2 Update server.py entrypoint”# Add CLI support for Dockerif __name__ == "__main__": import argparse
parser = argparse.ArgumentParser(description="CSTP Server") parser.add_argument("--host", default=os.getenv("CSTP_HOST", "0.0.0.0")) parser.add_argument("--port", type=int, default=int(os.getenv("CSTP_PORT", "8100"))) parser.add_argument("--config", help="Path to config YAML (overrides env)")
args = parser.parse_args() run_server(host=args.host, port=args.port, config_path=args.config)Phase 3: Documentation
Section titled “Phase 3: Documentation”3.1 Update README.md
Section titled “3.1 Update README.md”Add “Docker Deployment” section:
- Quick start with docker-compose
- Environment variable reference
- Production deployment tips
- Health check endpoints
3.2 Create docs/DOCKER.md
Section titled “3.2 Create docs/DOCKER.md”Detailed Docker deployment guide:
- Building the image
- Running with docker-compose
- Running standalone
- Connecting to external ChromaDB
- Security considerations
- Monitoring and logging
Files to Create/Modify
Section titled “Files to Create/Modify”| File | Action | Description |
|---|---|---|
Dockerfile |
Create | Multi-stage production build |
docker-compose.yml |
Create | Local dev with ChromaDB |
.env.example |
Create | Example environment file |
.dockerignore |
Create | Exclude unnecessary files |
a2a/config.py |
Modify | Add env var support |
a2a/server.py |
Modify | Add CLI entrypoint |
README.md |
Modify | Add Docker quick start |
docs/DOCKER.md |
Create | Full deployment guide |
Environment Variables Reference
Section titled “Environment Variables Reference”| Variable | Required | Default | Description |
|---|---|---|---|
GEMINI_API_KEY |
✅ | - | Gemini API key for embeddings |
CSTP_HOST |
❌ | 0.0.0.0 |
Server bind address |
CSTP_PORT |
❌ | 8100 |
Server port |
CHROMA_URL |
❌ | http://chromadb:8000 |
ChromaDB endpoint |
CHROMA_TOKEN |
❌ | - | ChromaDB auth token |
CSTP_AUTH_TOKENS |
✅ | - | Agent authentication tokens |
GUARDRAILS_PATHS |
❌ | - | Custom guardrail directories |
LOG_LEVEL |
❌ | INFO |
Logging verbosity |
CSTP_AGENT_NAME |
❌ | cognition-engines |
Agent card name |
CSTP_AGENT_DESCRIPTION |
❌ | - | Agent card description |
CSTP_AGENT_URL |
❌ | - | Agent card URL |
Acceptance Criteria
Section titled “Acceptance Criteria”docker build .succeedsdocker-compose upstarts server + ChromaDB- Health check passes at
/health - Authentication works with env-configured tokens
- Guardrails load from mounted volume
- Queries work against ChromaDB
- Graceful shutdown on SIGTERM
Estimated Effort
Section titled “Estimated Effort”- Phase 1 (Docker files): 1-2 hours
- Phase 2 (Config updates): 1 hour
- Phase 3 (Documentation): 1 hour
Total: ~4 hours