deerflow-code/offline-backend-20260512/backend/start-backend-docker.sh
2026-09-07 18:24:55 +08:00

111 lines
3.8 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
IMAGE_NAME="${IMAGE_NAME:-deerflow-backend-offline:latest}"
CONTAINER_NAME="${CONTAINER_NAME:-deerflow-backend}"
BACKEND_PORT="${1:-${BACKEND_PORT:-8001}}"
CODE_DIR="${CODE_DIR:-${SCRIPT_DIR}}"
DATA_DIR="${DATA_DIR:-${SCRIPT_DIR}/docker-data}"
CONFIG_DIR="${CONFIG_DIR:-${DATA_DIR}/config}"
RUNTIME_DIR="${RUNTIME_DIR:-${DATA_DIR}/.deer-flow}"
SKILLS_DIR="${SKILLS_DIR:-${DATA_DIR}/skills}"
KNOWLEDGE_DIR="${KNOWLEDGE_DIR:-${DATA_DIR}/knowledge}"
LOGS_DIR="${LOGS_DIR:-${DATA_DIR}/logs}"
CONFIG_FILE="${CONFIG_DIR}/config.yaml"
EXTENSIONS_FILE="${CONFIG_DIR}/extensions_config.json"
LANGGRAPH_FILE="${CONFIG_DIR}/langgraph.json"
ENV_FILE="${CONFIG_DIR}/.env"
ENV_SOURCE="${CODE_DIR}/.env"
# The repository-level offline deployment keeps its tracked environment file
# one directory above the backend source. Prefer a backend-local file when a
# deployment provides one, otherwise use that shared file.
if [[ ! -f "${ENV_SOURCE}" && -f "$(dirname "${CODE_DIR}")/.env" ]]; then
ENV_SOURCE="$(dirname "${CODE_DIR}")/.env"
fi
copy_if_missing() {
local src="$1"
local dst="$2"
if [[ ! -e "${dst}" && -e "${src}" ]]; then
mkdir -p "$(dirname "${dst}")"
cp -a "${src}" "${dst}"
fi
}
copy_dir_if_missing() {
local src="$1"
local dst="$2"
if [[ ! -e "${dst}" && -d "${src}" ]]; then
mkdir -p "$(dirname "${dst}")"
cp -a "${src}" "${dst}"
fi
}
mkdir -p "${CONFIG_DIR}" "${RUNTIME_DIR}/data" "${LOGS_DIR}"
copy_if_missing "${CODE_DIR}/config.yaml" "${CONFIG_FILE}"
copy_if_missing "${CODE_DIR}/extensions_config.json" "${EXTENSIONS_FILE}"
copy_if_missing "${CODE_DIR}/langgraph.json" "${LANGGRAPH_FILE}"
copy_if_missing "${ENV_SOURCE}" "${ENV_FILE}"
touch "${ENV_FILE}"
copy_dir_if_missing "${CODE_DIR}/skills" "${SKILLS_DIR}"
mkdir -p "${SKILLS_DIR}"
copy_dir_if_missing "${CODE_DIR}/knowledge" "${KNOWLEDGE_DIR}"
mkdir -p "${KNOWLEDGE_DIR}"
copy_dir_if_missing "${CODE_DIR}/.deer-flow/agents" "${RUNTIME_DIR}/agents"
copy_dir_if_missing "${CODE_DIR}/.deer-flow/channels" "${RUNTIME_DIR}/channels"
copy_dir_if_missing "${CODE_DIR}/.deer-flow/users" "${RUNTIME_DIR}/users"
copy_if_missing "${CODE_DIR}/.deer-flow/SOUL.md" "${RUNTIME_DIR}/SOUL.md"
copy_if_missing "${CODE_DIR}/.deer-flow/USER.md" "${RUNTIME_DIR}/USER.md"
copy_if_missing "${CODE_DIR}/.deer-flow/system_settings.json" "${RUNTIME_DIR}/system_settings.json"
if docker ps -a --format '{{.Names}}' | grep -Fxq "${CONTAINER_NAME}"; then
docker rm -f "${CONTAINER_NAME}" >/dev/null
fi
DOCKER_ARGS=(
run -d
--name "${CONTAINER_NAME}"
--restart unless-stopped
-p "${BACKEND_PORT}:${BACKEND_PORT}"
--add-host host.docker.internal:host-gateway
-e "BACKEND_PORT=${BACKEND_PORT}"
-e "DEER_FLOW_GATEWAY_PORT=${BACKEND_PORT}"
-e "DEER_FLOW_PROJECT_ROOT=/app/backend"
-e "DEER_FLOW_HOME=/app/backend/.deer-flow"
-e "DEER_FLOW_HOST_BASE_DIR=${RUNTIME_DIR}"
-e "DEER_FLOW_CONFIG_PATH=/app/backend/config.yaml"
-e "DEER_FLOW_EXTENSIONS_CONFIG_PATH=/app/backend/extensions_config.json"
-e "DEER_FLOW_SKILLS_PATH=/app/backend/skills"
-v "${CODE_DIR}:/app/backend"
-v "${CONFIG_FILE}:/app/backend/config.yaml"
-v "${EXTENSIONS_FILE}:/app/backend/extensions_config.json"
-v "${LANGGRAPH_FILE}:/app/backend/langgraph.json"
-v "${ENV_FILE}:/app/backend/.env"
-v "${RUNTIME_DIR}:/app/backend/.deer-flow"
-v "${SKILLS_DIR}:/app/backend/skills"
-v "${KNOWLEDGE_DIR}:/app/backend/knowledge"
-v "${LOGS_DIR}:/app/backend/logs"
)
if [[ -S /var/run/docker.sock ]]; then
DOCKER_ARGS+=(-v /var/run/docker.sock:/var/run/docker.sock)
fi
DOCKER_ARGS+=("${IMAGE_NAME}")
docker "${DOCKER_ARGS[@]}"
echo "Started ${CONTAINER_NAME}"
echo "Backend: http://127.0.0.1:${BACKEND_PORT}"
echo "Config: ${CONFIG_DIR}"
echo "Data: ${DATA_DIR}"