diff --git a/.gitignore b/.gitignore index bee8a64..82b2a9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ __pycache__ +app/app.log +app/chroma.log diff --git a/docker-compose-base.yaml b/docker-compose-base.yaml index dd45ab2..6fa6d89 100644 --- a/docker-compose-base.yaml +++ b/docker-compose-base.yaml @@ -8,7 +8,7 @@ services: - ./dataset:/dataset # 将宿主机的data目录挂载到容器内的/app/dataset - ./chroma_db:/chroma_db # 将宿主机的model目录挂载到容器内的/app/model working_dir: /app # 设置工作目录 - command: ["./wait-for-it.sh", "chroma:8000", "--", "python", "app.py"] # 启动后端服务并等待 Chroma 服务 + # command: ["wait-for-it", "chroma:8000", "--", "python", "server.py"] # 启动后端服务并等待 Chroma 服务 ports: - "8082:8082" environment: @@ -39,15 +39,17 @@ services: - smart_bot_network chroma: - image: python:3.10 + build: + context: . + dockerfile: ./docker/chroma/Dockerfile volumes: - ./chroma_db:/chroma_db # 挂载 Chroma 数据库目录 - ./app:/app # 挂载应用目录 working_dir: /app # 设置工作目录 - command: > - bash -c " - pip install langchain_chroma chromadb -i https://pypi.tuna.tsinghua.edu.cn/simple/ && - chroma run --path chroma_db --port 8000 --host 0.0.0.0" # 启动 Chroma + # command: > + # bash -c " + # pip install langchain_chroma chromadb && + # chroma run --path chroma_db --port 8000 --host 0.0.0.0" # 启动 Chroma ports: - "8000:8000" # 映射 Chroma 服务端口 networks: diff --git a/docker/backend/Dockerfile b/docker/backend/Dockerfile index 5180bd5..5174593 100644 --- a/docker/backend/Dockerfile +++ b/docker/backend/Dockerfile @@ -1,18 +1,21 @@ # 使用 Python 官方镜像 FROM python:3.10-slim +# 设置工作目录 +WORKDIR /app + +# 更新包列表并安装 netcat-openbsd +RUN apt-get update && apt-get install -y netcat-openbsd && rm -rf /var/lib/apt/lists/* + # 复制 wait-for-it.sh 脚本 -COPY scripts/wait-for-it.sh /usr/local/bin/wait-for-it +COPY ./scripts/wait-for-it.sh /usr/local/bin/wait-for-it # 给予执行权限 RUN chmod +x /usr/local/bin/wait-for-it -# 设置工作目录 -WORKDIR /app - # 复制 requirements.txt 文件并安装依赖 COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple +RUN pip install -r requirements.txt # 复制应用代码 COPY app/. . @@ -20,5 +23,5 @@ COPY app/. . # 暴露服务端口 EXPOSE 8082 -# # 设置容器启动命令,等待 chroma 服务启动 -# CMD ["wait-for-it", "chroma:8000", "--", "python", "app.py"] \ No newline at end of file +# 设置容器启动命令,等待 chroma 服务启动 +CMD ["wait-for-it", "chroma:8000", "--", "python", "server.py"] \ No newline at end of file diff --git a/docker/chroma/Dockerfile b/docker/chroma/Dockerfile new file mode 100644 index 0000000..435e2b6 --- /dev/null +++ b/docker/chroma/Dockerfile @@ -0,0 +1,17 @@ +# 使用官方的 Python 3.10 基础镜像 +FROM python:3.10 + +# 设置工作目录 +WORKDIR /app + +# 复制应用代码 +COPY app/. . + +# 安装所需的 Python 包 +RUN pip install --no-cache-dir langchain_chroma chromadb + +# 暴露 Chroma 服务端口 +EXPOSE 8000 + +# 运行 Chroma 服务 +CMD ["chroma", "run", "--path", "chroma_db", "--port", "8000", "--host", "0.0.0.0"] diff --git a/scripts/wait-for-it.sh b/scripts/wait-for-it.sh index b28d2ae..3974640 100755 --- a/scripts/wait-for-it.sh +++ b/scripts/wait-for-it.sh @@ -1,44 +1,182 @@ #!/usr/bin/env bash +# Use this script to test if a given TCP host/port are available -# Use this to wait for a service to be available. -# Usage: wait-for-it.sh host:port [-t timeout] [-- command args] -# Example: wait-for-it.sh db:5432 -- python my_app.py - -TIMEOUT=15 -WAIT_FOR=0 - -while [[ $# -gt 0 ]]; do - case "$1" in - -t) - TIMEOUT="$2" - shift 2 - ;; - *) - WAIT_FOR="$1" - shift - ;; - esac +WAITFORIT_cmdname=${0##*/} + +echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } + +usage() +{ + cat << USAGE >&2 +Usage: + $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] + -h HOST | --host=HOST Host or IP under test + -p PORT | --port=PORT TCP port under test + Alternatively, you specify the host and port as host:port + -s | --strict Only execute subcommand if the test succeeds + -q | --quiet Don't output any status messages + -t TIMEOUT | --timeout=TIMEOUT + Timeout in seconds, zero for no timeout + -- COMMAND ARGS Execute command with args after the test finishes +USAGE + exit 1 +} + +wait_for() +{ + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + else + echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" + fi + WAITFORIT_start_ts=$(date +%s) + while : + do + if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then + nc -z $WAITFORIT_HOST $WAITFORIT_PORT + WAITFORIT_result=$? + else + (echo -n > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 + WAITFORIT_result=$? + fi + if [[ $WAITFORIT_result -eq 0 ]]; then + WAITFORIT_end_ts=$(date +%s) + echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" + break + fi + sleep 1 + done + return $WAITFORIT_result +} + +wait_for_wrapper() +{ + # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 + if [[ $WAITFORIT_QUIET -eq 1 ]]; then + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + else + timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & + fi + WAITFORIT_PID=$! + trap "kill -INT -$WAITFORIT_PID" INT + wait $WAITFORIT_PID + WAITFORIT_RESULT=$? + if [[ $WAITFORIT_RESULT -ne 0 ]]; then + echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" + fi + return $WAITFORIT_RESULT +} + +# process arguments +while [[ $# -gt 0 ]] +do + case "$1" in + *:* ) + WAITFORIT_hostport=(${1//:/ }) + WAITFORIT_HOST=${WAITFORIT_hostport[0]} + WAITFORIT_PORT=${WAITFORIT_hostport[1]} + shift 1 + ;; + --child) + WAITFORIT_CHILD=1 + shift 1 + ;; + -q | --quiet) + WAITFORIT_QUIET=1 + shift 1 + ;; + -s | --strict) + WAITFORIT_STRICT=1 + shift 1 + ;; + -h) + WAITFORIT_HOST="$2" + if [[ $WAITFORIT_HOST == "" ]]; then break; fi + shift 2 + ;; + --host=*) + WAITFORIT_HOST="${1#*=}" + shift 1 + ;; + -p) + WAITFORIT_PORT="$2" + if [[ $WAITFORIT_PORT == "" ]]; then break; fi + shift 2 + ;; + --port=*) + WAITFORIT_PORT="${1#*=}" + shift 1 + ;; + -t) + WAITFORIT_TIMEOUT="$2" + if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi + shift 2 + ;; + --timeout=*) + WAITFORIT_TIMEOUT="${1#*=}" + shift 1 + ;; + --) + shift + WAITFORIT_CLI=("$@") + break + ;; + --help) + usage + ;; + *) + echoerr "Unknown argument: $1" + usage + ;; + esac done -if [[ -z "$WAIT_FOR" ]]; then - echo "Usage: wait-for-it.sh host:port [-t timeout] [-- command args]" - exit 1 +if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then + echoerr "Error: you need to provide a host and port to test." + usage fi -HOST=$(echo "$WAIT_FOR" | cut -d: -f1) -PORT=$(echo "$WAIT_FOR" | cut -d: -f2) +WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} +WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} +WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} +WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} -# Wait for the host:port to be available -echo "Waiting for $WAIT_FOR..." -for ((i=0; i/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) + +WAITFORIT_BUSYTIMEFLAG="" +if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then + WAITFORIT_ISBUSY=1 + # Check if busybox timeout uses -t flag + # (recent Alpine versions don't support -t anymore) + if timeout &>/dev/stdout | grep -q -e '-t '; then + WAITFORIT_BUSYTIMEFLAG="-t" + fi +else + WAITFORIT_ISBUSY=0 +fi -# Check if the service is up -if ! nc -z "$HOST" "$PORT"; then - echo "Timeout waiting for $WAIT_FOR" - exit 1 +if [[ $WAITFORIT_CHILD -gt 0 ]]; then + wait_for + WAITFORIT_RESULT=$? + exit $WAITFORIT_RESULT +else + if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then + wait_for_wrapper + WAITFORIT_RESULT=$? + else + wait_for + WAITFORIT_RESULT=$? + fi fi -echo "$WAIT_FOR is up!" +if [[ $WAITFORIT_CLI != "" ]]; then + if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then + echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" + exit $WAITFORIT_RESULT + fi + exec "${WAITFORIT_CLI[@]}" +else + exit $WAITFORIT_RESULT +fi \ No newline at end of file