Files
micro_servers/docker.sh
T
2026-07-30 21:57:04 +08:00

387 lines
10 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
#
# 微服务容器化管理脚本
# 用法: ./docker.sh [command]
#
set -e
cd "$(dirname "$0")"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
check_docker() {
if ! command -v docker &> /dev/null; then
error "Docker 未安装,请先安装 Docker Desktop"
fi
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
error "Docker Compose 未安装"
fi
}
# 使用 docker compose 或 docker-compose(兼容旧版本)
docker_compose() {
if docker compose version &> /dev/null; then
docker compose "$@"
else
docker-compose "$@"
fi
}
cmd_build() {
info "构建所有服务镜像..."
docker_compose build --progress=plain "$@"
info "构建完成"
}
cmd_up() {
info "启动服务(后台运行)..."
docker_compose up -d "$@"
info "服务已启动"
echo ""
cmd_ps
}
cmd_down() {
info "停止并移除容器..."
docker_compose down "$@"
info "服务已停止"
}
cmd_start() {
info "启动已存在的容器..."
docker_compose start "$@"
}
cmd_stop() {
info "停止运行中的容器..."
docker_compose stop "$@"
}
cmd_restart() {
info "重启服务..."
docker_compose restart "$@"
}
cmd_ps() {
info "服务状态:"
docker_compose ps
}
cmd_logs() {
if [ -z "$1" ]; then
docker_compose logs -f --tail=100
else
docker_compose logs -f --tail=100 "$@"
fi
}
cmd_shell() {
local service=${1:-dnfs}
info "进入 $service 容器 shell..."
docker_compose exec "$service" /bin/bash || docker_compose exec "$service" /bin/sh
}
cmd_rebuild() {
info "重新构建并启动服务..."
docker_compose build --no-cache "$@"
docker_compose up -d "$@"
}
cmd_clean() {
warn "此操作将停止所有容器并删除数据卷(数据库和ChromaDB数据将丢失!)"
read -p "确认继续? [y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
docker_compose down -v
info "已清理所有容器和数据卷"
else
info "已取消"
fi
}
cmd_pull() {
info "拉取基础镜像..."
docker pull python:3.11-slim
}
cmd_health() {
info "检查服务健康状态..."
local services=("db:8005" "ai_review:8007" "dnfs:8006")
for svc in "${services[@]}"; do
IFS=':' read -r name port <<< "$svc"
if nc -z 127.0.0.1 "$port" 2>/dev/null; then
echo -e " ${GREEN}✓${NC} $name :$port 健康"
else
echo -e " ${RED}✗${NC} $name :$port 不可达"
fi
done
}
# ── 数据库管理命令 ──────────────────────────────────────────────
DB_CONTAINER="micro-db"
_check_db_running() {
if ! docker ps --format '{{.Names}}' | grep -q "^${DB_CONTAINER}$"; then
error "db 容器未运行,请先启动服务: ./docker.sh up"
fi
}
cmd_db_info() {
_check_db_running
info "数据库信息:"
docker_compose exec db python db_tools.py info
}
cmd_db_backup() {
_check_db_running
local backup_file="${1:-}"
if [ -z "$backup_file" ]; then
backup_file="backup_$(date +%Y%m%d_%H%M%S).db"
fi
info "执行数据库备份..."
# 先做 WAL checkpoint 确保数据完整
docker_compose exec db python db_tools.py wal-checkpoint
# 备份到容器内的 /app/backups 目录(映射到宿主机 ./backups)
docker_compose exec db python db_tools.py backup "/app/backups/$backup_file"
echo ""
info "备份文件: ./backups/$backup_file"
ls -lh "./backups/$backup_file" 2>/dev/null || info "(文件已写入容器 /app/backups/) "
}
cmd_db_export() {
_check_db_running
local export_file="${1:-}"
if [ -z "$export_file" ]; then
export_file="export_$(date +%Y%m%d_%H%M%S).json"
fi
info "导出数据库为 JSON..."
docker_compose exec db python db_tools.py export "/app/backups/$export_file"
echo ""
info "导出文件: ./backups/$export_file"
}
cmd_db_import() {
local import_file="$1"
if [ -z "$import_file" ]; then
error "用法: ./docker.sh db-import <json文件路径>"
fi
if [ ! -f "./backups/$import_file" ] && [ ! -f "$import_file" ]; then
# 检查是否在backups目录
error "导入文件不存在: $import_file (请放在 ./backups/ 目录下或提供绝对路径)"
fi
_check_db_running
local container_path="/app/backups/$(basename "$import_file")"
# 如果是宿主机路径且不在backups下,先复制到backups
if [ -f "$import_file" ] && [ ! -f "./backups/$(basename "$import_file")" ]; then
warn "复制文件到 backups 目录..."
cp "$import_file" "./backups/"
fi
warn "即将导入数据,现有数据将被覆盖!"
read -p "确认继续? [y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
# 先备份当前数据
cmd_db_backup "before_import_$(date +%Y%m%d_%H%M%S).db"
info "开始导入..."
docker_compose exec db python db_tools.py import "$container_path"
else
info "已取消"
fi
}
cmd_db_vacuum() {
_check_db_running
info "执行 VACUUM 压缩数据库..."
docker_compose exec db python db_tools.py vacuum
}
cmd_db_restore() {
local backup_file="$1"
if [ -z "$backup_file" ]; then
error "用法: ./docker.sh db-restore <备份文件路径> (从 ./backups/ 目录)"
error "示例: ./docker.sh db-restore backup_20260730_120000.db"
fi
local backup_path="./backups/$backup_file"
if [ ! -f "$backup_path" ]; then
# 尝试绝对路径
if [ -f "$backup_file" ]; then
backup_path="$backup_file"
else
error "备份文件不存在: $backup_file"
fi
fi
_check_db_running
warn "即将从备份恢复数据库,当前数据将被覆盖!"
warn "备份文件: $backup_path"
read -p "确认继续? [y/N] 输入 YES 确认: " -r
echo
if [[ "$REPLY" == "YES" ]]; then
info "停止 dnfs 和 ai_review 服务..."
docker_compose stop dnfs ai_review
info "复制备份文件到容器..."
docker cp "$backup_path" "$DB_CONTAINER:/app/data/database.db"
info "重启 db 服务..."
docker_compose restart db
# 等待db健康
info "等待 db 服务恢复..."
sleep 5
info "启动其他服务..."
docker_compose start dnfs ai_review
info "恢复完成!"
else
info "已取消"
fi
}
cmd_db_list_backups() {
info "备份文件列表 (./backups/):"
if [ -d "./backups" ]; then
ls -lhS ./backups/ 2>/dev/null | grep -v "total" | grep -v ".gitkeep" || echo " (无备份文件)"
else
echo " backups 目录不存在"
fi
}
usage() {
echo "微服务容器化管理脚本"
echo ""
echo "用法: ./docker.sh <command> [options]"
echo ""
echo "── 服务管理 ──"
echo " build 构建所有服务镜像"
echo " up 启动所有服务(后台运行)"
echo " down 停止并移除所有容器"
echo " start 启动已停止的容器"
echo " stop 停止运行中的容器"
echo " restart 重启服务"
echo " ps 查看服务状态"
echo " logs [svc] 查看日志(默认所有服务,可指定服务名)"
echo " shell [svc] 进入容器shell(默认dnfs)"
echo " rebuild 重新构建(无缓存)并启动"
echo " health 检查服务健康状态"
echo " pull 拉取最新基础镜像"
echo " clean 停止并删除所有容器+数据卷(危险!)"
echo ""
echo "── 数据库管理 (SQLite) ──"
echo " db-info 查看数据库信息和表统计"
echo " db-backup [file] 备份数据库(.db 二进制文件,输出到 ./backups/)"
echo " db-export [file] 导出数据为 JSON(跨平台传输,输出到 ./backups/)"
echo " db-import <file> 从 JSON 导入数据(文件放在 ./backups/ 下)"
echo " db-restore <file> 从 .db 备份文件恢复"
echo " db-vacuum VACUUM 压缩数据库"
echo " db-ls 列出备份文件"
echo ""
echo "示例:"
echo " ./docker.sh build dnfs # 仅构建dnfs服务"
echo " ./docker.sh logs dnfs # 查看dnfs日志"
echo " ./docker.sh shell db # 进入db容器"
echo " ./docker.sh db-backup # 立即备份"
echo " ./docker.sh db-export # 导出JSON用于迁移"
echo " ./docker.sh db-ls # 查看现有备份"
echo ""
}
# 主逻辑
check_docker
case "${1:-}" in
build)
shift
cmd_build "$@"
;;
up)
shift
cmd_up "$@"
;;
down)
shift
cmd_down "$@"
;;
start)
shift
cmd_start "$@"
;;
stop)
shift
cmd_stop "$@"
;;
restart)
shift
cmd_restart "$@"
;;
ps|status)
cmd_ps
;;
logs)
shift
cmd_logs "$@"
;;
shell)
shift
cmd_shell "$@"
;;
rebuild)
shift
cmd_rebuild "$@"
;;
health)
cmd_health
;;
pull)
cmd_pull
;;
clean)
cmd_clean
;;
# ── 数据库管理命令 ──
db-info|dbinfo)
cmd_db_info
;;
db-backup|dbbackup)
shift
cmd_db_backup "$@"
;;
db-export|dbexport)
shift
cmd_db_export "$@"
;;
db-import|dbimport)
shift
cmd_db_import "$@"
;;
db-restore|dbrestore)
shift
cmd_db_restore "$@"
;;
db-vacuum|dbvacuum)
cmd_db_vacuum
;;
db-ls|dbls)
cmd_db_list_backups
;;
*)
usage
exit 1
;;
esac