Add Docker Compose with Caddy reverse proxy integration

- Multi-stage Dockerfile with development and production modes
- Docker Compose with caddy-docker-proxy labels for HTTPS
- Domain configuration: DOMAIN=rentcache.l.supported.systems
- Comprehensive Makefile with development and production targets
- Support for external caddy network and Redis backend
- Health checks and proper volume management
- Environment configuration with .env file

Usage:
- make setup  # Complete setup
- make dev    # Development with hot reload
- make prod   # Production deployment
- URL: https://rentcache.l.supported.systems
This commit is contained in:
Ryan Malloy 2025-09-09 20:13:37 -06:00
parent c0eaecad21
commit f46bdc978e
3 changed files with 210 additions and 147 deletions

68
Dockerfile Normal file
View File

@ -0,0 +1,68 @@
# Multi-stage Dockerfile for RentCache
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS base
# Set working directory
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
# Copy dependency files
COPY pyproject.toml uv.lock ./
# Install dependencies
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-dev
# Copy source code
COPY src/ ./src/
COPY README.md LICENSE ./
# Install the project
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-editable
# Development stage
FROM base AS development
# Install development dependencies
RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-editable
# Create non-root user
RUN groupadd -r rentcache && useradd -r -g rentcache rentcache
RUN chown -R rentcache:rentcache /app
USER rentcache
# Create data directories
RUN mkdir -p /app/data /app/logs
EXPOSE 8000
# Development command with hot reload
CMD ["uv", "run", "rentcache", "server", "--host", "0.0.0.0", "--port", "8000", "--reload"]
# Production stage
FROM base AS production
# Create non-root user
RUN groupadd -r rentcache && useradd -r -g rentcache rentcache
RUN chown -R rentcache:rentcache /app
USER rentcache
# Create data directories
RUN mkdir -p /app/data /app/logs
# Compile bytecode for better performance
ENV UV_COMPILE_BYTECODE=1
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Production command
CMD ["uv", "run", "rentcache", "server", "--host", "0.0.0.0", "--port", "8000"]

236
Makefile
View File

@ -1,176 +1,118 @@
# RentCache Makefile
.PHONY: help install dev test lint format clean server docs
.PHONY: help dev prod build up down logs shell test clean
# Default target
help:
@echo "RentCache Development Commands"
@echo "=============================="
help: ## Show this help message
@echo "RentCache - Intelligent Rentcast API caching proxy"
@echo ""
@echo "Setup:"
@echo " install Install dependencies"
@echo " dev Install dev dependencies"
@echo ""
@echo "Development:"
@echo " server Start development server"
@echo " test Run tests"
@echo " test-cov Run tests with coverage"
@echo " lint Run linting"
@echo " format Format code"
@echo ""
@echo "Database:"
@echo " db-init Initialize database"
@echo " db-reset Reset database"
@echo ""
@echo "Utilities:"
@echo " clean Clean temporary files"
@echo " docs Generate documentation"
@echo " check Run all checks (lint, test, format)"
@echo "Available targets:"
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
# Installation
install:
uv sync
# Development
dev: ## Start development environment with hot reload
@echo "🚀 Starting RentCache in development mode..."
@docker compose --profile redis up --build -d
@echo "✅ RentCache available at: https://rentcache.l.supported.systems"
@echo "📚 API docs: https://rentcache.l.supported.systems/docs"
@echo "❤️ Health: https://rentcache.l.supported.systems/health"
dev:
uv sync --all-extras
prod: ## Start production environment
@echo "🏭 Starting RentCache in production mode..."
@MODE=production DEBUG=false docker compose up --build -d
@echo "✅ RentCache running in production mode"
# Development server
server:
uv run rentcache server --reload
# Docker management
build: ## Build Docker images
@docker compose build
# Testing
test:
uv run pytest -v
up: ## Start services
@docker compose up -d
test-cov:
uv run pytest --cov=src/rentcache --cov-report=html --cov-report=term
down: ## Stop services
@docker compose down
test-watch:
uv run pytest-watch --runner "uv run pytest"
logs: ## View logs
@docker compose logs -f rentcache
# Code quality
lint:
uv run ruff check src tests
uv run mypy src
shell: ## Open shell in running container
@docker compose exec rentcache /bin/bash
format:
uv run black src tests
uv run ruff check src tests --fix
# Testing and development
test: ## Run tests
@echo "🧪 Running tests..."
@uv run pytest tests/ -v
check: lint test
@echo "✅ All checks passed!"
test-cov: ## Run tests with coverage
@echo "🧪 Running tests with coverage..."
@uv run pytest tests/ --cov=src/rentcache --cov-report=html
# Database management
db-init:
uv run python -c "import asyncio; from rentcache.models import Base; from sqlalchemy.ext.asyncio import create_async_engine; asyncio.run(create_async_engine('sqlite+aiosqlite:///./rentcache.db').begin().__aenter__().run_sync(Base.metadata.create_all))"
lint: ## Run linting
@echo "🔍 Running linting..."
@uv run ruff check src/ tests/
@uv run mypy src/
db-reset:
rm -f rentcache.db
$(MAKE) db-init
format: ## Format code
@echo "✨ Formatting code..."
@uv run black src/ tests/
@uv run ruff --fix src/ tests/
# CLI shortcuts
create-key:
@read -p "Key name: " name; \
read -p "Rentcast API key: " key; \
uv run rentcache create-key "$$name" "$$key"
# Database and cache
db-shell: ## Open database shell
@echo "🗄️ Opening database shell..."
@docker compose exec rentcache uv run python -c "from rentcache.database import engine; import sqlite3; sqlite3.connect('data/rentcache.db').execute('.tables')"
list-keys:
uv run rentcache list-keys
cache-clear: ## Clear all cache
@echo "🧹 Clearing cache..."
@docker compose exec rentcache uv run rentcache clear-cache --all
stats:
uv run rentcache stats
health: ## Check system health
@echo "❤️ Checking health..."
@docker compose exec rentcache uv run rentcache health
health:
uv run rentcache health
stats: ## Show usage statistics
@echo "📊 Usage statistics..."
@docker compose exec rentcache uv run rentcache stats
# Cleanup
clean:
find . -type d -name __pycache__ -delete
find . -type f -name "*.pyc" -delete
find . -type d -name "*.egg-info" -exec rm -rf {} +
rm -rf .coverage
rm -rf htmlcov/
rm -rf reports/
rm -rf build/
rm -rf dist/
clean: ## Clean up containers, volumes, and images
@echo "🧹 Cleaning up..."
@docker compose down -v --remove-orphans
@docker system prune -f
# Documentation
docs:
@echo "📚 API documentation available at:"
@echo " http://localhost:8000/docs (when server is running)"
@echo " http://localhost:8000/redoc (alternative docs)"
clean-all: clean ## Clean everything including images
@docker compose down -v --rmi all --remove-orphans
@docker system prune -af
# Docker commands
docker-build:
docker build -t rentcache .
# API key management
create-key: ## Create API key (usage: make create-key NAME=myapp KEY=your_key)
@docker compose exec rentcache uv run rentcache create-key $(NAME) $(KEY) --daily-limit 1000
docker-run:
docker run -p 8000:8000 --env-file .env rentcache
list-keys: ## List all API keys
@docker compose exec rentcache uv run rentcache list-keys
docker-dev:
docker-compose up -d
# Install local development
install: ## Install for local development
@echo "📦 Installing dependencies..."
@uv sync
@echo "✅ Ready for development"
docker-logs:
docker-compose logs -f rentcache
local-dev: install ## Run locally for development
@echo "🖥️ Starting local development server..."
@uv run rentcache server --reload
docker-stop:
docker-compose down
# URL helpers
url: ## Show the service URL
@echo "🌐 RentCache URL: https://rentcache.l.supported.systems"
# Production deployment helpers
deploy-check:
@echo "🚀 Pre-deployment checklist:"
@echo " - [ ] Tests passing"
@echo " - [ ] Environment variables configured"
@echo " - [ ] Database migrations ready"
@echo " - [ ] SSL certificates configured"
@echo " - [ ] Monitoring setup"
@echo " - [ ] Backup strategy in place"
docs: ## Open API documentation
@echo "📚 API Documentation: https://rentcache.l.supported.systems/docs"
# Performance testing
perf-test:
@echo "⚡ Running performance tests..."
uv run python -m pytest tests/ -m performance -v
benchmark:
@echo "📊 Running benchmarks..."
# Add your benchmark commands here
# Development environment
env-copy:
cp .env.example .env
@echo "📝 .env file created from example. Please edit with your settings."
setup: install env-copy db-init
@echo "🎉 Setup complete! Run 'make server' to start development."
# Release helpers
version:
@echo "Current version: $$(grep version pyproject.toml | head -1 | cut -d'"' -f2)"
bump-version:
@read -p "New version: " version; \
sed -i "s/version = .*/version = \"$$version\"/" pyproject.toml; \
echo "Version bumped to $$version"
build:
uv build
publish:
uv publish
# Monitoring and debugging
logs:
tail -f rentcache.log
monitor:
watch -n 1 "curl -s http://localhost:8000/metrics | jq '.'"
debug-server:
uv run python -m debugpy --listen 5678 --wait-for-client -m rentcache.server
# Quick shortcuts for common operations
s: server
t: test
f: format
l: lint
c: clean
# Quick setup
setup: ## Complete setup (build, create network if needed, start)
@echo "🚀 Setting up RentCache..."
@docker network create caddy 2>/dev/null || true
@make build
@make dev
@echo ""
@echo "🎉 RentCache is ready!"
@make url

53
docker-compose.yml Normal file
View File

@ -0,0 +1,53 @@
services:
rentcache:
build:
context: .
dockerfile: Dockerfile
target: ${MODE:-production}
environment:
- HOST=0.0.0.0
- PORT=8000
- DATABASE_URL=sqlite+aiosqlite:///./data/rentcache.db
- DEBUG=${DEBUG:-false}
- LOG_LEVEL=${LOG_LEVEL:-INFO}
volumes:
- ./data:/app/data
- ./logs:/app/logs
# Development hot-reload
- ./src:/app/src:ro
networks:
- caddy
expose:
- "8000"
labels:
caddy: ${DOMAIN:-rentcache.l.supported.systems}
caddy.reverse_proxy: "{{upstreams}}"
caddy.header.X-Forwarded-Proto: https
caddy.header.X-Real-IP: "{remote_host}"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped
# Optional Redis for caching
redis:
image: redis:7-alpine
networks:
- caddy
volumes:
- redis_data:/data
command: redis-server --appendonly yes
profiles:
- redis
restart: unless-stopped
networks:
caddy:
external: true
volumes:
redis_data:
driver: local