- Add comprehensive Docker Compose configuration with 16 developer services - Configure Homepage dashboard with service discovery and grouping - Set up environment configuration for demo deployment - Include project documentation (PRD, README, User Guide, Agent guidelines) - Establish foundation for developer tooling stack with proper networking and security Services include developer tools (Homepage, Atuin, Wakapi, ArchiveBox, Tube Archivist, MailHog), infrastructure (PostgreSQL, Elasticsearch, Redis, Docker Socket Proxy), monitoring (InfluxDB, Grafana), and documentation (Draw.io, Kroki).
546 lines
15 KiB
YAML
546 lines
15 KiB
YAML
---
|
|
# TSYS Developer Support Stack - Docker Compose Configuration for Demo
|
|
#
|
|
# NOTE: This configuration uses only Docker named volumes for storage, not bind mounts.
|
|
# All data is ephemeral and will be lost when the stack is removed with 'docker compose down -v'.
|
|
# This is intentional for the demo environment to ensure no persistent data accumulation.
|
|
#
|
|
services:
|
|
# Homepage - Developer dashboard
|
|
homepage:
|
|
image: ghcr.io/gethomepage/homepage:latest
|
|
container_name: tsysdevstack-supportstack-homepage
|
|
ports:
|
|
- "${HOMEPAGE_PORT}:3000"
|
|
volumes:
|
|
- ./homepage/config:/app/config:ro,Z # Demo: read-only config mount for functionality
|
|
# Running as root to avoid permission issues in demo
|
|
labels:
|
|
- "homepage.group=Developer Tools"
|
|
- "homepage.name=Homepage"
|
|
- "homepage.icon=homepage"
|
|
- "homepage.href=http://192.168.3.6:4000"
|
|
- "homepage.description=Developer dashboard and service discovery"
|
|
environment:
|
|
DOCKER_HOST: >
|
|
tcp://tsysdevstack-supportstack-docker-socket-proxy:${DOCKER_PROXY_PORT}
|
|
HOMEPAGE_ALLOWED_HOSTS: "*"
|
|
HOMEPAGE_VAR_DOCKER_HOST: >
|
|
tcp://tsysdevstack-supportstack-docker-socket-proxy:${DOCKER_PROXY_PORT}
|
|
# Use docker.yaml with explicit include/exclude filtering
|
|
depends_on:
|
|
- tsysdevstack-supportstack-docker-socket-proxy
|
|
restart: unless-stopped
|
|
|
|
# Atuin - Shell history
|
|
atuin:
|
|
image: ghcr.io/atuinsh/atuin:latest
|
|
container_name: tsysdevstack-supportstack-atuin
|
|
ports:
|
|
- "${ATUIN_PORT}:8888"
|
|
labels:
|
|
- "homepage.group=Developer Tools"
|
|
- "homepage.name=Atuin"
|
|
- "homepage.icon=atuin"
|
|
- "homepage.href=http://192.168.3.6:4001"
|
|
- "homepage.description=Synced shell history database"
|
|
environment:
|
|
ATUIN_HOST: "0.0.0.0"
|
|
ATUIN_PORT: "8888"
|
|
ATUIN_OPEN_REGISTRATION: "true"
|
|
ATUIN_DB_URI: >
|
|
postgres://atuin:demo_password@tsysdevstack-supportstack-postgres:5432/atuin
|
|
RUST_LOG: "debug,atuin_server=debug,sqlx=debug"
|
|
command: server start
|
|
# No persistent volumes for demo - config is ephemeral
|
|
user: "${PUID}:${PGID}"
|
|
depends_on:
|
|
tsysdevstack-supportstack-postgres:
|
|
condition: service_healthy
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# Wakapi - Time tracking
|
|
wakapi:
|
|
image: ghcr.io/muety/wakapi:latest
|
|
container_name: tsysdevstack-supportstack-wakapi
|
|
ports:
|
|
- "${WAKAPI_PORT}:3000"
|
|
labels:
|
|
- "homepage.group=Developer Tools"
|
|
- "homepage.name=Wakapi"
|
|
- "homepage.icon=wakapi"
|
|
- "homepage.href=http://192.168.3.6:4002"
|
|
- "homepage.description=Self-hosted time tracking"
|
|
environment:
|
|
- WAKAPI_PASSWORD_SALT=demo_password
|
|
# No persistent volumes for demo - data is ephemeral
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "wget --no-verbose --tries=1 --spider http://localhost:8086/ping || exit 1"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# MailHog - Email testing
|
|
mailhog:
|
|
image: mailhog/mailhog:latest
|
|
container_name: tsysdevstack-supportstack-mailhog
|
|
ports:
|
|
- "1025:1025"
|
|
- "${MAILHOG_PORT}:8025"
|
|
labels:
|
|
- "homepage.group=Developer Tools"
|
|
- "homepage.name=MailHog"
|
|
- "homepage.icon=mailhog"
|
|
- "homepage.href=http://192.168.3.6:4005"
|
|
- "homepage.description=Email testing service"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "echo > /dev/tcp/localhost:8025"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 128M
|
|
cpus: '0.25'
|
|
|
|
# Pi-hole - DNS management
|
|
pihole:
|
|
image: pihole/pihole:latest
|
|
container_name: tsysdevstack-supportstack-pihole
|
|
# Note: Pi-hole requires root for DNS capabilities and file permissions
|
|
ports:
|
|
- "${PIHOLE_PORT}:80"
|
|
- "53:53/tcp"
|
|
- "53:53/udp"
|
|
- "67:67/udp"
|
|
labels:
|
|
- "homepage.group=Infrastructure"
|
|
- "homepage.name=Pi-hole"
|
|
- "homepage.icon=pihole"
|
|
- "homepage.href=http://192.168.3.6:4006"
|
|
- "homepage.description=DNS-based ad blocking and network monitoring"
|
|
environment:
|
|
- TZ=UTC
|
|
- WEBPASSWORD=${DEMO_PASSWORD}
|
|
- PIHOLE_DNS_=1.1.1.1;1.0.0.1
|
|
- DNSMASQ_LISTENING=all
|
|
- WEBTHEME=default-dark
|
|
# No persistent volumes for demo - configuration is ephemeral
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "echo > /dev/tcp/localhost/80"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 512M
|
|
cpus: '0.75'
|
|
|
|
# Portainer - Container management
|
|
portainer:
|
|
image: portainer/portainer-ce:latest
|
|
container_name: tsysdevstack-supportstack-portainer
|
|
ports:
|
|
- "${PORTAINER_PORT}:9000"
|
|
labels:
|
|
- "homepage.group=Infrastructure"
|
|
- "homepage.name=Portainer"
|
|
- "homepage.icon=portainer"
|
|
- "homepage.href=http://192.168.3.6:4007"
|
|
- "homepage.description=Container management interface"
|
|
# No persistent volumes for demo - data is ephemeral
|
|
# Note: Portainer needs root for data directory permissions
|
|
environment:
|
|
DOCKER_HOST: >
|
|
tcp://tsysdevstack-supportstack-docker-socket-proxy:${DOCKER_PROXY_PORT}
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "echo > /dev/tcp/localhost/9000"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# ArchiveBox - Web archiving
|
|
archivebox:
|
|
image: archivebox/archivebox:latest
|
|
container_name: tsysdevstack-supportstack-archivebox
|
|
ports:
|
|
- "${ARCHIVEBOX_PORT}:8000"
|
|
labels:
|
|
- "homepage.group=Developer Tools"
|
|
- "homepage.name=ArchiveBox"
|
|
- "homepage.icon=archivebox"
|
|
- "homepage.href=http://192.168.3.6:4003"
|
|
- "homepage.description=Self-hosted web archiving"
|
|
environment:
|
|
- ALLOWED_HOSTS=*
|
|
- MEDIA_MAX_SIZE=750m
|
|
# No persistent volumes for demo - data is ephemeral
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# InfluxDB - Time series database
|
|
influxdb:
|
|
image: influxdb:2.7-alpine
|
|
container_name: tsysdevstack-supportstack-influxdb
|
|
ports:
|
|
- "${INFLUXDB_PORT}:8086"
|
|
labels:
|
|
- "homepage.group=Monitoring"
|
|
- "homepage.name=InfluxDB"
|
|
- "homepage.icon=influxdb"
|
|
- "homepage.href=http://192.168.3.6:4008"
|
|
- "homepage.description=Time series database for metrics storage"
|
|
environment:
|
|
- DOCKER_INFLUXDB_INIT_MODE=setup
|
|
- DOCKER_INFLUXDB_INIT_USERNAME=admin
|
|
- DOCKER_INFLUXDB_INIT_PASSWORD=${DEMO_PASSWORD}
|
|
- DOCKER_INFLUXDB_INIT_ORG=tsysdev
|
|
- DOCKER_INFLUXDB_INIT_BUCKET=metrics
|
|
# No persistent volumes for demo - data is ephemeral
|
|
user: "${PUID}:${PGID}"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "wget --no-verbose --tries=1 --spider http://localhost:8086/ping || exit 1"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# Grafana - Analytics visualization
|
|
grafana:
|
|
image: grafana/grafana:latest
|
|
container_name: tsysdevstack-supportstack-grafana
|
|
ports:
|
|
- "${GRAFANA_PORT}:3000"
|
|
labels:
|
|
- "homepage.group=Monitoring"
|
|
- "homepage.name=Grafana"
|
|
- "homepage.icon=grafana"
|
|
- "homepage.href=http://192.168.3.6:4009"
|
|
- "homepage.description=Analytics and visualization platform"
|
|
environment:
|
|
- GF_SECURITY_ADMIN_USER=admin
|
|
- GF_SECURITY_ADMIN_PASSWORD=${DEMO_PASSWORD}
|
|
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
|
|
- GF_SERVER_DOMAIN=192.168.3.6:4009
|
|
- GF_SERVER_ROOT_URL=http://192.168.3.6:4009
|
|
# No persistent volumes for demo - data is ephemeral
|
|
user: "${PUID}:${PGID}"
|
|
depends_on:
|
|
- influxdb
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "echo > /dev/tcp/localhost/3000"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 512M
|
|
cpus: '0.75'
|
|
|
|
# Draw.io - Diagramming
|
|
drawio:
|
|
image: jgraph/drawio:latest
|
|
container_name: tsysdevstack-supportstack-drawio
|
|
user: "${PUID}:${PGID}"
|
|
ports:
|
|
- "${DRAWIO_PORT}:8080"
|
|
labels:
|
|
- "homepage.group=Documentation"
|
|
- "homepage.name=Draw.io"
|
|
- "homepage.icon=diagram"
|
|
- "homepage.href=http://192.168.3.6:4010"
|
|
- "homepage.description=Web-based diagramming tool"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "echo > /dev/tcp/localhost/3000"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# Tube Archivist - YouTube media archiving
|
|
tube-archivist:
|
|
image: bbilly1/tubearchivist:latest
|
|
container_name: tsysdevstack-supportstack-tube-archivist
|
|
ports:
|
|
- "4004:8000"
|
|
labels:
|
|
- "homepage.group=Developer Tools"
|
|
- "homepage.name=Tube Archivist"
|
|
- "homepage.icon=youtube"
|
|
- "homepage.href=http://192.168.3.6:4004"
|
|
- "homepage.description=Self-hosted YouTube media archiving"
|
|
environment:
|
|
- TA_HOST=192.168.3.6:4004
|
|
- TA_USERNAME=demo_user
|
|
- TA_PASSWORD=demo_password
|
|
- ES_URL=http://elastic:demo_password@tsysdevstack-supportstack-elasticsearch:9200
|
|
- ELASTIC_PASSWORD=demo_password
|
|
- REDIS_CON=redis://tsysdevstack-supportstack-redis:6379
|
|
- TZ=UTC
|
|
depends_on:
|
|
tsysdevstack-supportstack-elasticsearch:
|
|
condition: service_healthy
|
|
tsysdevstack-supportstack-redis:
|
|
condition: service_healthy
|
|
# No persistent volumes for demo - cache and media are ephemeral
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "wget --no-verbose --tries=1 --spider http://localhost:8000/ || exit 1"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 512M
|
|
cpus: '1.0'
|
|
|
|
# Kroki - Diagrams as code
|
|
kroki:
|
|
image: yuzutech/kroki:latest
|
|
container_name: tsysdevstack-supportstack-kroki
|
|
user: "${PUID}:${PGID}"
|
|
ports:
|
|
- "${KROKI_PORT}:8000"
|
|
labels:
|
|
- "homepage.group=Documentation"
|
|
- "homepage.name=Kroki"
|
|
- "homepage.icon=diagram"
|
|
- "homepage.href=http://192.168.3.6:4011"
|
|
- "homepage.description=Service for converting text diagrams to images"
|
|
environment:
|
|
- KROKI_SAFE_MODE=0
|
|
- KROKI_PLANTUML_ALLOW_LIST=*
|
|
- KROKI_MERMAID_ALLOW_LIST=*
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "wget --no-verbose --tries=1 --spider http://localhost:8000/health || exit 1"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# Docker Socket Proxy - Secure Docker API access
|
|
tsysdevstack-supportstack-docker-socket-proxy:
|
|
image: tecnativa/docker-socket-proxy:latest
|
|
container_name: tsysdevstack-supportstack-docker-socket-proxy
|
|
ports:
|
|
- "${DOCKER_PROXY_PORT}:2375"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
environment:
|
|
- CONTAINERS=1
|
|
- SERVICES=1
|
|
- TASKS=1
|
|
- NETWORKS=1
|
|
- NODES=1
|
|
- IMAGES=1
|
|
- VOLUMES=1
|
|
- EXEC=0
|
|
- SECRETS=0
|
|
- CONFIGS=0
|
|
- PLUGINS=0
|
|
- SYSTEM=0
|
|
- INFO=1
|
|
- VERSION=1
|
|
- EVENTS=0
|
|
- POST=0
|
|
- DELETE=0
|
|
- PUT=0
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- "wget --no-verbose --tries=1 --spider http://localhost:2375/version || exit 1"
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 60s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 128M
|
|
cpus: '0.25'
|
|
|
|
# PostgreSQL - Database for Atuin
|
|
tsysdevstack-supportstack-postgres:
|
|
image: postgres:15-alpine
|
|
container_name: tsysdevstack-supportstack-postgres
|
|
labels:
|
|
- "homepage.group=Infrastructure"
|
|
- "homepage.name=PostgreSQL"
|
|
- "homepage.icon=postgresql"
|
|
- "homepage.description=PostgreSQL database server"
|
|
environment:
|
|
- POSTGRES_DB=atuin
|
|
- POSTGRES_USER=atuin
|
|
- POSTGRES_PASSWORD=${DEMO_PASSWORD}
|
|
# No persistent volumes for demo - data is ephemeral
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD
|
|
- pg_isready
|
|
- -U
|
|
- atuin
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
cpus: '0.5'
|
|
|
|
# Elasticsearch - Search engine
|
|
tsysdevstack-supportstack-elasticsearch:
|
|
image: docker.elastic.co/elasticsearch/elasticsearch:8.11.1
|
|
container_name: tsysdevstack-supportstack-elasticsearch
|
|
labels:
|
|
- "homepage.group=Infrastructure"
|
|
- "homepage.name=Elasticsearch"
|
|
- "homepage.icon=elasticsearch"
|
|
- "homepage.description=Search and analytics engine"
|
|
environment:
|
|
- "discovery.type=single-node"
|
|
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
|
- "xpack.security.enabled=true"
|
|
- "ELASTIC_PASSWORD=${DEMO_PASSWORD}"
|
|
- "path.repo=/usr/share/elasticsearch/data/snapshot"
|
|
# No persistent volumes for demo - data is ephemeral
|
|
user: "${PUID}:${PGID}"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD-SHELL
|
|
- >
|
|
curl -f -u elastic:demo_password
|
|
http://localhost:9200/_cluster/health?wait_for_status=yellow&timeout=30s || exit 1
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 5
|
|
start_period: 120s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 1G
|
|
cpus: '1.0'
|
|
|
|
# Redis for Tube Archivist
|
|
tsysdevstack-supportstack-redis:
|
|
image: redis:7-alpine
|
|
container_name: tsysdevstack-supportstack-redis
|
|
user: "${PUID}:${PGID}"
|
|
labels:
|
|
- "homepage.group=Infrastructure"
|
|
- "homepage.name=Redis"
|
|
- "homepage.icon=redis"
|
|
- "homepage.description=In-memory data structure store"
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test:
|
|
- CMD
|
|
- redis-cli
|
|
- ping
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 128M
|
|
cpus: '0.25'
|
|
|
|
# No persistent volumes - demo is 100% ephemeral
|
|
# Only Docker socket bind mount is used for functionality
|
|
|
|
networks:
|
|
default:
|
|
name: tsysdevstack_supportstack
|