diff --git a/.github/workflows/backend_checks.yml b/.github/workflows/backend_checks.yml index beb06e8dc..fcc2ef82c 100644 --- a/.github/workflows/backend_checks.yml +++ b/.github/workflows/backend_checks.yml @@ -15,7 +15,7 @@ jobs: backend-checks: runs-on: self-hosted env: - API_PRODUCTION_WORKERS: 1 + API_WORKERS: 1 RAY_CONFIG: "config_gpu.yaml" JWT_SECRET: ${{ secrets.JWT_SECRET }} steps: @@ -29,6 +29,7 @@ jobs: sed -i 's/COMPOSE_PROJECT_NAME=demo/COMPOSE_PROJECT_NAME=action-runner/' .env sed -i 's/\(DATS_BACKEND_DOCKER_VERSION=[0-9.]*\)/\1-${{ github.run_id }}/' .env sed -i 's/\(DATS_RAY_DOCKER_VERSION=[0-9.]*\)/\1-${{ github.run_id }}/' .env + sed -i "s/UID=121/UID=$(id -u)/" .env sed -i "s/GID=126/GID=$(id -g)/" .env echo "SPACY_CACHE_DIR=$HOME/spacy_models" >> .env echo "MODELS_CACHE_DIR=$HOME/models_cache" >> .env diff --git a/.github/workflows/frontend_checks.yml b/.github/workflows/frontend_checks.yml index 1e35b3f8b..0b7def4b7 100644 --- a/.github/workflows/frontend_checks.yml +++ b/.github/workflows/frontend_checks.yml @@ -14,7 +14,7 @@ jobs: frontend-checks: runs-on: self-hosted env: - API_PRODUCTION_WORKERS: 1 + API_WORKERS: 1 VITE_APP_SERVER: http://localhost:13120 COMPOSE_PROFILES: "ray,background,backend,frontend" RAY_CONFIG: "config_gpu.yaml" @@ -33,6 +33,7 @@ jobs: cp .env.example .env sed -i 's/COMPOSE_PROJECT_NAME=demo/COMPOSE_PROJECT_NAME=action-runner/' .env sed -i 's/\(DATS_FRONTEND_DOCKER_VERSION=[0-9.]*\)/\1-${{ github.run_id }}/' .env + sed -i "s/UID=121/UID=$(id -u)/" .env sed -i "s/GID=126/GID=$(id -g)/" .env echo "SPACY_CACHE_DIR=$HOME/spacy_models" >> .env echo "MODELS_CACHE_DIR=$HOME/models_cache" >> .env diff --git a/backend/src/backend_api_entrypoint.sh b/backend/src/backend_api_entrypoint.sh index f1e5df00a..6a9bed794 100755 --- a/backend/src/backend_api_entrypoint.sh +++ b/backend/src/backend_api_entrypoint.sh @@ -4,11 +4,11 @@ set -e LOG_LEVEL=${LOG_LEVEL:-debug} API_PORT=${API_PORT:-5500} API_PRODUCTION_MODE=${API_PRODUCTION_MODE:--1} -API_PRODUCTION_WORKERS=${API_PRODUCTION_WORKERS:-10} +API_WORKERS=${API_WORKERS:-10} if [ "${API_PRODUCTION_MODE}" -ge 1 ]; then # start api in production mode without hot reload and only X worker - uvicorn --log-level "${LOG_LEVEL}" --port "${API_PORT}" --host "0.0.0.0" --workers "${API_PRODUCTION_WORKERS}" main:app + uvicorn --log-level "${LOG_LEVEL}" --port "${API_PORT}" --host "0.0.0.0" --workers "${API_WORKERS}" main:app else # start api in dev mode with hot reload and only 1 worker uvicorn --reload --log-level "${LOG_LEVEL}" --port "${API_PORT}" --host "0.0.0.0" main:app diff --git a/backend/src/celery_background_jobs_worker_entrypoint.sh b/backend/src/celery_background_jobs_worker_entrypoint.sh index d321342d1..621f7c2c7 100755 --- a/backend/src/celery_background_jobs_worker_entrypoint.sh +++ b/backend/src/celery_background_jobs_worker_entrypoint.sh @@ -7,6 +7,7 @@ export MKL_NUM_THREADS=1 LOG_LEVEL=${LOG_LEVEL:-debug} CELERY_BACKGROUND_JOBS_WORKER_CONCURRENCY=${CELERY_BACKGROUND_JOBS_WORKER_CONCURRENCY:-1} +CELERY_DEBUG_MODE=${CELERY_DEBUG_MODE:-0} if [ "$CELERY_DEBUG_MODE" -eq 1 ]; then echo "Running celery in debug mode!" diff --git a/backend/src/configs/production.yaml b/backend/src/configs/production.yaml index d0df40cd6..3a96a5d5f 100644 --- a/backend/src/configs/production.yaml +++ b/backend/src/configs/production.yaml @@ -1,7 +1,7 @@ api: port: 5500 max_upload_file_size: 104857600 # 100 MB in bytes - production_mode: ${oc.env:API_PRODUCTION_MODE, 1} + production_mode: 1 auth: jwt: token_url: /authentication/login diff --git a/bin/deploy.sh b/bin/deploy.sh index 4e4351255..56a726881 100755 --- a/bin/deploy.sh +++ b/bin/deploy.sh @@ -9,10 +9,11 @@ git pull # update .env file cp .env.example .env sed -i 's/COMPOSE_PROJECT_NAME=demo/COMPOSE_PROJECT_NAME=prod-dats/' .env -sed -i 's/CELERY_DEBUG_PORT=45678/CELERY_DEBUG_PORT=10178/' .env sed -i 's/131/101/g' .env sed -i "s/JWT_SECRET=/JWT_SECRET=$(pwgen 32 1)/" .env +sed -i "s/UID=121/UID=$(id -u)/" .env +sed -i "s/GID=126/GID=$(id -g)/" .env # pull & start docker containers docker compose pull -docker compose up --wait +docker compose up -f compose.yml -f compose.production.yml --wait diff --git a/bin/setup-envs.sh b/bin/setup-envs.sh new file mode 100755 index 000000000..2be16b13d --- /dev/null +++ b/bin/setup-envs.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +if [ ! -d ".git" ]; then + echo "This script must be run from the root directory of the project." + exit 1 +fi + +while [[ "$#" -gt 0 ]]; do + case $1 in + --project_name) PROJECT_NAME="$2"; shift ;; + --port_prefix) PORT_PREFIX="$2"; shift ;; + --help) + echo "Usage: $0 --project_name --port_prefix " + echo " --project_name The name of the project." + echo " --port_prefix The port prefix to use." + echo " --help Display this help message." + exit 0 + ;; + *) echo "Unknown parameter passed: $1"; exit 1 ;; + esac + shift +done + +if [ -z "$PROJECT_NAME" ] || [ -z "$PORT_PREFIX" ]; then + echo "--project_name and --port_prefix parameters are required." + exit 1 +fi + +JWT_SECRET=$(pwgen 32 1) +REPO_ROOT="$(pwd)/docker/backend_repo" + +cp docker/.env.example docker/.env +cp backend/.env.example backend/.env +cp frontend/.env.development.example frontend/.env.development +cp frontend/.env.production.example frontend/.env.production + +# setup docker .env file +sed -i "s/COMPOSE_PROJECT_NAME=demo/COMPOSE_PROJECT_NAME=${PROJECT_NAME}/" docker/.env +sed -i "s/131/${PORT_PREFIX}/g" docker/.env +sed -i "s/JWT_SECRET=/JWT_SECRET=${JWT_SECRET}/" docker/.env +sed -i "s/UID=121/UID=$(id -u)/" docker/.env +sed -i "s/GID=126/GID=$(id -g)/" docker/.env + +# setup backend .env file +sed -i "s/131/${PORT_PREFIX}/g" backend/.env +sed -i "s/JWT_SECRET=/JWT_SECRET=${JWT_SECRET}/" backend/.env +sed -i "s|REPO_ROOT=/insert_path_to_dats_repo/docker/backend_repo|REPO_ROOT=${REPO_ROOT}|" backend/.env + +# setup frontend .env file +sed -i "s/131/${PORT_PREFIX}/g" frontend/.env.development diff --git a/docker/.env.example b/docker/.env.example index d7aadf23e..477f86ff8 100644 --- a/docker/.env.example +++ b/docker/.env.example @@ -6,7 +6,6 @@ ### Docker settings COMPOSE_PROJECT_NAME=demo # remove profiles to disable containers -# add `development` if you are developing # dependencies are as follows: # ray < background < backend < frontend # you can remove profiles from right to left @@ -26,16 +25,15 @@ DATS_FRONTEND_DOCKER_VERSION=1.1.1 UID=121 GID=126 +### Frontend settings +FRONTEND_EXPOSED=13100 ### Backend settings +API_EXPOSED=13120 # LOG LEVEL ('critical', 'error', 'warning', 'info', 'debug', 'trace') API_LOG_LEVEL=info -# Install Jupyter (true) or not (false) -API_INSTALL_JUPYTER=false -# Development mode (0) or production mode (1) -API_PRODUCTION_MODE=1 -# This is only used when API_PRODUCTION_MODE == 1 -API_PRODUCTION_WORKERS=10 +# Number of production workers +API_WORKERS=10 # Use `pwgen` to generate a secret or use any long random string JWT_SECRET= # The system user is automatically created and owns automatically generated data. @@ -57,10 +55,6 @@ MAIL_VALIDATE_CERTS=False ### Celery background jobs worker settings # LOG LEVEL ('critical', 'error', 'warning', 'info', 'debug', 'trace') CELERY_LOG_LEVEL=info -# Install Jupyter (true) or not (false) -CELERY_INSTALL_JUPYTER=false -CELERY_DEBUG_MODE=0 -CELERY_DEBUG_PORT=45678 CELERY_BACKGROUND_JOBS_WORKER_CONCURRENCY=10 @@ -95,34 +89,25 @@ POSTGRES_PASSWORD=dats123 RAY_CONFIG=config_gpu.yaml -### Exposed ports -# These settings tell services which ports should be -# published, available to the outside world. -# If you're deploying your backend or frontend -# outside of docker, use these values -# to connect to the services in the respective -# .env files. -FRONTEND_EXPOSED=13100 +### Development settings +# These settings only affect the compose.override.yaml +# which is only used in development -API_EXPOSED=13120 +## Celery worker settings +# Install Jupyter (true) or not (false) +CELERY_INSTALL_JUPYTER=false +CELERY_DEBUG_MODE=0 +CELERY_DEBUG_PORT=13199 +## Exposed ports CONTENT_SERVER_EXPOSED=13121 - POSTGRES_EXPOSED=13122 - RABBIT_EXPOSED=13123 - REDIS_EXPOSED=13124 - ELASTICSEARCH_EXPOSED=13125 KIBANA_EXPOSED=13126 - -JUPYTER_API_EXPOSED=13127 JUPYTER_CELERY_EXPOSED=13129 - RAY_API_EXPOSED=13130 RAY_DASHBOARD_EXPOSED=13131 - WEAVIATE_EXPOSED=13132 - OLLAMA_EXPOSED=13133 diff --git a/docker/docker-compose-ollama.yml b/docker/compose.ollama.yml similarity index 90% rename from docker/docker-compose-ollama.yml rename to docker/compose.ollama.yml index 28779f534..35132fe81 100644 --- a/docker/docker-compose-ollama.yml +++ b/docker/compose.ollama.yml @@ -1,4 +1,4 @@ -# docker compose -f docker-compose-ollama.yml up -d +# docker compose -f compose.ollama.yml up -d services: ollama: diff --git a/docker/compose.override.yml b/docker/compose.override.yml new file mode 100644 index 000000000..cba5175ea --- /dev/null +++ b/docker/compose.override.yml @@ -0,0 +1,62 @@ +services: + postgres: + ports: + - "${POSTGRES_EXPOSED:-13122}:5432" + + rabbitmq: + ports: + - "${RABBIT_EXPOSED:-13123}:5672" + + redis: + ports: + - "${REDIS_EXPOSED:-13124}:6379" + + weaviate: + ports: + - "${WEAVIATE_EXPOSED:-13132}:8080" + + elasticsearch: + ports: + - "${ELASTICSEARCH_EXPOSED:-13125}:9200" + + kibana: + image: docker.elastic.co/kibana/kibana:8.11.1 + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:5601 || exit 1"] + interval: 30s + timeout: 10s + retries: 5 + environment: + ELASTICSEARCH_URL: http://elasticsearch:9200 + ELASTICSEARCH_HOSTS: '["http://elasticsearch:9200"]' + ports: + - "${KIBANA_EXPOSED:-13126}:5601" + networks: + - dats_demo_network + depends_on: + elasticsearch: + condition: service_healthy + restart: true + + lighttpd: + image: sebp/lighttpd + volumes: + - ./backend_repo:/var/www/localhost/htdocs + tty: true + ports: + - "${CONTENT_SERVER_EXPOSED:-13121}:80" + networks: + - dats_demo_network + + ray: + ports: + - "${RAY_API_EXPOSED:-13130}:8000" + - "${RAY_DASHBOARD_EXPOSED:-13131}:8265" + + celery-background-jobs-worker: + environment: + INSTALL_JUPYTER: ${CELERY_INSTALL_JUPYTER:-false} + CELERY_DEBUG_MODE: ${CELERY_DEBUG_MODE:-0} + ports: + - "${JUPYTER_CELERY_EXPOSED:-13129}:8888" + - "${CELERY_DEBUG_PORT:-45678}:6900" diff --git a/docker/compose.production.yml b/docker/compose.production.yml new file mode 100644 index 000000000..89c8d228b --- /dev/null +++ b/docker/compose.production.yml @@ -0,0 +1,15 @@ +services: + elasticsearch: + environment: + - xpack.security.enabled=false # no auth + - discovery.type=single-node # single node cluster + - ES_JAVA_OPTS=-Xms8g -Xmx8g + + ray: + deploy: + resources: + reservations: + devices: + - driver: nvidia + device_ids: ["0"] # use first gpu for production + capabilities: [gpu] diff --git a/docker/docker-compose.yml b/docker/compose.yml similarity index 84% rename from docker/docker-compose.yml rename to docker/compose.yml index a2a3728db..5107920bf 100644 --- a/docker/docker-compose.yml +++ b/docker/compose.yml @@ -9,8 +9,6 @@ services: environment: POSTGRES_USER: ${POSTGRES_USER:-datsuser} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-dats123} - ports: - - "${POSTGRES_EXPOSED:-13122}:5432" volumes: - "postgres_data_demo:/var/lib/postgresql/data" networks: @@ -26,8 +24,6 @@ services: environment: RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-datsuser} RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-dats123} - ports: - - "${RABBIT_EXPOSED:-13123}:5672" volumes: - "rabbitmq_data_demo:/var/lib/rabbitmq/data" networks: @@ -42,8 +38,6 @@ services: retries: 5 environment: REDIS_PASSWORD: ${REDIS_PASSWORD:-dats123} - ports: - - "${REDIS_EXPOSED:-13124}:6379" volumes: - "redis_data_demo:/var/lib/redis/data" command: redis-server --requirepass "${REDIS_PASSWORD:-dats123}" --save 60 1 @@ -64,8 +58,6 @@ services: interval: 30s timeout: 10s retries: 5 - ports: - - "${WEAVIATE_EXPOSED:-13132}:8080" volumes: - "weaviate_data_demo:/var/lib/weaviate" restart: on-failure:0 @@ -104,49 +96,9 @@ services: volumes: - elasticsearch_data_demo:/usr/share/elasticsearch/data - ./elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml - ports: - - "${ELASTICSEARCH_EXPOSED:-13125}:9200" networks: - dats_demo_network - kibana: - image: docker.elastic.co/kibana/kibana:8.11.1 - healthcheck: - test: ["CMD-SHELL", "curl -f http://localhost:5601 || exit 1"] - interval: 30s - timeout: 10s - retries: 5 - ports: - - "${KIBANA_EXPOSED:-13126}:5601" - environment: - ELASTICSEARCH_URL: http://elasticsearch:9200 - ELASTICSEARCH_HOSTS: '["http://elasticsearch:9200"]' - networks: - - dats_demo_network - depends_on: - elasticsearch: - condition: service_healthy - restart: true - profiles: - - development - - lighttpd: - image: sebp/lighttpd - healthcheck: - test: ["CMD-SHELL", "curl -f http://localhost/ || exit 1"] - interval: 30s - timeout: 10s - retries: 5 - volumes: - - ./backend_repo:/var/www/localhost/htdocs - ports: - - "${CONTENT_SERVER_EXPOSED:-13121}:80" - tty: true - networks: - - dats_demo_network - profiles: - - development - ray: image: uhhlt/dats_ray:${DATS_RAY_DOCKER_VERSION:-debian_dev_latest} build: @@ -174,9 +126,6 @@ services: - ./backend_repo:/tmp/dats - "${MODELS_CACHE_DIR:-./models_cache}:/models_cache" - ./numba_cache:/numba_cache - ports: - - "${RAY_API_EXPOSED:-13130}:8000" - - "${RAY_DASHBOARD_EXPOSED:-13131}:8265" shm_size: 12gb networks: - dats_demo_network @@ -205,9 +154,7 @@ services: environment: DATS_BACKEND_CONFIG: /dats_code/src/configs/production.yaml LOG_LEVEL: ${CELERY_LOG_LEVEL:-info} - INSTALL_JUPYTER: ${CELERY_INSTALL_JUPYTER:-false} CELERY_BACKGROUND_JOBS_WORKER_CONCURRENCY: ${CELERY_BACKGROUND_JOBS_WORKER_CONCURRENCY:-1} - CELERY_DEBUG_MODE: ${CELERY_DEBUG_MODE:-0} POSTGRES_DB: ${POSTGRES_DB:-dats} POSTGRES_USER: ${POSTGRES_USER:-datsuser} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-dats123} @@ -248,9 +195,6 @@ services: ray: condition: service_healthy restart: true - ports: - - "${JUPYTER_CELERY_EXPOSED:-13129}:8888" - - "${CELERY_DEBUG_PORT:-45678}:6900" networks: - dats_demo_network - ollama_network @@ -273,9 +217,7 @@ services: environment: DATS_BACKEND_CONFIG: /dats_code/src/configs/production.yaml LOG_LEVEL: ${API_LOG_LEVEL:-info} - INSTALL_JUPYTER: ${API_INSTALL_JUPYTER:-false} - API_PRODUCTION_MODE: ${API_PRODUCTION_MODE:-0} - API_PRODUCTION_WORKERS: ${API_PRODUCTION_WORKERS:-10} + API_WORKERS: ${API_WORKERS:-10} JWT_SECRET: ${JWT_SECRET:-""} SYSTEM_USER_EMAIL: ${SYSTEM_USER_EMAIL} SYSTEM_USER_PASSWORD: ${SYSTEM_USER_PASSWORD} @@ -318,7 +260,6 @@ services: restart: true ports: - "${API_EXPOSED:-13120}:5500" - - "${JUPYTER_API_EXPOSED:-13127}:8888" networks: - dats_demo_network - ollama_network