feat(demo): migrate 5 SelfStack services to demo stack (16→24 services)
Add Reactive Resume, Metrics, Kiwix, Resume Matcher, and Apple Health from the earlier SelfStack project. Rewrite Apple Health collector to use InfluxDB v2 with proper error handling. Update all tests, scripts, Homepage config, env template, and documentation for the expanded stack. New services: - Reactive Resume (4016) + Postgres/Minio/Chrome companions - Metrics (4021) - GitHub metrics visualization - Kiwix (4022) - offline wiki reader - Resume Matcher (4023) - AI resume screening - Apple Health (4024) - health data collector → InfluxDB v2 Also adds git policy to AGENTS.md: always commit and push automatically. 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
@@ -43,6 +43,14 @@ volumes:
|
||||
driver: local
|
||||
${COMPOSE_PROJECT_NAME}_atuin_data:
|
||||
driver: local
|
||||
${COMPOSE_PROJECT_NAME}_reactiveresume_postgres_data:
|
||||
driver: local
|
||||
${COMPOSE_PROJECT_NAME}_reactiveresume_minio_data:
|
||||
driver: local
|
||||
${COMPOSE_PROJECT_NAME}_kiwix_data:
|
||||
driver: local
|
||||
${COMPOSE_PROJECT_NAME}_resumematcher_data:
|
||||
driver: local
|
||||
|
||||
services:
|
||||
# Docker Socket Proxy - Security Layer
|
||||
@@ -585,3 +593,260 @@ services:
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
# Reactive Resume - Postgres Database
|
||||
reactiveresume-postgres:
|
||||
image: postgres:16-alpine
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-reactiveresume-postgres"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
volumes:
|
||||
- ${COMPOSE_PROJECT_NAME}_reactiveresume_postgres_data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: ${RESUME_POSTGRES_DB}
|
||||
POSTGRES_USER: ${RESUME_POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${RESUME_POSTGRES_PASSWORD}
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${RESUME_POSTGRES_USER} -d ${RESUME_POSTGRES_DB}"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: 5
|
||||
|
||||
# Reactive Resume - Minio Storage
|
||||
reactiveresume-minio:
|
||||
image: minio/minio
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-reactiveresume-minio"
|
||||
restart: unless-stopped
|
||||
command: server /data
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
ports:
|
||||
- "${RESUME_MINIO_PORT}:9000"
|
||||
volumes:
|
||||
- ${COMPOSE_PROJECT_NAME}_reactiveresume_minio_data:/data
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${RESUME_MINIO_USER}
|
||||
MINIO_ROOT_PASSWORD: ${RESUME_MINIO_PASSWORD}
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "--silent", "http://localhost:9000/minio/health/live"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: ${HEALTH_CHECK_RETRIES}
|
||||
|
||||
# Reactive Resume - Chrome (PDF Generation)
|
||||
reactiveresume-chrome:
|
||||
image: ghcr.io/browserless/chromium:latest
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-reactiveresume-chrome"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
environment:
|
||||
TIMEOUT: 10000
|
||||
CONCURRENT: 10
|
||||
TOKEN: ${RESUME_CHROME_TOKEN}
|
||||
EXIT_ON_HEALTH_FAILURE: true
|
||||
PRE_REQUEST_HEALTH_CHECK: true
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "--silent", "http://localhost:3000/health"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: ${HEALTH_CHECK_RETRIES}
|
||||
start_period: 30s
|
||||
|
||||
# Reactive Resume - Resume Builder
|
||||
reactiveresume-app:
|
||||
image: amruthpillai/reactive-resume:latest
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-reactiveresume-app"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
ports:
|
||||
- "${REACTIVE_RESUME_PORT}:3000"
|
||||
depends_on:
|
||||
reactiveresume-postgres:
|
||||
condition: service_healthy
|
||||
reactiveresume-minio:
|
||||
condition: service_started
|
||||
reactiveresume-chrome:
|
||||
condition: service_started
|
||||
environment:
|
||||
PORT: 3000
|
||||
NODE_ENV: production
|
||||
PUBLIC_URL: http://localhost:${REACTIVE_RESUME_PORT}
|
||||
STORAGE_URL: http://localhost:${RESUME_MINIO_PORT}/default
|
||||
CHROME_TOKEN: ${RESUME_CHROME_TOKEN}
|
||||
CHROME_URL: ws://reactiveresume-chrome:3000
|
||||
DATABASE_URL: postgresql://${RESUME_POSTGRES_USER}:${RESUME_POSTGRES_PASSWORD}@reactiveresume-postgres:5432/${RESUME_POSTGRES_DB}
|
||||
ACCESS_TOKEN_SECRET: ${RESUME_ACCESS_TOKEN_SECRET}
|
||||
REFRESH_TOKEN_SECRET: ${RESUME_REFRESH_TOKEN_SECRET}
|
||||
MAIL_FROM: noreply@localhost
|
||||
STORAGE_ENDPOINT: reactiveresume-minio
|
||||
STORAGE_PORT: 9000
|
||||
STORAGE_REGION: us-east-1
|
||||
STORAGE_BUCKET: default
|
||||
STORAGE_ACCESS_KEY: ${RESUME_MINIO_USER}
|
||||
STORAGE_SECRET_KEY: ${RESUME_MINIO_PASSWORD}
|
||||
STORAGE_USE_SSL: "false"
|
||||
STORAGE_SKIP_BUCKET_CHECK: "false"
|
||||
labels:
|
||||
homepage.group: "Productivity"
|
||||
homepage.name: "Reactive Resume"
|
||||
homepage.icon: "reactive-resume"
|
||||
homepage.href: "http://localhost:${REACTIVE_RESUME_PORT}"
|
||||
homepage.description: "Open-source resume builder"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "--silent", "http://localhost:3000/api/health"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
# Metrics - GitHub Metrics Visualization
|
||||
metrics:
|
||||
image: ghcr.io/lowlighter/metrics:latest
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-metrics"
|
||||
restart: unless-stopped
|
||||
entrypoint: [""]
|
||||
command: ["npm", "start"]
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
ports:
|
||||
- "${METRICS_PORT}:3000"
|
||||
volumes:
|
||||
- ./config/metrics/settings.json:/metrics/settings.json:ro
|
||||
environment:
|
||||
- PUID=${DEMO_UID}
|
||||
- PGID=${DEMO_GID}
|
||||
labels:
|
||||
homepage.group: "Monitoring"
|
||||
homepage.name: "Metrics"
|
||||
homepage.icon: "github"
|
||||
homepage.href: "http://localhost:${METRICS_PORT}"
|
||||
homepage.description: "GitHub metrics visualization"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: ${HEALTH_CHECK_RETRIES}
|
||||
start_period: 30s
|
||||
|
||||
# Kiwix - Offline Wiki
|
||||
kiwix:
|
||||
image: ghcr.io/kiwix/kiwix-serve:latest
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-kiwix"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
ports:
|
||||
- "${KIWIX_PORT}:8080"
|
||||
volumes:
|
||||
- ${COMPOSE_PROJECT_NAME}_kiwix_data:/data
|
||||
environment:
|
||||
- PUID=${DEMO_UID}
|
||||
- PGID=${DEMO_GID}
|
||||
labels:
|
||||
homepage.group: "Documentation"
|
||||
homepage.name: "Kiwix"
|
||||
homepage.icon: "kiwix"
|
||||
homepage.href: "http://localhost:${KIWIX_PORT}"
|
||||
homepage.description: "Offline wiki reader"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: ${HEALTH_CHECK_RETRIES}
|
||||
|
||||
# Resume Matcher - AI Resume Screening
|
||||
resumematcher:
|
||||
image: ghcr.io/srbhr/resume-matcher:latest
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-resumematcher"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
ports:
|
||||
- "${RESUME_MATCHER_PORT}:3000"
|
||||
volumes:
|
||||
- ${COMPOSE_PROJECT_NAME}_resumematcher_data:/app/backend/data
|
||||
environment:
|
||||
- PUID=${DEMO_UID}
|
||||
- PGID=${DEMO_GID}
|
||||
labels:
|
||||
homepage.group: "Productivity"
|
||||
homepage.name: "Resume Matcher"
|
||||
homepage.icon: "resume"
|
||||
homepage.href: "http://localhost:${RESUME_MATCHER_PORT}"
|
||||
homepage.description: "AI-powered resume screening"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 512M
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "--silent", "http://localhost:3000/api/v1/health"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: 5
|
||||
start_period: 60s
|
||||
|
||||
# Apple Health - Health Data Collector
|
||||
applehealth:
|
||||
build:
|
||||
context: ./config/applehealth
|
||||
dockerfile: Dockerfile
|
||||
image: tsys-applehealth:latest
|
||||
container_name: "${COMPOSE_PROJECT_NAME}-applehealth"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- ${COMPOSE_NETWORK_NAME}
|
||||
ports:
|
||||
- "${APPLEHEALTH_PORT}:5353"
|
||||
environment:
|
||||
- INFLUXDB_URL=http://influxdb:8086
|
||||
- INFLUXDB_TOKEN=${INFLUXDB_AUTH_TOKEN}
|
||||
- INFLUXDB_ORG=${INFLUXDB_ORG}
|
||||
- INFLUXDB_BUCKET=${INFLUXDB_BUCKET}
|
||||
- PUID=${DEMO_UID}
|
||||
- PGID=${DEMO_GID}
|
||||
depends_on:
|
||||
influxdb:
|
||||
condition: service_healthy
|
||||
labels:
|
||||
homepage.group: "Monitoring"
|
||||
homepage.name: "Apple Health"
|
||||
homepage.icon: "apple-health"
|
||||
homepage.href: "http://localhost:${APPLEHEALTH_PORT}"
|
||||
homepage.description: "Health data collection and visualization"
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 256M
|
||||
healthcheck:
|
||||
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:5353/health')"]
|
||||
interval: ${HEALTH_CHECK_INTERVAL}
|
||||
timeout: ${HEALTH_CHECK_TIMEOUT}
|
||||
retries: ${HEALTH_CHECK_RETRIES}
|
||||
start_period: 15s
|
||||
|
||||
Reference in New Issue
Block a user