annator-command-center / docker-configs /docker-compose.yaml
techprotrade's picture
Deploy ATOM FastAPI command center runtime (part 5)
90c6b42 verified
Raw
History Blame Contribute Delete
34 kB
version: "3.6"
services:
traefik:
image: "traefik:v2.10.4"
container_name: "traefik"
command:
- "--log.level=ERROR"
- "--providers.docker=true"
- "--providers.docker.exposedByDefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Let's Encrypt Resolver Configuration
- "--certificatesresolvers.le.acme.email=${LETSENCRYPT_EMAIL:-admin@example.com}" # Placeholder for user's email
- "--certificatesresolvers.le.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.le.acme.httpchallenge=true"
- "--certificatesresolvers.le.acme.httpchallenge.entrypoint=web"
# Global HTTP to HTTPS redirection (optional, can also be per-router)
# - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
# - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
labels:
- traefik.http.middlewares.strip-traefik.stripprefix.prefixes=/v1/traefik
- traefik.http.routers.traefik.rule=Host(`${HOST_NAME}`) && PathPrefix(`/v1/traefik`) || Host(`localhost`) && PathPrefix(`/v1/traefik`)
- traefik.http.routers.traefik.entrypoints=web # Traefik dashboard itself can remain on HTTP for simplicity if only accessed locally or via tunnel
- traefik.http.routers.traefik.middlewares=strip-traefik@docker,traefik-auth@docker # Added auth to traefik dashboard
- traefik.http.routers.traefik.service=api@internal
- "traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_USER:-admin}:${TRAEFIK_PASSWORD:-password}" # Renamed middleware for clarity
# Middleware for HTTP to HTTPS redirection
- "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.https-redirect.redirectscheme.permanent=true"
ports:
- "80:80"
- "443:443"
- "9090:8080" # Traefik API/Dashboard port (if enabled and needed)
volumes:
- ./letsencrypt:/letsencrypt
- "/var/run/docker.sock:/var/run/docker.sock:ro"
whoami: # Test service, useful for debugging Traefik rules
image: "traefik/whoami"
container_name: "whoami"
expose:
- 80 # whoami listens on port 80 by default
labels:
- "traefik.enable=true"
# HTTP router for whoami (for testing)
- "traefik.http.routers.whoami-http.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/whoami-http`)"
- "traefik.http.routers.whoami-http.entrypoints=web"
- "traefik.http.services.whoami.loadbalancer.server.port=80" # whoami default port
# HTTPS router for whoami (for testing HTTPS setup)
- "traefik.http.routers.whoami-https.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/whoami`)"
- "traefik.http.routers.whoami-https.entrypoints=websecure"
- "traefik.http.routers.whoami-https.tls=true"
- "traefik.http.routers.whoami-https.tls.certresolver=le"
- "traefik.http.routers.whoami-https.service=whoami" # Use the same service definition
postgres:
image: postgres:13-alpine
restart: always
volumes:
- ./postgres/data:/var/lib/postgresql/data
- ./initdb.d:/docker-entrypoint-initdb.d:ro
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-secretpgpassword}
POSTGRES_USERNAME: ${POSTGRES_USERNAME:-postgres}
healthcheck:
test:
["CMD", "pg_isready", "-U", "${POSTGRES_USERNAME}", "-d", "postgres"]
interval: 5s
timeout: 5s
retries: 5
ports:
- "5432:5432"
supertokens:
image: registry.supertokens.io/supertokens/supertokens-postgresql:6.0
depends_on:
postgres:
condition: service_healthy
expose:
- 3567
environment:
POSTGRESQL_CONNECTION_URI: ${SUPERTOKENS_POSTGRESQL_CONNECTION_URI:-postgresql://postgres:secretpgpassword@postgres:5432/postgres}
POSTGRESQL_TABLE_NAMES_PREFIX: Supertokens
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.strip-auth.stripprefix.prefixes=/v1/auth"
# HTTP router for auth (redirects to HTTPS)
- "traefik.http.routers.auth-http.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/auth`)"
- "traefik.http.routers.auth-http.entrypoints=web"
- "traefik.http.routers.auth-http.middlewares=strip-auth@docker,https-redirect@docker"
# HTTPS router for auth
- "traefik.http.routers.auth-https.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/auth`)"
- "traefik.http.routers.auth-https.entrypoints=websecure"
- "traefik.http.routers.auth-https.tls=true"
- "traefik.http.routers.auth-https.tls.certresolver=le"
- "traefik.http.routers.auth-https.middlewares=strip-auth@docker"
- "traefik.http.routers.auth-https.service=auth-service" # Explicit service name
- "traefik.http.services.auth-service.loadbalancer.server.port=3567"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3567/hello"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
postgraphile:
image: graphile/postgraphile:4 # Using latest V4, V5 is still in beta
depends_on:
postgres:
condition: service_healthy
restart: always
ports:
- "5000:5000" # Default PostGraphile port
environment:
DATABASE_URL: postgres://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD:-secretpgpassword}@postgres:5432/postgres
PGRAPHILE_WATCH_PG: "true" # Enable watch mode for schema changes
PGRAPHILE_JWT_SECRET: ${POSTGRAPHILE_JWT_SECRET:-secretjwtsecret} # JWT secret for PostGraphile
PGRAPHILE_JWT_PG_ROLE: public # Default role if not authenticated, or specify a dedicated one
PGRAPHILE_PG_DEFAULT_ROLE: public # Role to use for unauthenticated requests
# PostGraphile doesn't have a direct admin secret concept for API access. Access control is via PG roles.
# For enhanced security, consider using a dedicated read-only role for PostGraphile unless mutations are needed.
# PGRAPHILE_OWNER_CONNECTION_STRING: postgres://${POSTGRES_USERNAME}:${POSTGRES_PASSWORD:-secretpgpassword}@postgres:5432/postgres # For schema watching and migrations if needed with a more privileged user
PGRAPHILE_ENABLE_GRAPHIQL: "true"
# Add any other necessary PostGraphile environment variables here
# e.g., PGRAPHILE_SCHEMA_NAMES: public,app_public # Specify schemas to expose
# PGRAPHILE_APPEND_PLUGINS: @graphile-contrib/pg-simplify-inflector,@graphile/pg-pubsub
# PGRAPHILE_SIMPLE_COLLECTIONS: omit # or 'both' or 'only'
# PGRAPHILE_ENHANCE_GRAPHIQL: 'true'
# PGRAPHILE_ALLOW_EXPLAIN: 'true' # For debugging, be cautious in production
healthcheck:
test: [
"CMD-SHELL",
"curl -f http://localhost:5000/graphql?query={__typename} || exit 1",
] # Basic healthcheck query
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
functions:
build: ../../frontend-nextjs/project/functions
container_name: "functions"
depends_on:
- minio
- zookeeper
- kafka1
- optaplanner
- postgres
- postgraphile # Changed from graphql-engine
- redis # Replaced mongo with redis
environment:
BASIC_AUTH: ${BASIC_AUTH:-false}
FUNCTION_SERVER_URL: ${FUNCTION_SERVER_URL:-http://functions:3000}
OPENAI_API_KEY: ${OPENAI_API_KEY:-sk-default-openai-key}
GOOGLE_CLIENT_ID_ANDROID: ${GOOGLE_CLIENT_ID_ANDROID:-default_android_client_id}
GOOGLE_CLIENT_ID_IOS: ${GOOGLE_CLIENT_ID_IOS:-default_ios_client_id}
GOOGLE_CLIENT_ID_WEB: ${GOOGLE_CLIENT_ID_WEB:-default_web_client_id}
GOOGLE_CLIENT_ID_ATOMIC_WEB: ${GOOGLE_CLIENT_ID_ATOMIC_WEB:-}
GOOGLE_CLIENT_SECRET_ATOMIC_WEB: ${GOOGLE_CLIENT_SECRET_ATOMIC_WEB:-}
# PostGraphile doesn't use admin secrets, access control is via PG roles
POSTGRAPHILE_GRAPHQL_URL: http://postgraphile:5000/graphql # New URL for PostGraphile
# Not applicable for PostGraphile
GOOGLE_CLIENT_SECRET_WEB: ${GOOGLE_CLIENT_SECRET_WEB:-default_web_secret}
EMAIL: ${EMAIL:-admin@example.com}
# Base URL for the Python API service (running in python-agent)
# NOTE: python-agent service removed - duplicate functionality exists in backend/integrations/
# PYTHON_API_SERVICE_BASE_URL: ${PYTHON_API_SERVICE_BASE_URL:-http://python-agent:5000}
DOMAIN: ${DOMAIN:-localhost}
S3_ENDPOINT: http://minio:8484
S3_BUCKET: nhost
S3_ACCESS_KEY: ${STORAGE_ACCESS_KEY:-minioadmin}
S3_SECRET_KEY: ${STORAGE_SECRET_KEY:-minioadmin}
KAFKA_USERNAME: ${KAFKA_USERNAME:-kafka-user}
KAFKA_PASSWORD: ${KAFKA_PASSWORD:-kafka-password}
HOST_IP: ${HOST_IP:-127.0.0.1}
ZOOM_PASS_KEY: ${ZOOM_PASS_KEY:-default_zoom_pass_key}
ZOOM_CLIENT_ID: ${ZOOM_CLIENT_ID:-default_zoom_client_id}
ZOOM_SALT_FOR_PASS: ${ZOOM_SALT_FOR_PASS:-default_salt}
ZOOM_IV_FOR_PASS: ${ZOOM_IV_FOR_PASS:-default_iv}
OPTAPLANNER_URL: http://optaplanner:8081
OPTAPLANNER_USERNAME: ${OPTAPLANNER_USERNAME:-admin}
OPTAPLANNER_PASSWORD: ${OPTAPLANNER_PASSWORD:-adminpassword}
OPTAPLAN_ADMIN_CALLBACK_URL: http://functions:3000/post-process-calendar/onPostOptaCal/on-opta-plan-post-process-calendar-admin
GOOGLE_CALENDAR_WEBHOOK_URL: https://${HOST_NAME:-localhost}/v1/functions/google-calendar-sync/googleCalendarWebhook/google-calendar-webhook-public
GOOGLE_PEOPLE_SYNC_ADMIN_URL: https://${HOST_NAME:-localhost}/v1/functions/google-calendar-sync/googlePeopleSync/google-contact-sync-admin
OPTAPLANNER_DURATION: ${OPTAPLANNER_DURATION:-60}
OPTAPLANNER_SHORT_DURATION: ${OPTAPLANNER_SHORT_DURATION:-30}
APP_CLIENT_URL: ${APP_CLIENT_URL:-http://localhost:3000}
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.strip-functions.stripprefix.prefixes=/v1/functions"
# HTTP router for functions (redirects to HTTPS)
- "traefik.http.routers.functions-http.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/functions/`)"
- "traefik.http.routers.functions-http.entrypoints=web"
- "traefik.http.routers.functions-http.middlewares=strip-functions@docker,https-redirect@docker"
# HTTPS router for functions
- "traefik.http.routers.functions-https.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/functions/`)"
- "traefik.http.routers.functions-https.entrypoints=websecure"
- "traefik.http.routers.functions-https.tls=true"
- "traefik.http.routers.functions-https.tls.certresolver=le"
- "traefik.http.routers.functions-https.middlewares=strip-functions@docker"
- "traefik.http.routers.functions-https.service=functions-service" # Explicit service name
- "traefik.http.services.functions-service.loadbalancer.server.port=3000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/healthz"] # Assuming a /healthz endpoint exists or will be added
interval: 30s
timeout: 10s
retries: 3
start_period: 60s # Give functions a bit longer to start
restart: always
expose:
- 3000
ports:
- 3030:3030
volumes:
- ../../frontend-nextjs/project/functions:/app
- functions_node_modules:/app/node_modules
- ../../frontend-nextjs/project/functions/logs:/app/logs
minio:
image: minio/minio:RELEASE.2021-09-24T00-24-24Z
entrypoint: sh
command: -c 'mkdir -p /data/nhost && /opt/bin/minio server --console-address :9001 --address :8484 /data'
environment:
MINIO_ROOT_USER: ${STORAGE_ACCESS_KEY:-minioadmin}
MINIO_ROOT_PASSWORD: ${STORAGE_SECRET_KEY:-minioadmin}
ports:
- ${MINIO_PORT:-8484}:8484
- 9001:9001
volumes:
- ./data/minio:/data
mailhog:
image: mailhog/mailhog
environment:
SMTP_HOST: ${AUTH_SMTP_HOST:-mailhog}
SMTP_PORT: ${AUTH_SMTP_PORT:-1025}
SMTP_PASS: ${AUTH_SMTP_PASS:-password}
SMTP_USER: ${AUTH_SMTP_USER:-user}
SMTP_SECURE: "${AUTH_SMTP_SECURE:-false}"
SMTP_SENDER: ${AUTH_SMTP_SENDER:-hbp@hbp.com}
ports:
- ${AUTH_SMTP_PORT:-1025}:1025
- 8025:8025
volumes:
- ./data/mailhog:/maildir
zookeeper:
image: confluentinc/cp-zookeeper:5.4.2
hostname: zookeeper
container_name: zookeeper
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: "2181"
ZOOKEEPER_TICK_TIME: "2000"
KAFKA_OPTS: "-Djava.security.auth.login.config=/etc/kafka/server-jaas.conf -Dzookeeper.authProvider.1=org.apache.zookeeper.server.auth.SASLAuthenticationProvider"
volumes:
- ./kafka/kafka/server-jaas.conf:/etc/kafka/server-jaas.conf:ro,z
kafka1:
image: confluentinc/cp-kafka:5.4.2
hostname: kafka1
container_name: kafka1
labels:
- "custom.project=kafkajs"
- "custom.service=kafka1"
depends_on:
- zookeeper
ports:
- "29092:29092"
- "9092:9092"
- "29093:29093"
- "9093:9093"
- "29094:29094"
- "9094:9094"
environment:
KAFKA_ADVERTISED_HOST_NAME: kafka1
KAFKA_BROKER_ID: "0"
KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181"
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT,PLAINTEXT:SASL_PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:29092,PLAINTEXT_HOST://localhost:9092
KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true"
KAFKA_DEFAULT_REPLICATION_FACTOR: "1"
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: "1"
KAFKA_NUM_PARTITIONS: "1"
KAFKA_DELETE_TOPIC_ENABLE: "true"
KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: "0"
KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL: "PLAIN"
KAFKA_SASL_ENABLED_MECHANISMS: "PLAIN,SCRAM-SHA-256,SCRAM-SHA-512"
KAFKA_OPTS: "-Djava.security.auth.login.config=/opt/kafka/config/server-jaas.conf"
KAFKA_AUTHORIZER_CLASS_NAME: "kafka.security.auth.SimpleAclAuthorizer"
KAFKA_ALLOW_EVERYONE_IF_NO_ACL_FOUND: "true"
# suppress verbosity
# https://github.com/confluentinc/cp-docker-images/blob/master/debian/kafka/include/etc/confluent/docker/log4j.properties.template
KAFKA_LOG4J_LOGGERS: "kafka.controller=INFO,kafka.producer.async.DefaultEventHandler=INFO,state.change.logger=INFO"
CONFLUENT_SUPPORT_METRICS_ENABLE: "false"
CONFLUENT_METRICS_REPORTER_TOPIC_REPLICAS: "1"
volumes:
- ./kafka/kafka/server-jaas.conf:/opt/kafka/config/server-jaas.conf:ro,z
live-meeting-worker:
build:
context: ../python-api/live_meeting_worker # Path to the Dockerfile directory
dockerfile: Dockerfile
container_name: live-meeting-worker
depends_on:
- postgres # If it ever needs to interact with postgres directly
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- NOTION_API_KEY=${NOTION_API_KEY}
- NOTION_PARENT_PAGE_ID=${NOTION_PARENT_PAGE_ID} # Optional
- DATABASE_URL=/app/data/live_meeting_tasks.db
volumes:
- ./worker_data:/app/data # For SQLite DB persistence
ports:
- "8001:8001" # Expose the port FastAPI runs on
restart: always
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8001/list_audio_devices"] # Basic healthcheck
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.strip-live-meeting-worker.stripprefix.prefixes=/v1/live-meeting-worker"
# HTTP router (redirects to HTTPS)
- "traefik.http.routers.live-meeting-worker-http.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/live-meeting-worker`)"
- "traefik.http.routers.live-meeting-worker-http.entrypoints=web"
- "traefik.http.routers.live-meeting-worker-http.middlewares=strip-live-meeting-worker@docker,https-redirect@docker"
# HTTPS router
- "traefik.http.routers.live-meeting-worker-https.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/v1/live-meeting-worker`)"
- "traefik.http.routers.live-meeting-worker-https.entrypoints=websecure"
- "traefik.http.routers.live-meeting-worker-https.tls=true"
- "traefik.http.routers.live-meeting-worker-https.tls.certresolver=le"
- "traefik.http.routers.live-meeting-worker-https.middlewares=strip-live-meeting-worker@docker"
- "traefik.http.routers.live-meeting-worker-https.service=live-meeting-worker-service"
- "traefik.http.services.live-meeting-worker-service.loadbalancer.server.port=8001"
optaplanner:
image: atomic-scheduler:latest
restart: always
depends_on:
postgres:
condition: service_healthy
environment:
QUARKUS_DATASOURCE_JDBC_URL: jdbc:postgresql://postgres:5432/postgres
QUARKUS_DATASOURCE_USERNAME: ${POSTGRES_USERNAME:-postgres}
QUARKUS_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD:-secretpgpassword}
QUARKUS_DATASOURCE_DB-KIND: postgresql
USERNAME: admin
PASSWORD: ${API_TOKEN:-secretapitoken}
ports:
- 8081:8081
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8081/q/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s # Quarkus apps can take a moment to start
app:
build:
context: ../../frontend-nextjs
args:
POSTGRAPHILE_GRAPHQL_URL: http://postgraphile:5000/graphql # Internal URL for server-side rendering or API routes if needed
NEXT_PUBLIC_POSTGRAPHILE_GRAPHQL_URL: http://localhost:5000/graphql # URL for client-side
NEXT_PUBLIC_EVENT_TO_QUEUE_AUTH_URL: https://${HOST_NAME:-localhost}/v1/functions/schedule-event/publisherScheduleEvent/schedule-event-auth
NEXT_PUBLIC_EVENT_TO_QUEUE_SHORT_AUTH_URL: https://${HOST_NAME:-localhost}/v1/functions/schedule-event/publisherScheduleShortEvent/schedule-short-event-auth
NEXT_PUBLIC_CALENDAR_TO_QUEUE_AUTH_URL: https://${HOST_NAME:-localhost}/v1/functions/schedule-assist/publisherScheduleMeeting/schedule-meeting-to-queue-auth
NEXT_PUBLIC_FEATURES_APPLY_TO_EVENTS_AUTH_URL: https://${HOST_NAME:-localhost}/v1/functions/features-apply/publish-to-features-worker/features-worker-to-queue-auth
NEXT_PUBLIC_METHOD_TO_SEARCH_INDEX_AUTH_URL: https://${HOST_NAME:-localhost}/v1/functions/events-search/eventsSearch/events-search-auth
NEXT_PUBLIC_GOOGLE_CALENDAR_ANDROID_AUTH_URL: https://${HOST_NAME:-localhost}/v1/functions/google-api-auth/googleCalendarAndroidAuth/google-calendar-android-auth
NEXT_PUBLIC_GOOGLE_CALENDAR_ANDROID_AUTH_REFRESH_URL: https://${HOST_NAME:-localhost}/v1/functions/google-api-auth/googleCalendarAndroidAuthRefresh/google-calendar-android-auth-refresh
NEXT_PUBLIC_GOOGLE_ATOMIC_WEB_AUTH_REFRESH_URL: https://${HOST_NAME:-localhost}/v1/functions/google-api-auth/googleAtomicWebAuthRefresh/google-atomic-web-auth-refresh
NEXT_PUBLIC_GOOGLE_CALENDAR_IOS_AUTH_REFRESH_URL: https://${HOST_NAME:-localhost}/v1/functions/google-api-auth/googleCalendarIosAuthRefresh/google-calendar-ios-auth-refresh
NEXT_PUBLIC_GOOGLE_OAUTH_ATOMIC_WEB_API_START_URL: https://${HOST_NAME:-localhost}/api/google/start-oauth
NEXT_PUBLIC_GOOGLE_OAUTH_ATOMIC_WEB_REDIRECT_URL: https://${HOST_NAME:-localhost}/api/google/oauth-callback
GOOGLE_CLIENT_ID_ATOMIC_WEB: ${GOOGLE_CLIENT_ID_ATOMIC_WEB:-default_atomic_web_client_id}
GOOGLE_CLIENT_SECRET_ATOMIC_WEB: ${GOOGLE_CLIENT_SECRET_ATOMIC_WEB:-default_atomic_web_secret}
ZOOM_IV_FOR_PASS: ${ZOOM_IV_FOR_PASS:-default_iv}
ZOOM_SALT_FOR_PASS: ${ZOOM_SALT_FOR_PASS:-default_salt}
ZOOM_PASS_KEY: ${ZOOM_PASS_KEY:-default_zoom_pass_key}
NEXT_PUBLIC_EMAIL_MEETING_INFO_TO_HOST_URL: https://${HOST_NAME:-localhost}/v1/functions/email-notification/meeting-info-host/meeting-info-to-host-auth
NEXT_PUBLIC_EMAIL_MEETING_INVITE_URL: https://${HOST_NAME:-localhost}/v1/functions/email-notification/meeting-invite-email/meeting-invite-auth
NEXT_PUBLIC_EMAIL_MEETING_CANCEL_URL: https://${HOST_NAME:-localhost}/v1/functions/email-notification/meeting-cancel-email/meeting-cancel-auth
NEXT_PUBLIC_HANDSHAKE_URL: https://${HOST_NAME:-localhost}/v1/handshake/
NEXT_PUBLIC_DELETE_ZOOM_CONFERENCE_URL: https://${HOST_NAME:-localhost}/v1/functions/zoom-meeting/delZoomMeet/delete-zoom-meet-auth
NEXT_PUBLIC_GOOGLE_CALENDAR_SYNC_URL: https://${HOST_NAME:-localhost}/v1/functions/google-calendar-sync/googleCalendarSync/google-calendar-sync-auth
NEXT_PUBLIC_SELF_GOOGLE_CALENDAR_WATCH_URL: https://${HOST_NAME:-localhost}/v1/functions/google-calendar-sync/googleCalendarWatch/google-calendar-watch-auth
NEXT_PUBLIC_GOOGLE_OAUTH_START_URL: https://${HOST_NAME:-localhost}/Auth/google/oauth-start
NEXT_PUBLIC_CHAT_WS_API_URL: ws://localhost:3030
NEXT_PUBLIC_GOOGLE_PEOPLE_SYNC_URL: https://${HOST_NAME:-localhost}/v1/functions/google-calendar-sync/googlePeopleSync/google-contact-sync-auth
NEXT_PUBLIC_ADD_DAILY_FEATURES_AUTOPILOT_URL: https://${HOST_NAME:-localhost}/v1/functions/autopilot/addDailyFeatures/add-daily-features-to-event-auth
NEXT_PUBLIC_DELETE_SCHEDULED_EVENT_URL: https://${HOST_NAME:-localhost}/v1/functions/autopilot/deleteScheduledEvent/delete-scheduled-event-auth
NEXT_PUBLIC_ZOOM_CREATE_MEETING_URL: https://${HOST_NAME:-localhost}/v1/functions/zoom-meeting/createZoomMeet/create-zoom-meet-auth
NEXT_PUBLIC_ZOOM_UPDATE_MEETING_URL: https://${HOST_NAME:-localhost}/v1/functions/zoom-meeting/updateZoomMeet/update-zoom-meet-auth
NEXT_PUBLIC_ZOOM_DELETE_MEETING_URL: https://${HOST_NAME:-localhost}/v1/functions/zoom-meeting/delZoomMeet/delete-zoom-meet-auth
NEXT_PUBLIC_ZOOM_OAUTH_START_URL: https://${HOST_NAME:-localhost}/zoom/oauth-start
NEXT_PUBLIC_LIVE_MEETING_WORKER_URL: http://live-meeting-worker:8001
container_name: app
depends_on:
- supertokens
- live-meeting-worker # Add dependency if app should wait for worker
labels:
- "traefik.enable=true"
# HTTP router for app (redirects to HTTPS)
- "traefik.http.routers.app-http.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/`)"
- "traefik.http.routers.app-http.entrypoints=web"
- "traefik.http.routers.app-http.middlewares=https-redirect@docker" # Apply global redirect
# HTTPS router for app
- "traefik.http.routers.app-https.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/`)"
- "traefik.http.routers.app-https.entrypoints=websecure"
- "traefik.http.routers.app-https.tls=true"
- "traefik.http.routers.app-https.tls.certresolver=le"
- "traefik.http.routers.app-https.service=app-service" # Explicit service name
- "traefik.http.services.app-service.loadbalancer.server.port=3000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/"] # Check root path
interval: 30s
timeout: 10s
retries: 3
start_period: 45s # Next.js apps can take a bit to start
ports:
- "3000:3000"
# Add NEXT_PUBLIC_LIVE_MEETING_WORKER_URL to environment or build args
# If it's passed during build time via build args:
# build:
# context: ../app_build_docker
# args:
# # ... other args
# NEXT_PUBLIC_LIVE_MEETING_WORKER_URL: http://live-meeting-worker:8001
# If it's passed as a runtime environment variable (more common for URLs):
environment:
# ... (ensure all existing environment variables for 'app' are maintained)
# Example of how it might be structured if environment is already used:
# EXISTING_ENV_VAR: ${EXISTING_ENV_VAR}
NEXT_PUBLIC_LIVE_MEETING_WORKER_URL: http://live-meeting-worker:8001
# PYTHON_API_SERVICE_BASE_URL: ${PYTHON_API_SERVICE_BASE_URL:-http://python-agent:5000} # Removed: python-agent service deprecated
# The existing 'app' service definition is complex with many build args.
# Need to be careful to merge this correctly.
# Based on the structure, build args are used. So I will add it there.
# python-agent:
# NOTE: Service removed - python_agent_build_docker directory deleted (2025-02-03)
# Reason: Duplicate functionality exists in backend/integrations/
# - Notion integration: backend/integrations/notion_service.py
# - Deepgram integration: backend/integrations/deepgram_service.py
# - All other services have real implementations
# This service contained placeholder Celery tasks that returned "method": "placeholder"
# To restore this service, uncomment the following and restore python_agent_build_docker directory
# python-agent:
# build:
# context: ../python_agent_build_docker
# dockerfile: Dockerfile
# container_name: python-agent
# depends_on:
# - postgres
# environment:
# - NOTION_API_TOKEN=${NOTION_API_TOKEN:-default_notion_token}
# - NOTION_NOTES_DATABASE_ID=${NOTION_NOTES_DATABASE_ID:-default_notes_db_id}
# - DEEPGRAM_API_KEY=${DEEPGRAM_API_KEY:-default_deepgram_key}
# - NOTION_RESEARCH_PROJECTS_DB_ID=${NOTION_RESEARCH_PROJECTS_DB_ID:-default_research_projects_db_id}
# - NOTION_RESEARCH_TASKS_DB_ID=${NOTION_RESEARCH_TASKS_DB_ID:-default_research_tasks_db_id}
# - OPENAI_API_KEY=${OPENAI_API_KEY:-sk-default-openai-key}
# - LANCEDB_URI=/lancedb_data/atom_core_db
# - LANCEDB_TABLE_NAME=${LANCEDB_TABLE_NAME:-meeting_transcripts_embeddings}
# - PYTHONUNBUFFERED=1
# volumes:
# - .:/app/project
# - ${LANCEDB_HOST_PATH:-./lance_db_data_shared}:/lancedb_data
# tty: true
# stdin_open: true
ingestion-pipeline-service:
build:
context: ../python-api/ingestion_pipeline
dockerfile: Dockerfile
container_name: ingestion-pipeline-service
restart: unless-stopped
depends_on:
- functions # Example dependency, adjust as needed
environment:
- NOTION_API_KEY=${NOTION_API_KEY}
- NOTION_TRANSCRIPTS_DATABASE_ID=${NOTION_TRANSCRIPTS_DATABASE_ID}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- LANCEDB_URI=/lancedb_data/atom_core_db # Points to the mounted volume + DB name
- ATOM_USER_ID_FOR_INGESTION=${ATOM_USER_ID_FOR_INGESTION:-default_atom_user_pipeline}
- PROCESSING_MODE=${PROCESSING_MODE:-incremental}
- LOG_LEVEL=${LOG_LEVEL:-INFO}
- PYTHONUNBUFFERED=1
volumes:
# Mount the shared LanceDB data volume
- ${LANCEDB_HOST_PATH:-./lance_db_data_shared}:/lancedb_data
ports:
- "8002:8002" # Expose for triggering, can be removed if triggered internally
healthcheck:
test:
[
"CMD-SHELL",
"curl -f http://localhost:8002/ingestion-status || exit 1",
]
interval: 60s
timeout: 10s
retries: 3
start_period: 60s
redis:
image: "redis:alpine"
container_name: redis
expose:
- 6379
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 1s
timeout: 3s
retries: 30
celery-worker:
build:
context: ../python_agent_build_docker
dockerfile: Dockerfile
container_name: celery-worker
command: celery -A project.celery_app worker --loglevel=info
volumes:
- .:/app/project
- ${LANCEDB_HOST_PATH:-./lance_db_data_shared}:/lancedb_data
depends_on:
- redis
- postgres
environment:
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-secretpgpassword}@postgres:5432/postgres
- NOTION_API_TOKEN=${NOTION_API_TOKEN:-default_notion_token}
- NOTION_NOTES_DATABASE_ID=${NOTION_NOTES_DATABASE_ID:-default_notes_db_id}
- DEEPGRAM_API_KEY=${DEEPGRAM_API_KEY:-default_deepgram_key}
- NOTION_RESEARCH_PROJECTS_DB_ID=${NOTION_RESEARCH_PROJECTS_DB_ID:-default_research_projects_db_id}
- NOTION_RESEARCH_TASKS_DB_ID=${NOTION_RESEARCH_TASKS_DB_ID:-default_research_tasks_db_id}
- OPENAI_API_KEY=${OPENAI_API_KEY:-sk-default-openai-key}
- LANCEDB_URI=/lancedb_data/atom_core_db
- LANCEDB_TABLE_NAME=${LANCEDB_TABLE_NAME:-meeting_transcripts_embeddings}
- PYTHONUNBUFFERED=1
# celery-worker:
# NOTE: Service removed - python_agent_build_docker directory deleted (2025-02-03)
# Celery background tasks with placeholder implementations (Slack, Email, Asana all returned "method": "placeholder")
# Real implementations exist in backend/integrations/
# To restore, uncomment and restore python_agent_build_docker directory
# celery-worker:
# build:
# context: ../python_agent_build_docker
# dockerfile: Dockerfile
# container_name: celery-worker
# command: celery -A project.celery_app worker --loglevel=info
# volumes:
# - .:/app/project
# - ${LANCEDB_HOST_PATH:-./lance_db_data_shared}:/lancedb_data
# depends_on:
# - redis
# - postgres
# environment:
# - CELERY_BROKER_URL=redis://redis:6379/0
# - CELERY_RESULT_BACKEND=redis://redis:6379/0
# - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-secretpgpassword}@postgres:5432/postgres
# - NOTION_API_TOKEN=${NOTION_API_TOKEN:-default_notion_token}
# - NOTION_NOTES_DATABASE_ID=${NOTION_NOTES_DATABASE_ID:-default_notes_db_id}
# - DEEPGRAM_API_KEY=${DEEPGRAM_API_KEY:-default_deepgram_key}
# - NOTION_RESEARCH_PROJECTS_DB_ID=${NOTION_RESEARCH_PROJECTS_DB_ID:-default_research_projects_db_id}
# - NOTION_RESEARCH_TASKS_DB_ID=${NOTION_RESEARCH_TASKS_DB_ID:-default_research_tasks_db_id}
# - OPENAI_API_KEY=${OPENAI_API_KEY:-sk-default-openai-key}
# - LANCEDB_URI=/lancedb_data/atom_core_db
# - LANCEDB_TABLE_NAME=${LANCEDB_TABLE_NAME:-meeting_transcripts_embeddings}
# - PYTHONUNBUFFERED=1
# celery-beat:
# NOTE: Service removed - python_agent_build_docker directory deleted (2025-02-03)
# Celery beat scheduler for placeholder background tasks
# To restore, uncomment and restore python_agent_build_docker directory
# celery-beat:
# build:
# context: ../python_agent_build_docker
# dockerfile: Dockerfile
# container_name: celery-beat
# command: celery -A project.celery_app beat --loglevel=info
# volumes:
# - .:/app/project
# depends_on:
# - redis
# - postgres
# environment:
# - CELERY_BROKER_URL=redis://redis:6379/0
# - CELERY_RESULT_BACKEND=redis://redis:6379/0
# - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD:-secretpgpassword}@postgres:5432/postgres
workflows-api:
build:
context: ../python-api/workflows
dockerfile: Dockerfile
container_name: workflows-api
restart: unless-stopped
depends_on:
- postgres
- redis
environment:
- DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres
- CELERY_BROKER_URL=redis://redis:6379/0
- CELERY_RESULT_BACKEND=redis://redis:6379/0
- OPENAI_API_KEY=${OPENAI_API_KEY}
- NOTION_API_KEY=${NOTION_API_KEY}
ports:
- "8003:8003"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8003/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
labels:
- "traefik.enable=true"
- "traefik.http.middlewares.strip-workflows-api.stripprefix.prefixes=/api/workflows"
- "traefik.http.routers.workflows-api-http.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/api/workflows`)"
- "traefik.http.routers.workflows-api-http.entrypoints=web"
- "traefik.http.routers.workflows-api-http.middlewares=strip-workflows-api@docker,https-redirect@docker"
- "traefik.http.routers.workflows-api-https.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/api/workflows`)"
- "traefik.http.routers.workflows-api-https.entrypoints=websecure"
- "traefik.http.routers.workflows-api-https.tls=true"
- "traefik.http.routers.workflows-api-https.tls.certresolver=le"
- "traefik.http.routers.workflows-api-https.middlewares=strip-workflows-api@docker"
- "traefik.http.routers.workflows-api-https.service=workflows-api-service"
- "traefik.http.services.workflows-api-service.loadbalancer.server.port=8003"
dropbox-api:
build:
context: ../python-api/dropbox_service
dockerfile: Dockerfile
container_name: dropbox-api
restart: unless-stopped
ports:
- "5001:5001"
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:5001/ || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
labels:
- "traefik.enable=true"
- "traefik.http.routers.dropbox-api.rule=Host(`${HOST_NAME:-localhost}`) && PathPrefix(`/api/dropbox`)"
- "traefik.http.routers.dropbox-api.entrypoints=websecure"
- "traefik.http.routers.dropbox-api.tls=true"
- "traefik.http.routers.dropbox-api.tls.certresolver=le"
- "traefik.http.services.dropbox-api.loadbalancer.server.port=5001"
volumes:
project_node_modules:
functions_node_modules: