services: postgres: image: postgres:16-alpine container_name: cert-study-postgres environment: POSTGRES_DB: ${POSTGRES_DB:-cert_study} POSTGRES_USER: ${POSTGRES_USER:-cert_study} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-cert_study} ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-cert_study} -d ${POSTGRES_DB:-cert_study}"] interval: 5s timeout: 5s retries: 20 restart: unless-stopped cert-study-app: build: context: . container_name: cert-study-app depends_on: postgres: condition: service_healthy ports: - "8501:8501" environment: STREAMLIT_SERVER_ADDRESS: 0.0.0.0 STREAMLIT_SERVER_PORT: 8501 STREAMLIT_BROWSER_GATHER_USAGE_STATS: "false" CERT_STUDY_LLM_PROVIDER: ${CERT_STUDY_LLM_PROVIDER:-ollama} OLLAMA_MODEL: ${OLLAMA_MODEL:-qwen2.5:14b} OLLAMA_FAST_MODEL: ${OLLAMA_FAST_MODEL:-qwen3.5:9b} OLLAMA_VISUAL_MODEL: ${OLLAMA_VISUAL_MODEL:-qwen3-vl:8b-instruct-q4_K_M} EMBEDDING_MODEL: ${EMBEDDING_MODEL:-BAAI/bge-m3} OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://host.docker.internal:11434} DATABASE_URL: ${DATABASE_URL:-postgresql+pg8000://cert_study:cert_study@postgres:5432/cert_study} AIRFLOW_API_BASE_URL: ${AIRFLOW_API_BASE_URL:-http://host.docker.internal:8080} AIRFLOW_API_USERNAME: ${AIRFLOW_API_USERNAME:-admin} AIRFLOW_API_PASSWORD: ${AIRFLOW_API_PASSWORD:-admin} volumes: - ./data:/app/data - ./chroma_db:/app/chroma_db - ./instance:/app/instance restart: unless-stopped airflow-init: build: context: . dockerfile: Dockerfile.airflow container_name: cert-study-airflow-init depends_on: postgres: condition: service_healthy entrypoint: /bin/bash command: - -c - airflow db migrate && airflow users create --username "$${AIRFLOW_ADMIN_USERNAME:-admin}" --password "$${AIRFLOW_ADMIN_PASSWORD:-admin}" --firstname Cert --lastname Study --role Admin --email "$${AIRFLOW_ADMIN_EMAIL:-admin@example.com}" || true environment: &airflow-env AIRFLOW__CORE__EXECUTOR: SequentialExecutor AIRFLOW__CORE__LOAD_EXAMPLES: "false" AIRFLOW__CORE__DAGS_ARE_PAUSED_AT_CREATION: "false" AIRFLOW__DATABASE__SQL_ALCHEMY_CONN: sqlite:////opt/airflow_db/airflow.db AIRFLOW__API__AUTH_BACKENDS: airflow.api.auth.backend.basic_auth CERT_STUDY_LLM_PROVIDER: ${CERT_STUDY_LLM_PROVIDER:-ollama} OLLAMA_MODEL: ${OLLAMA_MODEL:-qwen2.5:14b} OLLAMA_FAST_MODEL: ${OLLAMA_FAST_MODEL:-qwen3.5:9b} OLLAMA_VISUAL_MODEL: ${OLLAMA_VISUAL_MODEL:-qwen3-vl:8b-instruct-q4_K_M} EMBEDDING_MODEL: ${EMBEDDING_MODEL:-BAAI/bge-m3} OLLAMA_BASE_URL: ${OLLAMA_BASE_URL:-http://host.docker.internal:11434} DATABASE_URL: ${DATABASE_URL:-postgresql+pg8000://cert_study:cert_study@postgres:5432/cert_study} AIRFLOW_ADMIN_USERNAME: ${AIRFLOW_ADMIN_USERNAME:-admin} AIRFLOW_ADMIN_PASSWORD: ${AIRFLOW_ADMIN_PASSWORD:-admin} AIRFLOW_ADMIN_EMAIL: ${AIRFLOW_ADMIN_EMAIL:-admin@example.com} PYTHONPATH: /opt/airflow volumes: &airflow-volumes - ./dags:/opt/airflow/dags - ./cert_study_app:/opt/airflow/cert_study_app - ./data:/opt/airflow/data - ./chroma_db:/opt/airflow/chroma_db - ./airflow_logs:/opt/airflow/logs - ./airflow_db:/opt/airflow_db airflow-webserver: build: context: . dockerfile: Dockerfile.airflow container_name: cert-study-airflow-webserver depends_on: airflow-init: condition: service_started postgres: condition: service_healthy command: webserver ports: - "8080:8080" environment: *airflow-env volumes: *airflow-volumes restart: unless-stopped airflow-scheduler: build: context: . dockerfile: Dockerfile.airflow container_name: cert-study-airflow-scheduler depends_on: airflow-init: condition: service_started postgres: condition: service_healthy command: scheduler environment: *airflow-env volumes: *airflow-volumes restart: unless-stopped volumes: postgres_data: