2025-08-11 08:02:09 -06:00
{% extends "docs/base.html" %}
{% block title %}Docker Deployment - Claude Code Project Tracker{% endblock %}
{% block doc_content %}
< div class = "row" >
< div class = "col-lg-8" >
< h1 class = "mb-4" >
< i class = "fab fa-docker text-primary me-2" > < / i >
Docker Deployment Guide
< / h1 >
< p class = "lead" >
Deploy Claude Code Project Tracker using Docker with Caddy reverse proxy for production environments.
< / p >
<!-- Prerequisites -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-check-circle me-2" > < / i > Prerequisites< / h2 >
< div class = "alert alert-info" >
< p class = "mb-2" > < strong > Required:< / strong > < / p >
< ul class = "mb-0" >
< li > Docker and Docker Compose installed< / li >
< li > Caddy with docker-proxy plugin< / li >
< li > External Caddy network configured< / li >
< li > Domain name (or local development domain)< / li >
< / ul >
< / div >
< / section >
<!-- Quick Start -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-rocket me-2" > < / i > Quick Start< / h2 >
< p > Follow these steps to get Claude Code Tracker running with Docker:< / p >
< div class = "card mb-3" >
< div class = "card-header bg-light" >
< h5 class = "mb-0" > 1. Clone and Configure< / h5 >
< / div >
< div class = "card-body" >
< pre > < code class = "language-bash" > # Clone the repository
2025-08-11 09:30:37 -06:00
git clone https://git.supported.systems/claude/claude-code-tracker.git claude-tracker
2025-08-11 08:02:09 -06:00
cd claude-tracker
# Copy environment template
cp .env.example .env< / code > < / pre >
< / div >
< / div >
< div class = "card mb-3" >
< div class = "card-header bg-light" >
< h5 class = "mb-0" > 2. Configure Environment< / h5 >
< / div >
< div class = "card-body" >
< p > Edit the < code > .env< / code > file with your settings:< / p >
< pre > < code class = "language-bash" > # Domain configuration
DOMAIN=claude.l.supported.systems
# Database settings
DATABASE_URL=sqlite+aiosqlite:////app/data/tracker.db
# Application settings
DEBUG=false
PYTHONPATH=/app< / code > < / pre >
< / div >
< / div >
< div class = "card mb-3" >
< div class = "card-header bg-light" >
< h5 class = "mb-0" > 3. Deploy with Docker Compose< / h5 >
< / div >
< div class = "card-body" >
< pre > < code class = "language-bash" > # Build and start the container
docker-compose up -d
# View logs
docker-compose logs -f
# Check status
docker-compose ps< / code > < / pre >
< / div >
< / div >
2025-08-11 09:30:37 -06:00
< div class = "card mb-3" >
< div class = "card-header bg-success text-white" >
< h5 class = "mb-0" > 4. Install Claude Code Hooks< / h5 >
< / div >
< div class = "card-body" >
< p > After deployment, install hooks on your development machine to enable automatic tracking:< / p >
< pre > < code class = "language-bash" > # Install hooks using the same domain from your .env file
export DOMAIN=claude.l.supported.systems
./setup-hooks< / code > < / pre >
< div class = "alert alert-info mt-3" >
< i class = "fas fa-info-circle me-1" > < / i >
< strong > Note:< / strong > Hooks are installed on your local development machine, not in the Docker container. This allows Claude Code to send data to your deployed tracker.
< / div >
< div class = "alert alert-success" >
< i class = "fas fa-check me-1" > < / i >
< strong > Complete Setup:< / strong > Your tracker is now deployed and ready to receive data from Claude Code!
< / div >
< / div >
< / div >
2025-08-11 08:02:09 -06:00
< / section >
<!-- Docker Configuration -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-cog me-2" > < / i > Docker Configuration< / h2 >
< h4 class = "mt-4" > Dockerfile< / h4 >
< p > The application uses a multi-stage Docker build with Python 3.12 and uv package manager:< / p >
< div class = "card mb-3" >
< div class = "card-body" >
< pre > < code class = "language-dockerfile" > # Multi-stage build with Python 3.12
FROM python:3.12-slim
# Install uv package manager
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv
# Application setup
WORKDIR /app
COPY . .
# Install dependencies and create virtual environment
RUN uv venv & & uv pip install -r requirements.txt
# Database initialization script
COPY init_db.py ./
# Startup script with database initialization
CMD ["./start.sh"]< / code > < / pre >
< / div >
< / div >
< h4 class = "mt-4" > docker-compose.yml< / h4 >
< p > The Docker Compose configuration includes Caddy integration:< / p >
< div class = "card mb-3" >
< div class = "card-body" >
< pre > < code class = "language-yaml" > services:
claude-tracker:
build:
context: .
dockerfile: Dockerfile
container_name: claude-tracker-api
restart: unless-stopped
environment:
- DATABASE_URL=sqlite+aiosqlite:////app/data/tracker.db
- DEBUG=true
- PYTHONPATH=/app
volumes:
- ./data:/app/data
- ./app/dashboard/static:/app/app/dashboard/static:ro
networks:
- caddy
labels:
# Caddy reverse proxy configuration
caddy: ${DOMAIN:-claude.l.supported.systems}
caddy.reverse_proxy: "{{upstreams 8000}}"
expose:
- 8000
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
networks:
caddy:
external: true
name: caddy< / code > < / pre >
< / div >
< / div >
< / section >
<!-- Caddy Integration -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-globe me-2" > < / i > Caddy Integration< / h2 >
< p > The application integrates with Caddy using docker-proxy labels for automatic SSL and reverse proxy configuration.< / p >
< div class = "card mb-3" >
< div class = "card-header bg-light" >
< h5 class = "mb-0" > Caddy Labels Explained< / h5 >
< / div >
< div class = "card-body" >
< ul >
< li > < code > caddy: ${DOMAIN}< / code > - Sets the domain for the service< / li >
< li > < code > caddy.reverse_proxy: "{{upstreams 8000}}"< / code > - Proxies to port 8000< / li >
< li > Automatic SSL certificate generation< / li >
< li > Health check integration< / li >
< li > Load balancing support< / li >
< / ul >
< / div >
< / div >
< / section >
<!-- Database & Persistence -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-database me-2" > < / i > Database & Persistence< / h2 >
< p > The application uses SQLite with proper volume mounting for data persistence:< / p >
< div class = "card mb-3" >
< div class = "card-header bg-light" >
< h5 class = "mb-0" > Volume Configuration< / h5 >
< / div >
< div class = "card-body" >
< ul >
< li > < code > ./data:/app/data< / code > - Database and file storage< / li >
< li > < code > ./app/dashboard/static:/app/app/dashboard/static:ro< / code > - Static assets (read-only)< / li >
< / ul >
< div class = "alert alert-warning mt-3" >
< i class = "fas fa-exclamation-triangle me-1" > < / i >
< strong > Important:< / strong > Ensure the < code > ./data< / code > directory exists and has proper permissions before starting the container.
< / div >
< / div >
< / div >
< / section >
<!-- Management Commands -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-terminal me-2" > < / i > Management Commands< / h2 >
< div class = "row" >
< div class = "col-md-6" >
< div class = "card h-100" >
< div class = "card-header" >
< h5 class = "mb-0" > Container Management< / h5 >
< / div >
< div class = "card-body" >
< pre > < code class = "language-bash" > # Start services
docker-compose up -d
# Stop services
docker-compose down
# Restart services
docker-compose restart
# View logs
docker-compose logs -f
# Check status
docker-compose ps< / code > < / pre >
< / div >
< / div >
< / div >
< div class = "col-md-6" >
< div class = "card h-100" >
< div class = "card-header" >
< h5 class = "mb-0" > Database Management< / h5 >
< / div >
< div class = "card-body" >
< pre > < code class = "language-bash" > # Execute shell in container
docker-compose exec claude-tracker sh
# Initialize database manually
docker-compose exec claude-tracker python init_db.py
# Backup database
cp ./data/tracker.db ./data/tracker.db.backup
# View database size
du -h ./data/tracker.db< / code > < / pre >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- Monitoring & Health -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-heartbeat me-2" > < / i > Monitoring & Health< / h2 >
< div class = "card mb-3" >
< div class = "card-header bg-light" >
< h5 class = "mb-0" > Health Checks< / h5 >
< / div >
< div class = "card-body" >
< p > The container includes built-in health checks:< / p >
< ul >
< li > < strong > Endpoint:< / strong > < code > http://localhost:8000/health< / code > < / li >
< li > < strong > Interval:< / strong > 30 seconds< / li >
< li > < strong > Timeout:< / strong > 10 seconds< / li >
< li > < strong > Retries:< / strong > 3 attempts< / li >
< li > < strong > Start Period:< / strong > 30 seconds< / li >
< / ul >
< pre > < code class = "language-bash" > # Check health status
docker-compose ps
curl https://your-domain.com/health< / code > < / pre >
< / div >
< / div >
< div class = "card mb-3" >
< div class = "card-header bg-light" >
< h5 class = "mb-0" > Resource Limits< / h5 >
< / div >
< div class = "card-body" >
< p > Configured resource limits:< / p >
< ul >
< li > < strong > CPU Limit:< / strong > 1.0 core< / li >
< li > < strong > Memory Limit:< / strong > 512MB< / li >
< li > < strong > CPU Reservation:< / strong > 0.25 core< / li >
< li > < strong > Memory Reservation:< / strong > 128MB< / li >
< / ul >
< / div >
< / div >
< / section >
<!-- Troubleshooting -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-tools me-2" > < / i > Troubleshooting< / h2 >
< div class = "accordion" id = "troubleshootingAccordion" >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingOne" >
< button class = "accordion-button collapsed" type = "button" data-bs-toggle = "collapse" data-bs-target = "#collapseOne" >
Container keeps restarting
< / button >
< / h2 >
< div id = "collapseOne" class = "accordion-collapse collapse" data-bs-parent = "#troubleshootingAccordion" >
< div class = "accordion-body" >
< pre > < code class = "language-bash" > # Check logs for errors
docker-compose logs claude-tracker
# Check database permissions
ls -la ./data/
# Verify database initialization
docker-compose exec claude-tracker python init_db.py< / code > < / pre >
< / div >
< / div >
< / div >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingTwo" >
< button class = "accordion-button collapsed" type = "button" data-bs-toggle = "collapse" data-bs-target = "#collapseTwo" >
502 Bad Gateway errors
< / button >
< / h2 >
< div id = "collapseTwo" class = "accordion-collapse collapse" data-bs-parent = "#troubleshootingAccordion" >
< div class = "accordion-body" >
< pre > < code class = "language-bash" > # Check if container is running
docker-compose ps
# Verify health check
docker-compose exec claude-tracker curl localhost:8000/health
# Check Caddy network connectivity
docker network ls | grep caddy< / code > < / pre >
< / div >
< / div >
< / div >
< div class = "accordion-item" >
< h2 class = "accordion-header" id = "headingThree" >
< button class = "accordion-button collapsed" type = "button" data-bs-toggle = "collapse" data-bs-target = "#collapseThree" >
Database connection issues
< / button >
< / h2 >
< div id = "collapseThree" class = "accordion-collapse collapse" data-bs-parent = "#troubleshootingAccordion" >
< div class = "accordion-body" >
< pre > < code class = "language-bash" > # Create data directory if missing
mkdir -p ./data
chmod 755 ./data
# Remove corrupted database
rm ./data/tracker.db
# Restart container to reinitialize
docker-compose restart< / code > < / pre >
< / div >
< / div >
< / div >
< / div >
< / section >
<!-- Security Considerations -->
< section class = "mb-5" >
< h2 > < i class = "fas fa-shield-alt me-2" > < / i > Security Considerations< / h2 >
< div class = "alert alert-warning" >
< h5 > < i class = "fas fa-exclamation-triangle me-1" > < / i > Production Security< / h5 >
< ul class = "mb-0" >
< li > Set < code > DEBUG=false< / code > in production< / li >
< li > Use strong domain names and SSL certificates< / li >
< li > Regularly backup the database< / li >
< li > Monitor container logs for suspicious activity< / li >
< li > Keep Docker images updated< / li >
< li > Limit container resource usage< / li >
< / ul >
< / div >
< / section >
< / div >
<!-- Sidebar -->
< div class = "col-lg-4" >
< div class = "card sticky-top" style = "top: 1rem;" >
< div class = "card-header" >
< h5 class = "mb-0" > < i class = "fas fa-list me-1" > < / i > Quick Reference< / h5 >
< / div >
< div class = "card-body" >
< h6 > Essential Commands< / h6 >
< div class = "code-block mb-3" >
< pre > < code > # Deploy
docker-compose up -d
# Logs
docker-compose logs -f
# Stop
docker-compose down< / code > < / pre >
< / div >
< h6 > Key Files< / h6 >
< ul class = "list-unstyled" >
< li > < i class = "fas fa-file me-1" > < / i > < code > .env< / code > < / li >
< li > < i class = "fas fa-file me-1" > < / i > < code > docker-compose.yml< / code > < / li >
< li > < i class = "fas fa-file me-1" > < / i > < code > Dockerfile< / code > < / li >
< li > < i class = "fas fa-folder me-1" > < / i > < code > ./data/< / code > < / li >
< / ul >
< h6 > Default Ports< / h6 >
< ul class = "list-unstyled" >
< li > < i class = "fas fa-network-wired me-1" > < / i > 8000 (Internal)< / li >
< li > < i class = "fas fa-globe me-1" > < / i > 80/443 (Caddy)< / li >
< / ul >
< / div >
< / div >
< / div >
< / div >
{% endblock %}