Comprehensive design for Docker containerization including: - Single monolithic container approach for dev/testing - docker-compose.yml with environment variable injection - Sequential startup via entrypoint.sh script - GitHub Actions workflow for automated image builds on release tags - Documentation strategy and implementation checklist
11 KiB
Docker Deployment and CI/CD Design
Date: 2025-10-30 Status: Approved Target: Development/local testing environment
Overview
Package AI-Trader as a Docker container with docker-compose orchestration and automated image builds via GitHub Actions on release tags. Focus on simplicity and ease of use for researchers and developers.
Requirements
- Primary Use Case: Development and local testing
- Deployment Target: Single monolithic container (all MCP services + trading agent)
- Secrets Management: Environment variables (no mounted .env file)
- Data Strategy: Fetch price data on container startup
- Container Registry: GitHub Container Registry (ghcr.io)
- Trigger: Build images automatically on release tag push (
v*pattern)
Architecture
Components
- Dockerfile - Builds Python 3.10 image with all dependencies
- docker-compose.yml - Orchestrates container with volume mounts and environment config
- entrypoint.sh - Sequential startup script (data fetch → MCP services → trading agent)
- GitHub Actions Workflow - Automated image build and push on release tags
- .dockerignore - Excludes unnecessary files from image
- Documentation - Docker usage guide and examples
Execution Flow
Container Start
↓
entrypoint.sh
↓
1. Fetch/merge price data (get_daily_price.py → merge_jsonl.py)
↓
2. Start MCP services in background (start_mcp_services.py)
↓
3. Wait 3 seconds for service stabilization
↓
4. Run trading agent (main.py with config)
↓
Container Exit → Cleanup MCP services
Detailed Design
1. Dockerfile
Multi-stage build:
# Base stage
FROM python:3.10-slim as base
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Application stage
FROM base
WORKDIR /app
# Copy application code
COPY . .
# Create necessary directories
RUN mkdir -p data logs data/agent_data
# Make entrypoint executable
RUN chmod +x entrypoint.sh
# Expose MCP service ports
EXPOSE 8000 8001 8002 8003
# Set Python to run unbuffered
ENV PYTHONUNBUFFERED=1
# Use entrypoint script
ENTRYPOINT ["./entrypoint.sh"]
CMD ["configs/default_config.json"]
Key Features:
python:3.10-slimbase for smaller image size- Multi-stage for dependency caching
- Non-root user NOT included (dev/testing focus, can add later)
- Unbuffered Python output for real-time logs
- Default config path with override support
2. docker-compose.yml
version: '3.8'
services:
ai-trader:
build: .
container_name: ai-trader-app
volumes:
- ./data:/app/data
- ./logs:/app/logs
environment:
- OPENAI_API_BASE=${OPENAI_API_BASE}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- ALPHAADVANTAGE_API_KEY=${ALPHAADVANTAGE_API_KEY}
- JINA_API_KEY=${JINA_API_KEY}
- RUNTIME_ENV_PATH=/app/data/runtime_env.json
- MATH_HTTP_PORT=${MATH_HTTP_PORT:-8000}
- SEARCH_HTTP_PORT=${SEARCH_HTTP_PORT:-8001}
- TRADE_HTTP_PORT=${TRADE_HTTP_PORT:-8002}
- GETPRICE_HTTP_PORT=${GETPRICE_HTTP_PORT:-8003}
- AGENT_MAX_STEP=${AGENT_MAX_STEP:-30}
ports:
- "8000:8000"
- "8001:8001"
- "8002:8002"
- "8003:8003"
- "8888:8888" # Optional: web dashboard
restart: unless-stopped
Key Features:
- Volume mounts for data/logs persistence
- Environment variables interpolated from
.envfile (Docker Compose reads automatically) - No
.envfile mounted into container (cleaner separation) - Default port values with override support
- Restart policy for recovery
3. entrypoint.sh
#!/bin/bash
set -e # Exit on any error
echo "🚀 Starting AI-Trader..."
# Step 1: Data preparation
echo "📊 Fetching and merging price data..."
cd /app/data
python get_daily_price.py
python merge_jsonl.py
cd /app
# Step 2: Start MCP services in background
echo "🔧 Starting MCP services..."
cd /app/agent_tools
python start_mcp_services.py &
MCP_PID=$!
cd /app
# Step 3: Wait for services to initialize
echo "⏳ Waiting for MCP services to start..."
sleep 3
# Step 4: Run trading agent with config file
echo "🤖 Starting trading agent..."
CONFIG_FILE="${1:-configs/default_config.json}"
python main.py "$CONFIG_FILE"
# Cleanup on exit
trap "echo '🛑 Stopping MCP services...'; kill $MCP_PID 2>/dev/null" EXIT
Key Features:
- Sequential execution with clear logging
- MCP services run in background with PID capture
- Trap ensures cleanup on container exit
- Config file path as argument (defaults to
configs/default_config.json) - Fail-fast with
set -e
4. GitHub Actions Workflow
File: .github/workflows/docker-release.yml
name: Build and Push Docker Image
on:
push:
tags:
- 'v*' # Triggers on v1.0.0, v2.1.3, etc.
workflow_dispatch: # Manual trigger option
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract version from tag
id: meta
run: |
VERSION=${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/ai-trader:${{ steps.meta.outputs.version }}
ghcr.io/${{ github.repository_owner }}/ai-trader:latest
cache-from: type=gha
cache-to: type=gha,mode=max
Key Features:
- Triggers on
v*tags (e.g.,git tag v1.0.0 && git push origin v1.0.0) - Manual dispatch option for testing
- Uses
GITHUB_TOKEN(automatically provided, no secrets needed) - Builds with caching for faster builds
- Tags both version and
latest - Multi-platform support possible by adding
platforms: linux/amd64,linux/arm64
5. .dockerignore
# Version control
.git/
.gitignore
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
venv/
env/
ENV/
# IDE
.vscode/
.idea/
*.swp
*.swo
# Environment and secrets
.env
.env.*
!.env.example
# Data files (fetched at runtime)
data/*.json
data/agent_data/
data/merged.jsonl
# Logs
logs/
*.log
# Runtime state
runtime_env.json
# Documentation (not needed in image)
*.md
docs/
!README.md
# CI/CD
.github/
Purpose:
- Reduces image size
- Keeps secrets out of image
- Excludes generated files
- Keeps only necessary source code and scripts
Documentation Updates
New File: docs/DOCKER.md
Create comprehensive Docker usage guide including:
-
Quick Start
cp .env.example .env # Edit .env with your API keys docker-compose up -
Configuration
- Required environment variables
- Optional configuration overrides
- Custom config file usage
-
Usage Examples
# Run with default config docker-compose up # Run with custom config docker-compose run ai-trader configs/my_config.json # View logs docker-compose logs -f # Stop and clean up docker-compose down -
Data Persistence
- How volume mounts work
- Where data is stored
- How to backup/restore
-
Troubleshooting
- MCP services not starting → Check logs, verify ports available
- Missing API keys → Check .env file
- Data fetch failures → API rate limits or invalid keys
- Permission issues → Volume mount permissions
-
Using Pre-built Images
docker pull ghcr.io/hkuds/ai-trader:latest docker run --env-file .env -v $(pwd)/data:/app/data ghcr.io/hkuds/ai-trader:latest
Update .env.example
Add/clarify Docker-specific variables:
# AI Model API Configuration
OPENAI_API_BASE=https://your-openai-proxy.com/v1
OPENAI_API_KEY=your_openai_key
# Data Source Configuration
ALPHAADVANTAGE_API_KEY=your_alpha_vantage_key
JINA_API_KEY=your_jina_api_key
# System Configuration (Docker defaults)
RUNTIME_ENV_PATH=/app/data/runtime_env.json
# MCP Service Ports
MATH_HTTP_PORT=8000
SEARCH_HTTP_PORT=8001
TRADE_HTTP_PORT=8002
GETPRICE_HTTP_PORT=8003
# Agent Configuration
AGENT_MAX_STEP=30
Update Main README.md
Add Docker section after "Quick Start":
## Docker Deployment
### Using Docker Compose (Recommended)
```bash
# Setup environment
cp .env.example .env
# Edit .env with your API keys
# Run with docker-compose
docker-compose up
Using Pre-built Images
# Pull latest image
docker pull ghcr.io/hkuds/ai-trader:latest
# Run container
docker run --env-file .env \
-v $(pwd)/data:/app/data \
-v $(pwd)/logs:/app/logs \
ghcr.io/hkuds/ai-trader:latest
See docs/DOCKER.md for detailed Docker usage guide.
## Release Process
### For Maintainers
1. **Prepare release:**
```bash
# Ensure main branch is ready
git checkout main
git pull origin main
-
Create and push tag:
git tag v1.0.0 git push origin v1.0.0 -
GitHub Actions automatically:
- Builds Docker image
- Tags with version and
latest - Pushes to
ghcr.io/hkuds/ai-trader
-
Verify build:
- Check Actions tab for build status
- Test pull:
docker pull ghcr.io/hkuds/ai-trader:v1.0.0
-
Optional: Create GitHub Release
- Add release notes
- Include Docker pull command
For Users
# Pull specific version
docker pull ghcr.io/hkuds/ai-trader:v1.0.0
# Or always get latest
docker pull ghcr.io/hkuds/ai-trader:latest
Implementation Checklist
- Create Dockerfile with multi-stage build
- Create docker-compose.yml with volume mounts and environment config
- Create entrypoint.sh with sequential startup logic
- Create .dockerignore to exclude unnecessary files
- Create .github/workflows/docker-release.yml for CI/CD
- Create docs/DOCKER.md with comprehensive usage guide
- Update .env.example with Docker-specific variables
- Update main README.md with Docker deployment section
- Test local build:
docker-compose build - Test local run:
docker-compose up - Test with custom config
- Verify data persistence across container restarts
- Test GitHub Actions workflow (create test tag)
- Verify image pushed to ghcr.io
- Test pulling and running pre-built image
- Update CLAUDE.md with Docker commands
Future Enhancements
Possible improvements for production use:
-
Multi-container Architecture
- Separate containers for each MCP service
- Better isolation and independent scaling
- More complex orchestration
-
Security Hardening
- Non-root user in container
- Docker secrets for production
- Read-only filesystem where possible
-
Monitoring
- Health checks for MCP services
- Prometheus metrics export
- Logging aggregation
-
Optimization
- Multi-platform builds (ARM64 support)
- Smaller base image (alpine)
- Layer caching optimization
-
Development Tools
- docker-compose.dev.yml with hot reload
- Debug container with additional tools
- Integration test container
These are deferred to keep initial implementation simple and focused on development/testing use cases.