services: backend: build: ./backend #custom container, must contine its own Dockerfile container_name: alpha-backend ports: - "8000:8000" volumes: - ./backend:/app depends_on: postgres: condition: service_healthy #backend waits for db, basically starts only when the postgres is ready to accept connection opensearch: condition: service_healthy redis: condition: service_healthy environment: - DATABASE_URL=postgresql://admin:admin@postgres:5432/alpha - OPENSEARCH_HOST=http://opensearch:9200 - GROQ_API_KEY=${GROQ_API_KEY} - REDIS_URL=redis://redis:6379 - LANGCHAIN_API_KEY=${LANGCHAIN_API_KEY} - LANGCHAIN_TRACING_V2=true - LANGCHAIN_PROJECT=alphasignal env_file: - .env postgres: image: postgres:16 #prebuilt image container_name: alpha-postgres environment: #hardcoded the creds right now but in production we will use envs POSTGRES_USER: admin POSTGRES_PASSWORD: admin POSTGRES_DB: alpha env_file: - .env ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data #db wont reset on restart - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql #this will run the init.sql script when the container starts, allowing us to set up our database schema and initial data automatically healthcheck: test: ["CMD-SHELL", "pg_isready -U admin -d alpha"] interval: 5s timeout: 5s retries: 5 opensearch: image: opensearchproject/opensearch:2.11.0 #prebuilt image container_name: alpha-opensearch environment: - discovery.type=single-node - plugins.security.disabled=true - OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m env_file: - .env ports: - "9200:9200" volumes: - opensearch_data:/usr/share/opensearch/data healthcheck: test: ["CMD-SHELL", "curl -f http://localhost:9200/_cluster/health || exit 1"] interval: 10s timeout: 5s retries: 5 airflow-init: #just a one time setup container build: ./airflow #custom image, must contain its own Dockerfile. because we need dependencies like psycopg2 and yfinance container_name: alpha-airflow-init depends_on: postgres: condition: service_healthy environment: - AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=postgresql+psycopg2://admin:admin@postgres:5432/airflow - AIRFLOW__CORE__FERNET_KEY=${AIRFLOW__CORE__FERNET_KEY} #takes the encryption key from the .env - AIRFLOW__CORE__LOAD_EXAMPLES=false #prevents lame demos env_file: - .env command: bash -c "airflow db migrate && airflow users create -u admin -p admin -f Alpha -l Signal -r Admin -e admin@alphasignal.com" restart: on-failure airflow-webserver: build: ./airflow container_name: alpha-airflow-webserver depends_on: postgres: condition: service_healthy airflow-init: condition: service_completed_successfully ports: - "8080:8080" volumes: - ./airflow/dags:/opt/airflow/dags - airflow_logs:/opt/airflow/logs environment: - AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=postgresql+psycopg2://admin:admin@postgres:5432/airflow - AIRFLOW__CORE__FERNET_KEY=${AIRFLOW__CORE__FERNET_KEY} - AIRFLOW__CORE__LOAD_EXAMPLES=false - AIRFLOW__API__AUTH_BACKENDS=airflow.api.auth.backend.basic_auth - AIRFLOW__WEBSERVER__SECRET_KEY=${AIRFLOW__CORE__FERNET_KEY} env_file: - .env command: webserver restart: unless-stopped airflow-scheduler: build: ./airflow container_name: alpha-airflow-scheduler depends_on: postgres: condition: service_healthy airflow-init: condition: service_completed_successfully volumes: - ./airflow/dags:/opt/airflow/dags - airflow_logs:/opt/airflow/logs environment: - AIRFLOW__DATABASE__SQL_ALCHEMY_CONN=postgresql+psycopg2://admin:admin@postgres:5432/airflow - AIRFLOW__CORE__FERNET_KEY=${AIRFLOW__CORE__FERNET_KEY} - AIRFLOW__CORE__LOAD_EXAMPLES=false - AIRFLOW__API__AUTH_BACKENDS=airflow.api.auth.backend.basic_auth env_file: - .env command: scheduler restart: unless-stopped telegram-poller: build: ./airflow container_name: alpha-telegram-poller depends_on: airflow-webserver: condition: service_started airflow-scheduler: condition: service_started backend: condition: service_started environment: - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID} - BACKEND_URL=http://backend:8000 - AIRFLOW_API_URL=http://airflow-webserver:8080/api/v1 - AIRFLOW_API_USER=admin - AIRFLOW_API_PASS=admin - GROQ_API_KEY=${GROQ_API_KEY} env_file: - .env volumes: - ./airflow/dags:/opt/airflow/dags - airflow_logs:/opt/airflow/logs command: python /opt/airflow/dags/telegram_agent.py --poll restart: unless-stopped redis: image: redis/redis-stack-server:latest container_name: alpha-redis ports: - "6379:6379" volumes: - redis_data:/data healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s timeout: 3s retries: 5 volumes: postgres_data: opensearch_data: airflow_logs: redis_data: