89 lines
2.5 KiB
Bash
89 lines
2.5 KiB
Bash
#!/bin/sh
|
||
set -eu
|
||
|
||
# 容器入口:
|
||
# - 默认只启动 API(与原 Dockerfile 行为一致)
|
||
# - 如需测试“定时推送”,可额外启动 Celery Worker + Beat
|
||
#
|
||
# 环境变量:
|
||
# - START_API=1|0(默认 1)
|
||
# - START_WORKER=1|0(默认 0)
|
||
# - START_BEAT=1|0(默认 0)
|
||
# - START_ALL=1(等价于 START_WORKER=1 + START_BEAT=1)
|
||
# - HOST / PORT(API 监听地址,默认 0.0.0.0:8000)
|
||
|
||
log() {
|
||
echo "[entrypoint] $*"
|
||
}
|
||
|
||
START_API="${START_API:-1}"
|
||
START_WORKER="${START_WORKER:-0}"
|
||
START_BEAT="${START_BEAT:-0}"
|
||
|
||
if [ "${START_ALL:-0}" = "1" ]; then
|
||
START_WORKER="1"
|
||
START_BEAT="1"
|
||
fi
|
||
|
||
# Beat 只负责“投递任务到队列”,真正执行仍需要 Worker。
|
||
# 说明:
|
||
# - 单容器模式:若启动了 API(START_API=1)且同时启用了 Beat,则自动补齐 Worker,避免误配导致“只排程不执行”。
|
||
# - 多容器模式:允许单独启动 beat 容器(START_API=0, START_BEAT=1),不做自动补齐。
|
||
if [ "$START_API" = "1" ] && [ "$START_BEAT" = "1" ] && [ "$START_WORKER" != "1" ]; then
|
||
log "提示:已启用 START_BEAT=1(且 START_API=1),自动同时启用 START_WORKER=1(否则队列无人执行)。"
|
||
START_WORKER="1"
|
||
fi
|
||
|
||
PIDS=""
|
||
|
||
stop_children() {
|
||
# 温和退出
|
||
for pid in $PIDS; do
|
||
kill -TERM "$pid" >/dev/null 2>&1 || true
|
||
done
|
||
}
|
||
|
||
on_term() {
|
||
log "收到退出信号,正在停止子进程..."
|
||
stop_children
|
||
# 等待子进程退出,避免残留
|
||
wait >/dev/null 2>&1 || true
|
||
exit 0
|
||
}
|
||
|
||
trap on_term INT TERM
|
||
|
||
if [ "$START_WORKER" = "1" ]; then
|
||
log "启动 Celery Worker:celery -A app.worker:celery_app worker -l info"
|
||
celery -A app.worker:celery_app worker -l info &
|
||
PIDS="$PIDS $!"
|
||
fi
|
||
|
||
if [ "$START_BEAT" = "1" ]; then
|
||
log "启动 Celery Beat:celery -A app.worker:celery_app beat -l info"
|
||
celery -A app.worker:celery_app beat -l info &
|
||
PIDS="$PIDS $!"
|
||
fi
|
||
|
||
if [ "$START_API" = "1" ]; then
|
||
HOST="${HOST:-0.0.0.0}"
|
||
PORT="${PORT:-8000}"
|
||
log "启动 API:uvicorn app.main:app --host $HOST --port $PORT"
|
||
uvicorn app.main:app --host "$HOST" --port "$PORT" &
|
||
API_PID="$!"
|
||
PIDS="$PIDS $API_PID"
|
||
|
||
# 以 API 生命周期为准:API 退出则容器退出,并清理其他进程
|
||
wait "$API_PID"
|
||
CODE="$?"
|
||
log "API 已退出(code=$CODE),正在停止其他进程..."
|
||
stop_children
|
||
wait >/dev/null 2>&1 || true
|
||
exit "$CODE"
|
||
fi
|
||
|
||
# 未启动 API:就阻塞等待其他进程(一般用于仅跑 worker/beat 的容器)
|
||
log "未启动 API,等待后台进程..."
|
||
wait
|
||
|