agent/docker/docker-compose.yml
Snider 9df5ed10f6 feat(docker): local development stack for community onboarding
Multistage Dockerfile (FrankenPHP + Octane + Horizon + Reverb) with
docker-compose wiring 6 services: app, mariadb, qdrant, ollama, redis,
traefik. All data mounts to .core/vm/mnt/{config,data,log}. Traefik
routes *.lthn.sh with self-signed TLS. Setup script handles first-run
bootstrap including cert generation and embedding model pull.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-15 13:15:05 +00:00

138 lines
4.3 KiB
YAML

# Core Agent — Local Development Stack
# Usage: docker compose up -d
# Data: .core/vm/mnt/{config,data,log}
services:
app:
build:
context: ..
dockerfile: docker/Dockerfile
container_name: core-app
env_file: .env
volumes:
- ../.core/vm/mnt/log/app:/app/storage/logs
networks:
- core-net
depends_on:
mariadb:
condition: service_healthy
redis:
condition: service_healthy
qdrant:
condition: service_started
restart: unless-stopped
labels:
- "traefik.enable=true"
# Main app
- "traefik.http.routers.app.rule=Host(`lthn.sh`) || Host(`api.lthn.sh`) || Host(`mcp.lthn.sh`) || Host(`docs.lthn.sh`) || Host(`lab.lthn.sh`)"
- "traefik.http.routers.app.entrypoints=websecure"
- "traefik.http.routers.app.tls=true"
- "traefik.http.routers.app.service=app"
- "traefik.http.services.app.loadbalancer.server.port=8088"
# WebSocket (Reverb)
- "traefik.http.routers.app-ws.rule=Host(`lthn.sh`) && PathPrefix(`/app`)"
- "traefik.http.routers.app-ws.entrypoints=websecure"
- "traefik.http.routers.app-ws.tls=true"
- "traefik.http.routers.app-ws.service=app-ws"
- "traefik.http.routers.app-ws.priority=10"
- "traefik.http.services.app-ws.loadbalancer.server.port=8080"
mariadb:
image: mariadb:11
container_name: core-mariadb
environment:
MARIADB_ROOT_PASSWORD: ${DB_PASSWORD:-core_local_dev}
MARIADB_DATABASE: ${DB_DATABASE:-core_agent}
MARIADB_USER: ${DB_USERNAME:-core}
MARIADB_PASSWORD: ${DB_PASSWORD:-core_local_dev}
volumes:
- ../.core/vm/mnt/data/mariadb:/var/lib/mysql
networks:
- core-net
restart: unless-stopped
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 5s
retries: 5
qdrant:
image: qdrant/qdrant:v1.17
container_name: core-qdrant
volumes:
- ../.core/vm/mnt/data/qdrant:/qdrant/storage
networks:
- core-net
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.qdrant.rule=Host(`qdrant.lthn.sh`)"
- "traefik.http.routers.qdrant.entrypoints=websecure"
- "traefik.http.routers.qdrant.tls=true"
- "traefik.http.services.qdrant.loadbalancer.server.port=6333"
ollama:
image: ollama/ollama:latest
container_name: core-ollama
volumes:
- ../.core/vm/mnt/data/ollama:/root/.ollama
networks:
- core-net
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.ollama.rule=Host(`ollama.lthn.sh`)"
- "traefik.http.routers.ollama.entrypoints=websecure"
- "traefik.http.routers.ollama.tls=true"
- "traefik.http.services.ollama.loadbalancer.server.port=11434"
redis:
image: redis:7-alpine
container_name: core-redis
volumes:
- ../.core/vm/mnt/data/redis:/data
networks:
- core-net
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
traefik:
image: traefik:v3
container_name: core-traefik
command:
- "--api.dashboard=true"
- "--api.insecure=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.network=core-net"
- "--providers.file.directory=/etc/traefik/config"
- "--providers.file.watch=true"
- "--log.level=INFO"
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ../.core/vm/mnt/config/traefik:/etc/traefik/config
- ../.core/vm/mnt/log/traefik:/var/log/traefik
networks:
- core-net
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.rule=Host(`traefik.lthn.sh`)"
- "traefik.http.routers.traefik.entrypoints=websecure"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.service=api@internal"
networks:
core-net:
name: core-net