docker-compose.yml 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. services:
  2. odysseus:
  3. build: ./repo
  4. ports:
  5. - "${APP_BIND:-0.0.0.0}:${APP_PORT:-3004}:7000"
  6. volumes:
  7. - /var/run/docker.sock:/var/run/docker.sock:ro
  8. - ${APP_DATA_DIR:-/data/docker/odysseus/data}:/app/data:z
  9. - ${APP_LOGS_DIR:-/data/docker/odysseus/logs}:/app/logs:z
  10. - ${APP_DATA_DIR:-/data/docker/odysseus/data}/ssh:/app/.ssh:z
  11. - ${APP_DATA_DIR:-/data/docker/odysseus/data}/huggingface:/app/.cache/huggingface:z
  12. - ${APP_DATA_DIR:-/data/docker/odysseus/data}/local:/app/.local:z
  13. - /etc/localtime:/etc/localtime:ro
  14. extra_hosts:
  15. - "host.docker.internal:host-gateway"
  16. environment:
  17. - TZ=Europe/Tallinn
  18. - LLM_HOST=${LLM_HOST:-localhost}
  19. - LLM_HOSTS=${LLM_HOSTS:-http://host.docker.internal:11434,http://host.docker.internal:8070}
  20. - OLLAMA_BASE_URL=${OLLAMA_BASE_URL:-http://host.docker.internal:11434}
  21. - EMBEDDING_URL=${EMBEDDING_URL:-http://host.docker.internal:11434/v1/embeddings}
  22. - EMBEDDING_MODEL=${EMBEDDING_MODEL:-nomic-embed-text}
  23. - SEARXNG_INSTANCE=http://searxng:8080
  24. - CHROMADB_HOST=chromadb
  25. - CHROMADB_PORT=8000
  26. - DATABASE_URL=${DATABASE_URL:-sqlite:///./data/app.db}
  27. - AUTH_ENABLED=${AUTH_ENABLED:-true}
  28. - LOCALHOST_BYPASS=${LOCALHOST_BYPASS:-false}
  29. - ODYSSEUS_ADMIN_USER=${ODYSSEUS_ADMIN_USER:-admin}
  30. - ODYSSEUS_ADMIN_PASSWORD=${ODYSSEUS_ADMIN_PASSWORD:-}
  31. - ALLOWED_ORIGINS=${ALLOWED_ORIGINS:-http://localhost,http://127.0.0.1}
  32. - SECURE_COOKIES=${SECURE_COOKIES:-false}
  33. - FASTEMBED_MODEL=${FASTEMBED_MODEL:-sentence-transformers/all-MiniLM-L6-v2}
  34. - CLEANUP_INTERVAL_HOURS=${CLEANUP_INTERVAL_HOURS:-24}
  35. - BACKGROUND_TASK_FOREGROUND_GATE=false
  36. - ODYSSEUS_ENABLE_HOST_DOCKER=true
  37. - ODYSSEUS_CHAT_UPLOAD_MAX_BYTES=${ODYSSEUS_CHAT_UPLOAD_MAX_BYTES:-10485760}
  38. - ODYSSEUS_GALLERY_UPLOAD_MAX_BYTES=${ODYSSEUS_GALLERY_UPLOAD_MAX_BYTES:-104857600}
  39. - PUID=${PUID:-1000}
  40. - PGID=${PGID:-1000}
  41. devices:
  42. - /dev/kfd
  43. - /dev/dri
  44. group_add:
  45. - video
  46. - "122" # docker group
  47. - ${RENDER_GID:-render}
  48. depends_on:
  49. searxng:
  50. condition: service_healthy
  51. chromadb:
  52. condition: service_started
  53. networks:
  54. - main_ai_network
  55. restart: unless-stopped
  56. chromadb:
  57. image: docker.io/chromadb/chroma:latest
  58. ports:
  59. - "127.0.0.1:8100:8000"
  60. volumes:
  61. - /etc/localtime:/etc/localtime:ro
  62. - chromadb-data:/chroma/chroma
  63. environment:
  64. - TZ=Europe/Tallinn
  65. - ANONYMIZED_TELEMETRY=FALSE
  66. networks:
  67. - main_ai_network
  68. restart: unless-stopped
  69. searxng:
  70. image: docker.io/searxng/searxng:2026.5.31-7159b8aed
  71. entrypoint:
  72. - /bin/sh
  73. - -c
  74. - |
  75. set -eu
  76. if [ ! -s /etc/searxng/settings.yml ] || grep -q 'odysseus-local-searxng-json-2026-05-30\|__SEARXNG_SECRET__' /etc/searxng/settings.yml; then
  77. secret="$${SEARXNG_SECRET:-}"
  78. if [ -z "$$secret" ]; then
  79. secret="$$(python -c 'import secrets; print(secrets.token_urlsafe(48))')"
  80. fi
  81. sed "s|__SEARXNG_SECRET__|$$secret|g" /tmp/searxng-settings.yml.template > /etc/searxng/settings.yml
  82. fi
  83. exec /usr/local/searxng/entrypoint.sh
  84. ports:
  85. - "127.0.0.1:8088:8080"
  86. volumes:
  87. - /etc/localtime:/etc/localtime:ro
  88. - searxng-data:/etc/searxng
  89. - ./repo/config/searxng/settings.yml:/tmp/searxng-settings.yml.template:ro,z
  90. environment:
  91. - TZ=Europe/Tallinn
  92. - SEARXNG_BASE_URL=http://localhost:8080/
  93. cap_drop:
  94. - ALL
  95. cap_add:
  96. - CHOWN
  97. - SETGID
  98. - SETUID
  99. - DAC_OVERRIDE
  100. healthcheck:
  101. test: ["CMD-SHELL", "python -c \"import urllib.request; urllib.request.urlopen('http://localhost:8080/', timeout=5).read(1)\""]
  102. interval: 5s
  103. timeout: 6s
  104. retries: 20
  105. start_period: 10s
  106. networks:
  107. - main_ai_network
  108. restart: unless-stopped
  109. ntfy:
  110. image: docker.io/binwiederhier/ntfy
  111. command: serve
  112. ports:
  113. - "127.0.0.1:8091:80"
  114. volumes:
  115. - /etc/localtime:/etc/localtime:ro
  116. - ntfy-cache:/var/cache/ntfy
  117. - ./ntfy/server.yml:/etc/ntfy/server.yml:ro
  118. - ./ntfy/data:/var/lib/ntfy
  119. environment:
  120. - TZ=Europe/Tallinn
  121. - NTFY_BASE_URL=https://ohmu.tail20e23.ts.net:8091
  122. networks:
  123. - main_ai_network
  124. restart: unless-stopped
  125. volumes:
  126. searxng-data:
  127. chromadb-data:
  128. ntfy-cache:
  129. networks:
  130. main_ai_network:
  131. external: true
  132. name: main_ai_network