项目文件夹

文件
2026-07-13 12:35:20 +08:00

220 行
6.8 KiB
Bash
可执行文件

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
#!/bin/bash
# Xiaozhi Client Docker 启动脚本
# 使用改进的挂载点配置,支持自定义镜像版本
set -e
# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 配置
CONTAINER_NAME="xiaozhi-client"
IMAGE_NAME="shenjingnan/xiaozhi-client"
IMAGE_TAG="latest"
WORKSPACE_DIR="$HOME/xiaozhi-client"
WEB_PORT="9999"
HTTP_PORT="3000"
NETWORK_NAME="xiaozhi-network"
# 显示帮助信息
show_help() {
echo -e "${BLUE}Xiaozhi Client Docker 启动脚本${NC}"
echo "=================================="
echo ""
echo "使用方法:"
echo " $0 # 使用默认版本 (latest)"
echo " $0 <version> # 通过位置参数指定版本号"
echo " $0 --version <version> # 通过命名参数指定版本号"
echo " $0 --help|-h # 显示此帮助信息"
echo ""
echo "版本号格式示例:"
echo " • 语义化版本: v1.2.3, 1.2.3"
echo " • 预发布版本: v1.2.3-alpha, v1.2.3-beta.1"
echo " • 特殊标签: latest, stable, dev, main"
echo " • Git commit: abc123f"
echo ""
echo "使用示例:"
echo " $0 # 使用 latest 版本"
echo " $0 v1.2.3 # 使用 v1.2.3 版本"
echo " $0 --version stable # 使用 stable 版本"
echo ""
}
# 验证版本号格式
validate_version() {
local version="$1"
if [[ "$version" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9\.-]+)?(\+[a-zA-Z0-9\.-]+)?$ ]] || \
[[ "$version" =~ ^(latest|stable|dev|main)$ ]] || \
[[ "$version" =~ ^[a-f0-9]{6,40}$ ]]; then
return 0
else
return 1
fi
}
# 参数解析
IMAGE_TAG_SET=false
while [[ $# -gt 0 ]]; do
case $1 in
--help|-h)
show_help
exit 0
;;
--version)
if [[ -n "$2" && ! "$2" =~ ^- ]]; then
IMAGE_TAG="$2"
IMAGE_TAG_SET=true
shift 2
else
echo -e "${RED}❌ 错误:--version 参数需要指定版本号${NC}"
echo ""
show_help
exit 1
fi
;;
-*)
echo -e "${RED}❌ 错误:未知参数 $1${NC}"
echo ""
show_help
exit 1
;;
*)
if [[ "$IMAGE_TAG_SET" == "false" ]]; then
IMAGE_TAG="$1"
IMAGE_TAG_SET=true
shift
else
echo -e "${RED}❌ 错误:只能指定一个版本号${NC}"
echo ""
show_help
exit 1
fi
;;
esac
done
# 验证版本号格式
if ! validate_version "$IMAGE_TAG"; then
echo -e "${RED}❌ 错误:无效的版本号格式: $IMAGE_TAG${NC}"
echo ""
echo "支持的版本号格式:"
echo " • 语义化版本: v1.2.3, 1.2.3"
echo " • 预发布版本: v1.2.3-alpha, v1.2.3-beta.1"
echo " • 特殊标签: latest, stable, dev, main"
echo " • Git commit: abc123f"
echo ""
show_help
exit 1
fi
echo -e "${BLUE}🚀 Xiaozhi Client Docker 启动脚本${NC}"
echo "=================================="
echo -e "${BLUE}📦 使用镜像版本: ${GREEN}$IMAGE_TAG${NC}"
echo ""
# 检查 Docker 是否安装
if ! command -v docker &> /dev/null; then
echo -e "${RED}❌ Docker 未安装,请先安装 Docker${NC}"
exit 1
fi
# 创建工作目录
echo -e "${YELLOW}📁 创建工作目录: $WORKSPACE_DIR${NC}"
mkdir -p "$WORKSPACE_DIR"
# 创建支持 IPv6 的网络(如果不存在)
echo -e "${YELLOW}🌐 配置 Docker 网络(支持 IPv4 和 IPv6${NC}"
if ! docker network inspect "$NETWORK_NAME" &>/dev/null; then
# 检查 Docker 是否启用了 IPv6
if docker info 2>/dev/null | grep -q "IPv6: true"; then
echo -e "${GREEN}✓ Docker 已启用 IPv6,创建双栈网络${NC}"
docker network create \
--driver bridge \
--ipv6 \
--subnet=172.20.0.0/24 \
--gateway=172.20.0.1 \
--subnet=fd00:abcd::/64 \
--gateway=fd00:abcd::1 \
"$NETWORK_NAME"
else
echo -e "${YELLOW}⚠ Docker 未启用 IPv6,创建 IPv4 网络${NC}"
echo -e "${YELLOW} 提示:如需 IPv6 支持,请配置 /etc/docker/daemon.json${NC}"
docker network create \
--driver bridge \
--subnet=172.20.0.0/24 \
--gateway=172.20.0.1 \
"$NETWORK_NAME"
fi
else
echo -e "${GREEN}✓ 网络 $NETWORK_NAME 已存在${NC}"
fi
# 停止并删除已存在的容器
if docker ps -a --format 'table {{.Names}}' | grep -q "^$CONTAINER_NAME$"; then
echo -e "${YELLOW}🛑 停止并删除已存在的容器${NC}"
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
fi
# 拉取指定版本的镜像
echo -e "${YELLOW}📥 拉取镜像: $IMAGE_NAME:$IMAGE_TAG${NC}"
docker pull "$IMAGE_NAME:$IMAGE_TAG"
# 启动容器(简化的端口映射,自动支持双栈)
echo -e "${YELLOW}🚀 启动 Xiaozhi Client 容器${NC}"
docker run -d \
--name "$CONTAINER_NAME" \
--network "$NETWORK_NAME" \
-p "$WEB_PORT:9999" \
-p "$HTTP_PORT:3000" \
-v "$WORKSPACE_DIR:/workspaces" \
-e NODE_ENV=production \
-e XIAOZHI_WORKSPACE=/workspaces \
-e XIAOZHI_CONTAINER=true \
-e XIAOZHI_CONFIG_DIR=/workspaces \
--restart unless-stopped \
"$IMAGE_NAME:$IMAGE_TAG"
# 等待容器启动
echo -e "${YELLOW}⏳ 等待容器启动...${NC}"
sleep 3
# 检查容器状态
if docker ps --format 'table {{.Names}}' | grep -q "^$CONTAINER_NAME$"; then
echo -e "${GREEN}✅ 容器启动成功!${NC}"
echo ""
echo "📋 服务信息:"
echo " • Web UI (IPv4): http://localhost:$WEB_PORT"
echo " • Web UI (IPv6): http://[::1]:$WEB_PORT"
echo " • HTTP Server: http://localhost:$HTTP_PORT"
echo " • 工作目录: $WORKSPACE_DIR"
echo " • 配置文件: $WORKSPACE_DIR/xiaozhi.config.json"
echo ""
# 显示容器的 IPv6 地址(如果有)
IPV6_ADDR=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.GlobalIPv6Address}}{{end}}' "$CONTAINER_NAME" 2>/dev/null)
if [[ -n "$IPV6_ADDR" ]]; then
echo -e " ${GREEN}✓ 容器 IPv6 地址: $IPV6_ADDR${NC}"
fi
echo ""
echo "🔧 常用命令:"
echo " • 查看日志: docker logs -f $CONTAINER_NAME"
echo " • 停止服务: docker stop $CONTAINER_NAME"
echo " • 重启服务: docker restart $CONTAINER_NAME"
echo " • 查看网络: docker network inspect $NETWORK_NAME"
echo ""
echo -e "${GREEN}🎉 现在可以访问 http://localhost:$WEB_PORT 开始配置!${NC}"
else
echo -e "${RED}❌ 容器启动失败${NC}"
echo "查看错误日志:"
docker logs "$CONTAINER_NAME"
exit 1
fi