Add frontend and Caddy to Docker Compose dev environment

Containerize the frontend dev server (Vite) and add a Caddy reverse
proxy for HTTPS termination, replacing the manual local setup. The
Caddy config proxies /api/* to the backend and everything else to the
frontend dev server.

Also simplify start.sh: remove --local Poetry mode, extract
get_compose_cmd helper, and document new services and DEV_HOST env var.
This commit is contained in:
Viktor Barzin 2026-02-06 23:45:29 +00:00
parent 2626870396
commit e55902d813
No known key found for this signature in database
GPG key ID: 0EB088298288D958
3 changed files with 89 additions and 92 deletions

View file

@ -1,5 +1,3 @@
version: "3.8"
services:
redis:
image: redis:8
@ -111,6 +109,37 @@ services:
networks:
- rec-network
frontend:
image: node:24-alpine
container_name: rec-frontend
working_dir: /app
ports:
- "5173:5173"
volumes:
- ./frontend:/app
- frontend_node_modules:/app/node_modules
environment:
- DEV_HOST=${DEV_HOST:-localhost}
command: sh -c "npm ci && npm run dev -- --host"
networks:
- rec-network
caddy:
image: caddy:alpine
container_name: rec-caddy
ports:
- "443:443"
volumes:
- ./frontend/Caddyfile.dev:/etc/caddy/Caddyfile
- caddy_data:/data
environment:
- DEV_HOST=${DEV_HOST:-localhost}
depends_on:
- frontend
- app
networks:
- rec-network
networks:
rec-network:
driver: bridge
@ -119,3 +148,5 @@ volumes:
redis_data:
mysql_data:
app_venv:
frontend_node_modules:
caddy_data:

View file

@ -0,0 +1,11 @@
{$DEV_HOST:localhost}:443 {
tls internal
handle /api/* {
reverse_proxy app:5001
}
handle {
reverse_proxy frontend:5173
}
}

View file

@ -2,9 +2,13 @@
set -eu
# Real Estate Crawler - Development Server
# Starts all backend services + frontend + Caddy HTTPS proxy via Docker Compose.
#
# Usage:
# ./start.sh - Start with Docker (recommended)
# ./start.sh --local - Start locally (requires Poetry and dependencies)
# ./start.sh - Start all services (backend + frontend)
# ./start.sh --build - Rebuild images before starting
# ./start.sh --down - Stop and remove all containers
# ./start.sh --logs - Follow logs from all services
# ./start.sh --help - Show help
show_help() {
@ -14,16 +18,40 @@ show_help() {
echo ""
echo "Options:"
echo " (default) Start all services with Docker Compose"
echo " --local Run locally with Poetry (requires local deps)"
echo " --build Rebuild Docker images before starting"
echo " --down Stop and remove all containers"
echo " --logs Follow logs from all services"
echo " --help Show this help message"
echo ""
echo "Services started:"
echo " redis Redis broker + cache (port 6379)"
echo " mysql MySQL database (port 3306)"
echo " app FastAPI backend (hot-reload) (port 5001)"
echo " celery Celery background worker"
echo " celery-beat Celery periodic scheduler"
echo " frontend Vite dev server (hot-reload) (port 5173)"
echo " caddy HTTPS reverse proxy (port 443)"
echo ""
echo "Environment variables:"
echo " DEV_HOST Hostname for HTTPS access (default: localhost)"
echo " Set this to your dev machine's hostname for OIDC auth."
echo ""
echo "Examples:"
echo " ./start.sh # Start with Docker"
echo " ./start.sh --build # Rebuild and start"
echo " ./start.sh --local # Run locally with Poetry"
echo " ./start.sh # Start everything"
echo " ./start.sh --build # Rebuild and start"
echo " DEV_HOST=devvm.local ./start.sh # Start with custom hostname"
}
get_compose_cmd() {
if command -v docker &> /dev/null; then
echo "docker compose"
elif command -v podman-compose &> /dev/null; then
echo "podman-compose"
else
echo "❌ Error: Neither docker nor podman-compose found." >&2
echo " Install Docker: https://docs.docker.com/get-docker/" >&2
exit 1
fi
}
start_docker() {
@ -32,96 +60,26 @@ start_docker() {
build_flag="--build"
fi
echo "🐳 Starting services with Docker Compose..."
echo "Starting all services with Docker Compose..."
echo ""
# Check if docker/podman is available
if command -v docker &> /dev/null; then
COMPOSE_CMD="docker compose"
elif command -v podman-compose &> /dev/null; then
COMPOSE_CMD="podman-compose"
else
echo "❌ Error: Neither docker nor podman-compose found."
echo " Install Docker: https://docs.docker.com/get-docker/"
echo " Or run locally: ./start.sh --local"
exit 1
fi
local compose_cmd
compose_cmd=$(get_compose_cmd)
$COMPOSE_CMD up $build_flag
$compose_cmd up $build_flag
}
stop_docker() {
echo "🛑 Stopping all containers..."
if command -v docker &> /dev/null; then
docker compose down
elif command -v podman-compose &> /dev/null; then
podman-compose down
fi
echo "Stopping all containers..."
local compose_cmd
compose_cmd=$(get_compose_cmd)
$compose_cmd down
}
show_logs() {
if command -v docker &> /dev/null; then
docker compose logs -f
elif command -v podman-compose &> /dev/null; then
podman-compose logs -f
fi
}
start_local() {
echo "🛠️ Starting locally with Poetry..."
echo ""
# Check Poetry is available
if ! command -v poetry &> /dev/null; then
echo "❌ Error: Poetry not found."
echo " Install: curl -sSL https://install.python-poetry.org | python3 -"
echo " Or use Docker: ./start.sh"
exit 1
fi
# Source .env if it exists
if [[ -f .env ]]; then
set -a
source .env
set +a
fi
ENV_MODE=${ENV:-"dev"}
# Ensure Redis is running
if ! nc -z localhost 6379 2>/dev/null; then
echo "📦 Starting Redis container..."
docker run -d --rm --name rec-redis-local -p 6379:6379 redis:latest || true
sleep 2
fi
echo "✅ Redis OK"
# Test celery connection
poetry run python celery_app.py
# Start Celery worker in background
echo "🔧 Starting Celery worker..."
if [[ "$ENV_MODE" == "dev" ]]; then
poetry run celery -A celery_app worker --loglevel=info &
else
poetry run alembic upgrade head
poetry run celery -A celery_app worker --beat --loglevel=info &
fi
CELERY_PID=$!
cleanup() {
echo ""
echo "🛑 Stopping Celery worker (PID: $CELERY_PID)..."
kill "$CELERY_PID" 2>/dev/null || true
wait "$CELERY_PID" 2>/dev/null || true
}
trap cleanup EXIT SIGINT SIGTERM
# Start uvicorn
echo "🚀 Starting API server on http://localhost:5001"
echo ""
poetry run uvicorn api.app:app --host 0.0.0.0 --port 5001 --reload
local compose_cmd
compose_cmd=$(get_compose_cmd)
$compose_cmd logs -f
}
# Parse arguments
@ -129,9 +87,6 @@ case "${1:-}" in
--help|-h)
show_help
;;
--local)
start_local
;;
--down)
stop_docker
;;