docker-compose.yml 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. services:
  2. qdrant:
  3. image: qdrant/qdrant:latest
  4. container_name: modulos-qdrant
  5. ports:
  6. - "6333:6333"
  7. - "6334:6334"
  8. volumes:
  9. - ./qdrant_storage:/qdrant/storage
  10. restart: unless-stopped
  11. healthcheck:
  12. test:
  13. [
  14. "CMD-SHELL",
  15. "if command -v curl >/dev/null 2>&1; then curl -fsS http://localhost:6333/readyz >/dev/null; \
  16. elif command -v wget >/dev/null 2>&1; then wget -qO- http://localhost:6333/readyz >/dev/null; \
  17. else bash -lc \"exec 3<>/dev/tcp/127.0.0.1/6333; printf 'GET /readyz HTTP/1.0\\r\\n\\r\\n' >&3; head -n1 <&3 | grep -q '200'\"; fi"
  18. ]
  19. interval: 20s
  20. timeout: 5s
  21. retries: 5
  22. backend:
  23. build: ./backend
  24. container_name: modulos-backend
  25. ports:
  26. - "2281:8000"
  27. command: >
  28. bash -lc '
  29. set -euo pipefail;
  30. exec uvicorn app:app --host 0.0.0.0 --port 8000
  31. '
  32. user: "10001:10001" # run as appuser at runtime
  33. environment:
  34. # point to your Windows Ollama box
  35. - OLLAMA_URL=http://192.168.8.73:11434
  36. # talk to qdrant inside this compose
  37. - QDRANT_URL=http://qdrant:6333
  38. # defaults for collection/models (override if you like)
  39. - QDRANT_COLLECTION=planning_docs
  40. - EMBED_MODEL=nomic-embed-text
  41. - CHAT_MODEL=llama3.1:8b-instruct-q5_K_M
  42. #- CHAT_MODEL=llama3.1:8b
  43. # optional CORS, comma-separated list
  44. - CORS_ORIGINS=http://localhost:3000,http://192.168.8.69:2380,https://llm.modulos.com.au,https://api.modulos.com.au,https://tasplanning.report
  45. # Optional demo gate:
  46. - DEMO_REQUIRE_TOKEN=0
  47. - DEMO_TOKEN=DHv2xUx7vWzGg3O8UihDbUVQ7Svrub1FJXHv2Y3jyOTRrOTO19cLytm3b8Y8A6eC
  48. - TPR_DB=/data/telemetry.db
  49. - TPR_IP_SECRET=${TPR_IP_SECRET:-mmOwQgqljUs1CPiKW3O9vvL4XGalAHojOEmB7SJLBxXBPXHbBoDCMyS8fPc62aDk}
  50. depends_on:
  51. qdrant:
  52. condition: service_healthy
  53. volumes:
  54. - ./backend:/app
  55. - /home/modulos_llm/telemetry_data:/data
  56. restart: unless-stopped
  57. healthcheck:
  58. test: ["CMD", "curl", "-f", "http://localhost:8000/readyz"]
  59. interval: 20s
  60. timeout: 3s
  61. retries: 5
  62. web:
  63. build:
  64. context: .
  65. dockerfile: ./web/Dockerfile
  66. container_name: modulos-web
  67. ports:
  68. - "2380:80"
  69. volumes:
  70. - ./public:/var/www/html
  71. - cache:/var/www/html/cache
  72. - /home/modulos_llm/telemetry_data:/data
  73. environment:
  74. - TPR_DB=/data/telemetry.db
  75. - DEBIAN_FRONTEND=noninteractive
  76. - GOOGLE_APPLICATION_CREDENTIALS=/var/www/secure/service-account.json
  77. - GDOC_PARENT_ID=1Zkv6eThu-3szvRpug3fXiAuTDWLsWxxl
  78. - GDOC_SHARE_EMAIL=modulos.aust@gmail.com
  79. - GMAPS_API_KEY=${GMAPS_API_KEY}
  80. - SMTP_HOST=mail.modulos.com.au
  81. - SMTP_PORT=465
  82. - SMTP_USER=no-reply@modulos.com.au
  83. - SMTP_PASS=${SMTP_PASS}
  84. - SMTP_FROM=no-reply@modulos.com.au
  85. - SMTP_FROM_NAME=Tas Planning Assistant
  86. - NOTIFY_EMAIL=ben@modulos.com.au
  87. - APP_API_BASE=https://api.modulos.com.au/ask
  88. depends_on:
  89. - backend
  90. restart: unless-stopped
  91. command: >
  92. bash -lc '
  93. set -euo pipefail;
  94. apt-get update -y;
  95. apt-get install -y --no-install-recommends git unzip libzip-dev netcat-openbsd;
  96. rm -rf /var/lib/apt/lists/*;
  97. a2enmod rewrite headers >/dev/null || true;
  98. # Only build zip if not loaded
  99. php -m | grep -qi "^zip$" || docker-php-ext-install zip;
  100. # Write clean confs (printf avoids YAML here-doc pitfalls)
  101. printf "%s\n" "<Directory \"/var/www/html\">" \
  102. " AllowOverride All" \
  103. " Require all granted" \
  104. "</Directory>" \
  105. > /etc/apache2/conf-enabled/allowoverride.conf
  106. printf "%s\n" "SetEnvIfNoCase X-Forwarded-Proto ^https$ HTTPS=on" \
  107. > /etc/apache2/conf-enabled/proxy-https.conf
  108. # Extra: set HTTPS via mod_rewrite for libs reading env later
  109. printf "%s\n" "RewriteEngine On" \
  110. "RewriteCond %{HTTP:X-Forwarded-Proto} =https" \
  111. "RewriteRule .* - [E=HTTPS:on]" \
  112. > /etc/apache2/conf-enabled/rewrite-https.conf
  113. printf "ServerName localhost\n" > /etc/apache2/conf-enabled/servername.conf
  114. printf "PassEnv GMAPS_API_KEY\n" > /etc/apache2/conf-enabled/passenv.conf;
  115. chown -R www-data:www-data /var/www/html/cache || true;
  116. apachectl -t;
  117. exec apache2-foreground
  118. '
  119. sqliteweb:
  120. image: coleifer/sqlite-web:latest
  121. container_name: modulos-sqliteweb
  122. depends_on:
  123. - backend
  124. user: "10001:10001"
  125. volumes:
  126. - /home/modulos_llm/telemetry_data:/data # same volume the backend uses
  127. # external: true
  128. environment:
  129. - SQLITE_DATABASE=telemetry.db # looks for /data/telemetry.db
  130. # optional: protect with a password
  131. # - SQLITE_WEB_PASSWORD=${SQLITE_WEB_PASSWORD:-}
  132. ports:
  133. - "8091:8080"
  134. restart: unless-stopped
  135. composer:
  136. build:
  137. context: .
  138. dockerfile: ./web/Dockerfile
  139. working_dir: /app
  140. volumes:
  141. - ./public:/app
  142. # external: true
  143. command: ["composer", "install", "--no-interaction", "--no-progress", "--prefer-dist"]
  144. restart: unless-stopped
  145. depends_on:
  146. - web
  147. volumes:
  148. cache:
  149. external: true
  150. name: modulos_llm_cache
  151. telemetry_data: {}