mirror of
https://github.com/onyx-dot-app/onyx.git
synced 2026-10-22 03:14:06 -05:00
337 lines
12 KiB
YAML
337 lines
12 KiB
YAML
name: onyx
|
|
|
|
services:
|
|
api_server:
|
|
image: onyxdotapp/onyx-backend:${IMAGE_TAG:-latest}
|
|
build:
|
|
context: ../../backend
|
|
dockerfile: Dockerfile.cloud
|
|
command: >
|
|
/bin/sh -c "alembic -n schema_private upgrade head &&
|
|
echo \"Starting Onyx Api Server\" &&
|
|
uvicorn onyx.main:app --host 0.0.0.0 --port 8080"
|
|
depends_on:
|
|
- relational_db
|
|
- opensearch
|
|
- cache
|
|
- inference_model_server
|
|
- minio
|
|
restart: unless-stopped
|
|
environment:
|
|
- AUTH_TYPE=${AUTH_TYPE:-oidc}
|
|
- POSTGRES_HOST=relational_db
|
|
- OPENSEARCH_HOST=${OPENSEARCH_HOST:-opensearch}
|
|
- OPENSEARCH_ADMIN_PASSWORD=${OPENSEARCH_ADMIN_PASSWORD:-StrongPassword123!}
|
|
- REDIS_HOST=cache
|
|
- MODEL_SERVER_HOST=${MODEL_SERVER_HOST:-inference_model_server}
|
|
# MinIO configuration
|
|
- S3_ENDPOINT_URL=${S3_ENDPOINT_URL:-http://minio:9000}
|
|
- S3_AWS_ACCESS_KEY_ID=${S3_AWS_ACCESS_KEY_ID:?set a strong value in .env, not minioadmin}
|
|
- S3_AWS_SECRET_ACCESS_KEY=${S3_AWS_SECRET_ACCESS_KEY:?set a strong value in .env, not minioadmin}
|
|
env_file:
|
|
- path: .env
|
|
required: false
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
|
|
background:
|
|
image: onyxdotapp/onyx-backend:${IMAGE_TAG:-latest}
|
|
build:
|
|
context: ../../backend
|
|
dockerfile: Dockerfile
|
|
command: /app/scripts/supervisord_entrypoint.sh
|
|
depends_on:
|
|
- relational_db
|
|
- opensearch
|
|
- cache
|
|
- inference_model_server
|
|
- indexing_model_server
|
|
restart: unless-stopped
|
|
environment:
|
|
- AUTH_TYPE=${AUTH_TYPE:-oidc}
|
|
- POSTGRES_HOST=relational_db
|
|
- OPENSEARCH_HOST=${OPENSEARCH_HOST:-opensearch}
|
|
- OPENSEARCH_ADMIN_PASSWORD=${OPENSEARCH_ADMIN_PASSWORD:-StrongPassword123!}
|
|
- REDIS_HOST=cache
|
|
- MODEL_SERVER_HOST=${MODEL_SERVER_HOST:-inference_model_server}
|
|
- INDEXING_MODEL_SERVER_HOST=${INDEXING_MODEL_SERVER_HOST:-indexing_model_server}
|
|
# MinIO configuration
|
|
- S3_ENDPOINT_URL=${S3_ENDPOINT_URL:-http://minio:9000}
|
|
- S3_AWS_ACCESS_KEY_ID=${S3_AWS_ACCESS_KEY_ID:?set a strong value in .env, not minioadmin}
|
|
- S3_AWS_SECRET_ACCESS_KEY=${S3_AWS_SECRET_ACCESS_KEY:?set a strong value in .env, not minioadmin}
|
|
- DISCORD_BOT_TOKEN=${DISCORD_BOT_TOKEN:-}
|
|
- DISCORD_BOT_INVOKE_CHAR=${DISCORD_BOT_INVOKE_CHAR:-!}
|
|
# API Server connection for Discord bot message processing
|
|
- API_SERVER_PROTOCOL=${API_SERVER_PROTOCOL:-http}
|
|
- API_SERVER_HOST=${API_SERVER_HOST:-api_server}
|
|
env_file:
|
|
- path: .env
|
|
required: false
|
|
extra_hosts:
|
|
- "host.docker.internal:host-gateway"
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
|
|
web_server:
|
|
image: onyxdotapp/onyx-web-server:${IMAGE_TAG:-latest}
|
|
build:
|
|
context: ../../web
|
|
dockerfile: Dockerfile
|
|
args:
|
|
- NEXT_PUBLIC_DISABLE_LOGOUT=${NEXT_PUBLIC_DISABLE_LOGOUT:-}
|
|
- NEXT_PUBLIC_THEME=${NEXT_PUBLIC_THEME:-}
|
|
- NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED=${NEXT_PUBLIC_FORGOT_PASSWORD_ENABLED:-}
|
|
depends_on:
|
|
- api_server
|
|
restart: unless-stopped
|
|
environment:
|
|
- INTERNAL_URL=http://api_server:8080
|
|
env_file:
|
|
- path: .env
|
|
required: false
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
|
|
# Uncomment the block below to enable the MCP server for Onyx.
|
|
# mcp_server:
|
|
# image: onyxdotapp/onyx-backend:${IMAGE_TAG:-latest}
|
|
# build:
|
|
# context: ../../backend
|
|
# dockerfile: Dockerfile
|
|
# command: >
|
|
# /bin/sh -c "if [ \"${MCP_SERVER_ENABLED:-}\" != \"True\" ] && [ \"${MCP_SERVER_ENABLED:-}\" != \"true\" ]; then
|
|
# echo 'MCP server is disabled (MCP_SERVER_ENABLED=false), skipping...';
|
|
# exit 0;
|
|
# else
|
|
# exec python -m onyx.mcp_server_main;
|
|
# fi"
|
|
# env_file:
|
|
# - path: .env
|
|
# required: false
|
|
# depends_on:
|
|
# - relational_db
|
|
# - cache
|
|
# restart: "no"
|
|
# environment:
|
|
# - POSTGRES_HOST=relational_db
|
|
# - REDIS_HOST=cache
|
|
# # MCP Server Configuration
|
|
# - MCP_SERVER_ENABLED=${MCP_SERVER_ENABLED:-false}
|
|
# - MCP_SERVER_PORT=${MCP_SERVER_PORT:-8090}
|
|
# - MCP_SERVER_CORS_ORIGINS=${MCP_SERVER_CORS_ORIGINS:-}
|
|
# - API_SERVER_PROTOCOL=${API_SERVER_PROTOCOL:-http}
|
|
# - API_SERVER_HOST=${API_SERVER_HOST:-api_server}
|
|
# extra_hosts:
|
|
# - "host.docker.internal:host-gateway"
|
|
# logging:
|
|
# driver: json-file
|
|
# options:
|
|
# max-size: "50m"
|
|
# max-file: "6"
|
|
# volumes:
|
|
# - mcp_server_logs:/var/log/onyx
|
|
|
|
relational_db:
|
|
image: postgres:15.2-alpine
|
|
shm_size: 1g
|
|
command: -c 'max_connections=250'
|
|
restart: unless-stopped
|
|
# POSTGRES_USER and POSTGRES_PASSWORD should be set in .env file
|
|
env_file:
|
|
- path: .env
|
|
required: false
|
|
volumes:
|
|
- db_volume:/var/lib/postgresql/data
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
|
|
inference_model_server:
|
|
image: onyxdotapp/onyx-model-server:${IMAGE_TAG:-latest}
|
|
build:
|
|
context: ../../backend
|
|
dockerfile: Dockerfile.model_server
|
|
command: >
|
|
/bin/sh -c "if [ \"${DISABLE_MODEL_SERVER:-}\" = \"True\" ] || [ \"${DISABLE_MODEL_SERVER:-}\" = \"true\" ]; then
|
|
echo 'Skipping service...';
|
|
exit 0;
|
|
else
|
|
exec uvicorn model_server.main:app --host 0.0.0.0 --port 9000;
|
|
fi"
|
|
restart: on-failure
|
|
environment:
|
|
- MIN_THREADS_ML_MODELS=${MIN_THREADS_ML_MODELS:-}
|
|
# Set to debug to get more fine-grained logs
|
|
- LOG_LEVEL=${LOG_LEVEL:-info}
|
|
volumes:
|
|
# Not necessary, this is just to reduce download time during startup
|
|
- model_cache_huggingface:/app/.cache/huggingface/
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
|
|
indexing_model_server:
|
|
image: onyxdotapp/onyx-model-server:${IMAGE_TAG:-latest}
|
|
build:
|
|
context: ../../backend
|
|
dockerfile: Dockerfile.model_server
|
|
command: >
|
|
/bin/sh -c "if [ \"${DISABLE_MODEL_SERVER:-}\" = \"True\" ] || [ \"${DISABLE_MODEL_SERVER:-}\" = \"true\" ]; then
|
|
echo 'Skipping service...';
|
|
exit 0;
|
|
else
|
|
exec uvicorn model_server.main:app --host 0.0.0.0 --port 9000;
|
|
fi"
|
|
restart: on-failure
|
|
environment:
|
|
- MIN_THREADS_ML_MODELS=${MIN_THREADS_ML_MODELS:-}
|
|
- INDEXING_ONLY=True
|
|
# Set to debug to get more fine-grained logs
|
|
- LOG_LEVEL=${LOG_LEVEL:-info}
|
|
- VESPA_SEARCHER_THREADS=${VESPA_SEARCHER_THREADS:-1}
|
|
volumes:
|
|
# Not necessary, this is just to reduce download time during startup
|
|
- indexing_huggingface_model_cache:/app/.cache/huggingface/
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
|
|
opensearch:
|
|
image: opensearchproject/opensearch:3.6.0
|
|
restart: unless-stopped
|
|
# OpenSearch is the search backend and is enabled by default. To run against
|
|
# an external OpenSearch instance, set OPENSEARCH_HOST in your env and
|
|
# remove this service from the compose file (or skip it via the service list
|
|
# when running `docker compose up`).
|
|
environment:
|
|
# We need discovery.type=single-node so that OpenSearch doesn't try
|
|
# forming a cluster and waiting for other nodes to become live.
|
|
- discovery.type=single-node
|
|
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_ADMIN_PASSWORD:-StrongPassword123!}
|
|
# This and the JVM config below come from the example in https://docs.opensearch.org/latest/install-and-configure/install-opensearch/docker/
|
|
# We do this to avoid unstable performance from page swaps.
|
|
- bootstrap.memory_lock=true # Disable JVM heap memory swapping.
|
|
# Java heap should be ~50% of memory limit. For now we assume a limit of
|
|
# 4g although in practice the container can request more than this.
|
|
# See https://opster.com/guides/opensearch/opensearch-basics/opensearch-heap-size-usage-and-jvm-garbage-collection/
|
|
# Xms is the starting size, Xmx is the maximum size. These should be the
|
|
# same.
|
|
- "OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g"
|
|
volumes:
|
|
- opensearch-data:/usr/share/opensearch/data
|
|
# These come from the example in https://docs.opensearch.org/latest/install-and-configure/install-opensearch/docker/
|
|
ulimits:
|
|
# Similarly to bootstrap.memory_lock, we don't want to impose limits on
|
|
# how much memory a process can lock from being swapped.
|
|
memlock:
|
|
soft: -1 # Set memlock to unlimited (no soft or hard limit).
|
|
hard: -1
|
|
nofile:
|
|
soft: 65536 # Maximum number of open files for the opensearch user - set to at least 65536.
|
|
hard: 65536
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
|
|
nginx:
|
|
image: nginx:1.25.5-alpine
|
|
restart: unless-stopped
|
|
# nginx will immediately crash with `nginx: [emerg] host not found in upstream`
|
|
# if api_server / web_server are not up
|
|
depends_on:
|
|
- api_server
|
|
- web_server
|
|
ports:
|
|
- "80:80"
|
|
- "443:443"
|
|
volumes:
|
|
- ../data/nginx:/nginx-templates:ro
|
|
- ../data/certbot/conf:/etc/letsencrypt
|
|
- ../data/certbot/www:/var/www/certbot
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
command: >
|
|
/bin/sh -c "rm -f /etc/nginx/conf.d/default.conf
|
|
&& cp -a /nginx-templates/. /etc/nginx/conf.d/
|
|
&& sed 's/\r$//' /etc/nginx/conf.d/run-nginx.sh > /tmp/run-nginx.sh
|
|
&& chmod +x /tmp/run-nginx.sh
|
|
&& /tmp/run-nginx.sh app.conf.template.prod"
|
|
env_file:
|
|
- .env.nginx
|
|
environment:
|
|
# Nginx proxy timeout settings (in seconds)
|
|
- NGINX_PROXY_CONNECT_TIMEOUT=${NGINX_PROXY_CONNECT_TIMEOUT:-300}
|
|
- NGINX_PROXY_SEND_TIMEOUT=${NGINX_PROXY_SEND_TIMEOUT:-300}
|
|
- NGINX_PROXY_READ_TIMEOUT=${NGINX_PROXY_READ_TIMEOUT:-300}
|
|
|
|
# follows https://pentacent.medium.com/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71
|
|
certbot:
|
|
image: certbot/certbot
|
|
restart: unless-stopped
|
|
volumes:
|
|
- ../data/certbot/conf:/etc/letsencrypt
|
|
- ../data/certbot/www:/var/www/certbot
|
|
logging:
|
|
driver: json-file
|
|
options:
|
|
max-size: "50m"
|
|
max-file: "6"
|
|
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"
|
|
|
|
minio:
|
|
image: minio/minio:RELEASE.2025-07-23T15-54-02Z-cpuv1
|
|
restart: unless-stopped
|
|
environment:
|
|
MINIO_ROOT_USER: ${MINIO_ROOT_USER:?set a strong value in .env, not minioadmin}
|
|
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?set a strong value in .env, not minioadmin}
|
|
MINIO_DEFAULT_BUCKETS: ${S3_FILE_STORE_BUCKET_NAME:-onyx-file-store-bucket}
|
|
volumes:
|
|
- minio_data:/data
|
|
command: server /data --console-address ":9001"
|
|
healthcheck:
|
|
test: ["CMD", "mc", "ready", "local"]
|
|
interval: 30s
|
|
timeout: 20s
|
|
retries: 3
|
|
|
|
cache:
|
|
image: redis:7.4-alpine
|
|
restart: unless-stopped
|
|
# docker silently mounts /data even without an explicit volume mount, which enables
|
|
# persistence. explicitly setting save and appendonly forces ephemeral behavior.
|
|
command: redis-server --save "" --appendonly no
|
|
# Use tmpfs to prevent creation of anonymous volumes for /data
|
|
tmpfs:
|
|
- /data
|
|
|
|
volumes:
|
|
db_volume:
|
|
minio_data:
|
|
model_cache_huggingface:
|
|
indexing_huggingface_model_cache:
|
|
# mcp_server_logs:
|
|
# Persistent data for OpenSearch.
|
|
opensearch-data:
|