From faf78d30696c2df68da93a6d6538c487141d1b63 Mon Sep 17 00:00:00 2001 From: Idriss Sbaaoui <112825897+6ba3i@users.noreply.github.com> Date: Tue, 9 Jun 2026 13:04:05 +0800 Subject: [PATCH] Fix: OceanBase tenant startup drift and docs (#15829) ### What problem does this PR solve? OceanBase could start without the `ragflow` tenant, so RAGFlow failed to connect with `root@ragflow`. This PR adds a safe startup reconcile step and documents the required host limits before using OceanBase. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) - [x] Documentation Update --- docker/README.md | 42 +++++++++++- docker/docker-compose-base.yml | 6 ++ docker/oceanbase-entrypoint.sh | 115 +++++++++++++++++++++++++++++++++ 3 files changed, 162 insertions(+), 1 deletion(-) create mode 100755 docker/oceanbase-entrypoint.sh diff --git a/docker/README.md b/docker/README.md index 8479b59979..61db253dab 100644 --- a/docker/README.md +++ b/docker/README.md @@ -119,6 +119,46 @@ The [.env](./.env) file contains important environment variables for Docker. - `EMBEDDING_BATCH_SIZE` The number of text chunks processed in a single batch during embedding vectorization. Defaults to `16`. +### OceanBase prerequisites + +Before setting `DOC_ENGINE=oceanbase`, make sure the host OS allows the file descriptor and core dump limits OceanBase expects. + +1. Set host limits: + + ```bash + sudo tee /etc/security/limits.d/99-oceanbase.conf >/dev/null <<'EOF' + root soft nofile 655350 + root hard nofile 655350 + * soft nofile 655350 + * hard nofile 655350 + * soft core unlimited + * hard core unlimited + EOF + ``` + +2. Make sure PAM limits are enabled: + + ```bash + grep -E 'pam_limits\.so' /etc/pam.d/common-session /etc/pam.d/common-session-noninteractive + ``` + + If missing, add them: + + ```bash + echo 'session required pam_limits.so' | sudo tee -a /etc/pam.d/common-session + echo 'session required pam_limits.so' | sudo tee -a /etc/pam.d/common-session-noninteractive + ``` + +3. Log out and log back in, or reboot. + +4. Verify the effective limit: + + ```bash + ulimit -n + ``` + + Expected: `655350`, or at least `20000`. + ## 🐋 Service configuration [service_conf.yaml](./service_conf.yaml) specifies the system-level configuration for RAGFlow and is used by its API server and task executor. In a dockerized setup, this file is automatically created based on the [service_conf.yaml.template](./service_conf.yaml.template) file (replacing all environment variables by their values). @@ -268,4 +308,4 @@ If you already have SSL certificates from another provider: 1. Place your certificates in a directory accessible to Docker 2. Update the volume paths in `docker-compose.yml` to point to your certificate files 3. Ensure the certificate file contains the full certificate chain -4. Follow steps 4-5 from the Let's Encrypt guide above \ No newline at end of file +4. Follow steps 4-5 from the Let's Encrypt guide above diff --git a/docker/docker-compose-base.yml b/docker/docker-compose-base.yml index 1b2c0088d5..22c7a7b482 100644 --- a/docker/docker-compose-base.yml +++ b/docker/docker-compose-base.yml @@ -104,10 +104,16 @@ services: profiles: - oceanbase image: oceanbase/oceanbase-ce:4.4.1.0-100000032025101610 + entrypoint: ["bash", "/root/boot/ragflow-oceanbase-entrypoint.sh"] + ulimits: + nofile: + soft: 655350 + hard: 655350 volumes: - ./oceanbase/data:/root/ob - ./oceanbase/conf:/root/.obd/cluster - ./oceanbase/init.d:/root/boot/init.d + - ./oceanbase-entrypoint.sh:/root/boot/ragflow-oceanbase-entrypoint.sh:ro ports: - ${OCEANBASE_PORT:-2881}:2881 env_file: .env diff --git a/docker/oceanbase-entrypoint.sh b/docker/oceanbase-entrypoint.sh new file mode 100755 index 0000000000..2124e0dfc6 --- /dev/null +++ b/docker/oceanbase-entrypoint.sh @@ -0,0 +1,115 @@ +#!/bin/bash +set -euo pipefail + +log() { + echo "[ragflow-ob-entrypoint] $*" +} + +ob_sys() { + obclient -h127.0.0.1 -P2881 -uroot@sys -p"${OB_SYS_PASSWORD}" -Doceanbase -A -N -e "$1" +} + +ob_tenant_with_password() { + obclient -h127.0.0.1 -P2881 -uroot@"${OB_TENANT_NAME}" -p"${OB_TENANT_PASSWORD}" -A -N -e "$1" +} + +ob_tenant_without_password() { + obclient -h127.0.0.1 -P2881 -uroot@"${OB_TENANT_NAME}" -A -N -e "$1" +} + +wait_for_sys() { + for _ in $(seq 1 120); do + if ob_sys "SELECT 1" >/dev/null 2>&1; then + return 0 + fi + sleep 1 + done + return 1 +} + +tenant_exists() { + ob_sys "SELECT 1 FROM oceanbase.DBA_OB_TENANTS WHERE tenant_name='${OB_TENANT_NAME}'" 2>/dev/null | grep -q '^1$' +} + +wait_for_tenant_password() { + for _ in $(seq 1 60); do + if ob_tenant_with_password "SELECT 1" >/dev/null 2>&1; then + return 0 + fi + sleep 1 + done + return 1 +} + +ensure_tenant_ready() { + if ob_tenant_with_password "SELECT 1" >/dev/null 2>&1; then + log "tenant ${OB_TENANT_NAME} accepts the configured password" + return 0 + fi + + if tenant_exists; then + for _ in $(seq 1 120); do + if ob_tenant_with_password "SELECT 1" >/dev/null 2>&1; then + log "tenant ${OB_TENANT_NAME} became reachable with the configured password" + return 0 + fi + + if ob_tenant_without_password "SELECT 1" >/dev/null 2>&1; then + log "tenant ${OB_TENANT_NAME} exists with an empty root password; applying OB_TENANT_PASSWORD" + ob_tenant_without_password "ALTER USER root IDENTIFIED BY '${OB_TENANT_PASSWORD}'" >/dev/null 2>&1 || { + log "warning: failed to update the tenant root password" + return 1 + } + wait_for_tenant_password && return 0 + log "warning: tenant password update did not become effective in time" + return 1 + fi + + sleep 1 + done + + log "warning: tenant ${OB_TENANT_NAME} exists but never accepted the configured or empty password during reconciliation" + return 1 + fi + + log "tenant ${OB_TENANT_NAME} is missing; creating it with the configured password" + if ! obd cluster tenant create obcluster -n "${OB_TENANT_NAME}" -o "${OB_SCENARIO:-htap}" --password "${OB_TENANT_PASSWORD}" >/dev/null 2>&1; then + log "warning: failed to create tenant ${OB_TENANT_NAME}" + return 1 + fi + + if wait_for_tenant_password; then + return 0 + fi + + log "warning: tenant ${OB_TENANT_NAME} did not become connectable in time" + return 1 +} + +ensure_database() { + if ob_tenant_with_password "CREATE DATABASE IF NOT EXISTS \`${OCEANBASE_DOC_DBNAME}\`" >/dev/null 2>&1; then + log "database ${OCEANBASE_DOC_DBNAME} is ready in tenant ${OB_TENANT_NAME}" + return 0 + fi + + log "warning: failed to ensure database ${OCEANBASE_DOC_DBNAME}" + return 1 +} + +reconcile_oceanbase() { + if ! wait_for_sys; then + log "warning: sys tenant never became reachable; skipping reconciliation" + return 0 + fi + + ensure_tenant_ready || return 0 + ensure_database || return 0 +} + +/usr/sbin/sshd +/root/boot/start.sh & +start_pid=$! + +reconcile_oceanbase || true & + +wait "${start_pid}"