673 lines
20 KiB
Bash
Executable File
673 lines
20 KiB
Bash
Executable File
#!/bin/bash
|
||
# ===================================================================
|
||
# TopFans 打包上传部署脚本
|
||
# 功能:
|
||
# - 本地:构建镜像 → 推送到镜像仓库
|
||
# - 远程:拉取镜像 → 启动服务
|
||
# - 回滚:回滚到指定版本
|
||
# - 配置:快速上传配置文件、重启服务
|
||
# ===================================================================
|
||
#
|
||
# 使用前提:
|
||
# 1. 已安装 Docker
|
||
# 2. 已创建阿里云容器镜像仓库
|
||
# 3. 服务器已配置 SSH 免密登录
|
||
#
|
||
# 使用方式:
|
||
# # ========== 完整部署流程 ==========
|
||
# # 本地构建镜像
|
||
# ./deploy.sh build v1.0.0
|
||
#
|
||
# # 上传镜像到服务器(会自动跳过未变化的镜像)
|
||
# ./deploy.sh push v1.0.0
|
||
#
|
||
# # 远程部署
|
||
# ./deploy.sh deploy v1.0.0
|
||
#
|
||
# # 一键构建 + 推送 + 部署
|
||
# ./deploy.sh all v1.0.0
|
||
#
|
||
# # ========== 配置更新(不重新构建镜像)==========
|
||
# # 修改 .env.prod 或 docker-compose.prod.yml 后:
|
||
# ./deploy.sh upload-config --server 101.132.250.62
|
||
#
|
||
# # 上传配置并重启服务
|
||
# ./deploy.sh upload-config --server 101.132.250.62 && ./deploy.sh restart --server 101.132.250.62
|
||
#
|
||
# # ========== 其他命令 ==========
|
||
# # 回滚到指定版本
|
||
# ./deploy.sh rollback v0.9.0
|
||
#
|
||
# # 查看部署历史
|
||
# ./deploy.sh history
|
||
#
|
||
# # 清理本地镜像
|
||
# ./deploy.sh clean
|
||
#
|
||
# # ========== 服务器信息 ==========
|
||
# SERVER_HOST="101.132.250.62"
|
||
# SERVER_USER="root"
|
||
# SERVER_PASSWORD=">n73qBnCja-,#VF+Wq"
|
||
# SERVER_PATH="/opt/topfans/docker"
|
||
#
|
||
# ===================================================================
|
||
|
||
set -e
|
||
|
||
# ==================== 颜色定义 ====================
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
CYAN='\033[0;36m'
|
||
MAGENTA='\033[0;35m'
|
||
NC='\033[0m'
|
||
|
||
# ==================== 路径配置 ====================
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
cd "$SCRIPT_DIR"
|
||
|
||
# ==================== 镜像配置 ====================
|
||
# 本地构建后打包传输到服务器,不需要镜像仓库
|
||
SERVICES=(
|
||
"gateway"
|
||
"userservice"
|
||
"socialservice"
|
||
"assetservice"
|
||
"galleryservice"
|
||
"activityservice"
|
||
)
|
||
|
||
# ==================== 服务器配置 ====================
|
||
# ⚠️ 修改为你的服务器信息
|
||
SERVER_HOST="101.132.250.62" # 服务器 IP 或域名
|
||
SERVER_PORT="22" # SSH 端口
|
||
SERVER_USER="root" # SSH 用户名
|
||
SERVER_PASSWORD=">n73qBnCja-,#VF+Wq" # 服务器密码
|
||
SERVER_PATH="/opt/topfans/docker" # 服务器上 docker 目录路径
|
||
|
||
# ==================== SSH 别名 ====================
|
||
# 使用 sshpass 执行 SSH 命令
|
||
ssh_cmd() {
|
||
sshpass -p "$SERVER_PASSWORD" ssh -o StrictHostKeyChecking=no -p "$SERVER_PORT" "$SERVER_USER@$SERVER_HOST" "$@"
|
||
}
|
||
ssh_cmd_batch() {
|
||
sshpass -p "$SERVER_PASSWORD" ssh -o StrictHostKeyChecking=no -p "$SERVER_PORT" "$SERVER_USER@$SERVER_HOST" "$@"
|
||
}
|
||
scp_cmd() {
|
||
sshpass -p "$SERVER_PASSWORD" scp -P "$SERVER_PORT" "$@"
|
||
}
|
||
|
||
# ==================== 打印函数 ====================
|
||
print_step() {
|
||
echo ""
|
||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
echo -e "${BLUE} $1${NC}"
|
||
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||
}
|
||
|
||
print_msg() {
|
||
local color=$1
|
||
local msg=$2
|
||
echo -e "${color}${msg}${NC}"
|
||
}
|
||
|
||
# ==================== 帮助信息 ====================
|
||
show_help() {
|
||
cat << EOF
|
||
${MAGENTA}TopFans 部署脚本${NC}
|
||
|
||
${YELLOW}用法:${NC}
|
||
$0 <命令> [版本号] [选项]
|
||
|
||
${YELLOW}命令:${NC}
|
||
${GREEN}build${NC} <版本号> 本地构建镜像并打包传输到服务器
|
||
${GREEN}deploy${NC} <版本号> 远程部署(加载镜像 + 启动服务)
|
||
${GREEN}rollback${NC} <版本号> 回滚到指定版本
|
||
${GREEN}history${NC} 查看部署历史
|
||
${GREEN}all${NC} <版本号> 一键构建 + 传输 + 部署
|
||
${GREEN}clean${NC} 清理本地镜像(谨慎使用)
|
||
${GREEN}upload-config${NC} 仅上传配置文件(不重新构建镜像)
|
||
${GREEN}restart${NC} 重启服务(不重新构建/上传)
|
||
|
||
${YELLOW}选项:${NC}
|
||
--server <IP> 指定服务器(覆盖配置文件)
|
||
--skip-build 跳过构建(用于已构建过的情况)
|
||
--skip-push 跳过传输(用于已传输过的情况)
|
||
--force 强制执行(不确认)
|
||
--help, -h 显示此帮助
|
||
|
||
${YELLOW}示例:${NC}
|
||
$0 build v1.0.0 # 构建并打包传输到服务器
|
||
$0 deploy v1.0.0 --server 192.168.1.100 # 部署到服务器
|
||
$0 rollback v0.9.0 # 回滚到 v0.9.0
|
||
$0 history # 查看部署历史
|
||
$0 all v1.0.0 --server 192.168.1.100 # 一键完成所有操作
|
||
$0 upload-config --server 192.168.1.100 # 仅上传配置
|
||
$0 restart --server 192.168.1.100 # 重启服务
|
||
|
||
${YELLOW}前提准备:${NC}
|
||
1. 修改 SERVER_HOST 为你的服务器 IP
|
||
2. 配置服务器 SSH 免密登录(建议)
|
||
|
||
EOF
|
||
}
|
||
|
||
# ==================== 配置检查 ====================
|
||
check_config() {
|
||
local errors=0
|
||
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
print_msg "$YELLOW" "警告: SERVER_HOST 未设置,远程部署功能将不可用"
|
||
fi
|
||
|
||
return $errors
|
||
}
|
||
|
||
# ==================== 1. 构建镜像 ====================
|
||
do_build() {
|
||
print_step "🔨 构建 Docker 镜像"
|
||
|
||
# 调用构建脚本
|
||
# ./build.sh --no-cache
|
||
./build.sh
|
||
|
||
if [ $? -ne 0 ]; then
|
||
print_msg "$RED" "❌ 构建失败"
|
||
exit 1
|
||
fi
|
||
|
||
print_msg "$GREEN" "✅ 镜像构建完成"
|
||
}
|
||
|
||
# ==================== 2. 打包并传输镜像到服务器 ====================
|
||
do_push() {
|
||
local version=$1
|
||
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
print_msg "$RED" "错误: 请设置 SERVER_HOST"
|
||
exit 1
|
||
fi
|
||
|
||
print_step "📦 打包镜像为 tar 文件"
|
||
|
||
local tmp_dir="/tmp/topfans-images-${version}"
|
||
mkdir -p "${tmp_dir}"
|
||
|
||
local failed=()
|
||
local packed=()
|
||
|
||
for SERVICE in "${SERVICES[@]}"; do
|
||
local local_image="topfans/${SERVICE}:latest"
|
||
local tar_file="${tmp_dir}/${SERVICE}.tar"
|
||
|
||
echo ""
|
||
print_msg "$YELLOW" "处理 ${SERVICE}..."
|
||
|
||
if docker save "${local_image}" -o "${tar_file}"; then
|
||
echo -e " ${GREEN}✅ 已打包${NC}"
|
||
packed+=("${SERVICE}")
|
||
else
|
||
echo -e " ${RED}❌ 打包失败${NC}"
|
||
failed+=("${SERVICE}")
|
||
fi
|
||
done
|
||
|
||
if [ ${#failed[@]} -ne 0 ]; then
|
||
print_msg "$RED" "❌ 打包失败: ${failed[*]}"
|
||
rm -rf "${tmp_dir}"
|
||
exit 1
|
||
fi
|
||
|
||
print_msg "$GREEN" "✅ 全部打包完成"
|
||
|
||
# 计算本地镜像的 MD5 哈希
|
||
print_step "🔍 检查镜像差异"
|
||
local local_hash=""
|
||
for SERVICE in "${packed[@]}"; do
|
||
local tar_file="${tmp_dir}/${SERVICE}.tar"
|
||
local file_hash=$(md5 -q "${tar_file}")
|
||
local image_hash=$(docker images -q "topfans/${SERVICE}:latest")
|
||
local combo="${file_hash}:${image_hash}"
|
||
if [ -z "$local_hash" ]; then
|
||
local_hash="$combo"
|
||
else
|
||
local_hash="${local_hash}-${combo}"
|
||
fi
|
||
done
|
||
local local_md5=$(echo "$local_hash" | md5)
|
||
|
||
print_msg "$YELLOW" "本地镜像 MD5: ${local_md5:0:16}..."
|
||
|
||
# 获取服务器上的哈希
|
||
local server_hash=$(ssh_cmd "cat ${SERVER_PATH}/images/.images_hash 2>/dev/null || echo ''")
|
||
|
||
print_step "📤 传输镜像到服务器"
|
||
|
||
# 检查是否需要上传
|
||
if [ "$local_md5" = "$server_hash" ]; then
|
||
print_msg "$GREEN" "✅ 镜像未变化,跳过上传"
|
||
rm -rf "${tmp_dir}"
|
||
return 0
|
||
fi
|
||
|
||
print_msg "$YELLOW" "正在传输到 ${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}..."
|
||
|
||
# 创建服务器目录
|
||
ssh_cmd "mkdir -p ${SERVER_PATH}/images && rm -f ${SERVER_PATH}/images/*.tar 2>/dev/null || true"
|
||
|
||
# 传输 tar 文件
|
||
for SERVICE in "${packed[@]}"; do
|
||
local tar_file="${tmp_dir}/${SERVICE}.tar"
|
||
print_msg "$YELLOW" "传输 ${SERVICE}.tar..."
|
||
scp_cmd "${tar_file}" "${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/images/"
|
||
print_msg "$GREEN" "✅ ${SERVICE}.tar 传输完成"
|
||
done
|
||
|
||
# 保存哈希到服务器
|
||
ssh_cmd "echo '$local_md5' > ${SERVER_PATH}/images/.images_hash"
|
||
|
||
# 清理本地临时文件
|
||
rm -rf "${tmp_dir}"
|
||
|
||
print_msg "$GREEN" "✅ 镜像传输完成"
|
||
}
|
||
|
||
# ==================== 3. 远程部署 ====================
|
||
do_deploy() {
|
||
local version=$1
|
||
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
print_msg "$RED" "错误: 请设置 SERVER_HOST(服务器 IP)"
|
||
print_msg "$YELLOW" "使用方法: $0 deploy ${version} --server <IP>"
|
||
exit 1
|
||
fi
|
||
|
||
print_step "🚀 远程部署到 ${SERVER_HOST}"
|
||
|
||
print_msg "$YELLOW" "检查 Docker 环境..."
|
||
|
||
sshpass -p "$SERVER_PASSWORD" ssh -T -p "${SERVER_PORT}" "${SERVER_USER}@${SERVER_HOST}" << 'ENDSSH'
|
||
set -e
|
||
|
||
echo '=== 1. 检查/安装 Docker 环境 ==='
|
||
if ! command -v docker &> /dev/null; then
|
||
echo '📦 Docker 未安装,开始安装...'
|
||
|
||
# 使用阿里云镜像源安装 Docker
|
||
yum remove -y docker docker-common docker-selinux docker-engine-selinux docker-engine docker-ce 2>/dev/null || true
|
||
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
|
||
yum install -y docker-ce docker-ce-cli containerd.io
|
||
|
||
systemctl start docker
|
||
systemctl enable docker
|
||
echo '✅ Docker 安装成功'
|
||
fi
|
||
|
||
if ! command -v docker-compose &> /dev/null; then
|
||
if docker compose version &> /dev/null; then
|
||
echo '📦 创建 docker-compose 软链接...'
|
||
ln -sf /usr/libexec/docker/cli-plugins/docker-compose /usr/local/bin/docker-compose
|
||
else
|
||
echo '⚠️ docker-compose 未安装'
|
||
fi
|
||
fi
|
||
|
||
# 配置 Docker 镜像加速器
|
||
echo '📦 配置 Docker 镜像加速器...'
|
||
mkdir -p /etc/docker
|
||
cat > /etc/docker/daemon.json << 'DOCKER_EOF'
|
||
{
|
||
"registry-mirrors": [
|
||
"https://docker.1ms.run",
|
||
"https://docker.xuanyuan.me"
|
||
]
|
||
}
|
||
DOCKER_EOF
|
||
systemctl restart docker
|
||
echo '✅ 镜像加速器配置完成'
|
||
|
||
echo '✅ Docker 环境就绪'
|
||
ENDSSH
|
||
|
||
# 确保服务器目录存在
|
||
ssh_cmd "mkdir -p ${SERVER_PATH}/images"
|
||
print_msg "$GREEN" "✅ 服务器目录就绪"
|
||
|
||
# 上传配置文件
|
||
print_step "📤 上传配置文件"
|
||
print_msg "$YELLOW" "上传 docker-compose.prod.yml 和 .env.prod..."
|
||
scp_cmd "${SCRIPT_DIR}/docker-compose.prod.yml" "${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/"
|
||
scp_cmd "${SCRIPT_DIR}/.env.prod" "${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/"
|
||
scp_cmd "${SCRIPT_DIR}/init-db.sql" "${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/"
|
||
print_msg "$GREEN" "✅ 配置文件上传完成"
|
||
|
||
# 从 tar 文件加载镜像
|
||
print_step "📥 从 tar 文件加载镜像"
|
||
for SERVICE in "${SERVICES[@]}"; do
|
||
print_msg "$YELLOW" "加载 ${SERVICE}..."
|
||
ssh_cmd "docker load -i ${SERVER_PATH}/images/${SERVICE}.tar"
|
||
print_msg "$GREEN" "✅ ${SERVICE} 加载完成"
|
||
done
|
||
|
||
# 打 latest 标签
|
||
print_msg "$YELLOW" "打 latest 标签..."
|
||
ssh_cmd "
|
||
for service in ${SERVICES[*]}; do
|
||
docker tag topfans/\${service}:latest topfans/\${service}:v${version}
|
||
docker tag topfans/\${service}:latest topfans/\${service}:latest
|
||
done
|
||
echo '标签完成'
|
||
"
|
||
|
||
# 停止旧服务并清理
|
||
print_msg "$YELLOW" "停止旧服务..."
|
||
ssh_cmd "
|
||
cd ${SERVER_PATH} && \
|
||
docker-compose -f docker-compose.prod.yml down 2>/dev/null || true
|
||
|
||
# 停止并删除所有 topfans 容器
|
||
docker ps -a --filter 'name=topfans-' -q | xargs -r docker stop 2>/dev/null || true
|
||
docker ps -a --filter 'name=topfans-' -q | xargs -r docker rm 2>/dev/null || true
|
||
|
||
# 清理可能的端口占用 (8080, 5432)
|
||
fuser -k 8080/tcp 2>/dev/null || true
|
||
fuser -k 5432/tcp 2>/dev/null || true
|
||
"
|
||
|
||
# 启动新服务
|
||
print_msg "$YELLOW" "启动服务..."
|
||
ssh_cmd "
|
||
cd ${SERVER_PATH} && \
|
||
docker-compose -f docker-compose.prod.yml --profile prod up -d
|
||
"
|
||
|
||
# 等待并检查
|
||
print_msg "$YELLOW" "等待服务启动 (20s)..."
|
||
sleep 20
|
||
|
||
print_step "📊 部署结果"
|
||
|
||
ssh_cmd "
|
||
echo ''
|
||
docker-compose -f docker-compose.prod.yml ps
|
||
echo ''
|
||
echo -n 'Gateway 健康检查: '
|
||
curl -s http://localhost:8080/health > /dev/null && echo '✅ OK' || echo '⚠️ 检查失败'
|
||
"
|
||
|
||
print_msg "$GREEN" "✅ 远程部署完成"
|
||
}
|
||
|
||
# ==================== 4. 回滚 ====================
|
||
do_rollback() {
|
||
local version=$1
|
||
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
print_msg "$RED" "错误: 请设置 SERVER_HOST"
|
||
exit 1
|
||
fi
|
||
|
||
print_step "🔄 回滚到版本 v${version}"
|
||
|
||
print_msg "$YELLOW" "正在回滚 ${SERVER_HOST} 上的服务..."
|
||
|
||
# 停止服务
|
||
print_msg "$YELLOW" "停止服务..."
|
||
ssh_cmd "
|
||
cd ${SERVER_PATH} && \
|
||
docker-compose -f docker-compose.prod.yml down
|
||
"
|
||
|
||
# 从已有的 tar 文件加载镜像并打标签
|
||
for SERVICE in "${SERVICES[@]}"; do
|
||
print_msg "$YELLOW" "加载 ${SERVICE}:v${version}..."
|
||
ssh_cmd "
|
||
docker load -i ${SERVER_PATH}/images/${SERVICE}.tar
|
||
docker tag topfans/${SERVICE}:latest topfans/${SERVICE}:v${version}
|
||
docker tag topfans/${SERVICE}:latest topfans/${SERVICE}:latest
|
||
"
|
||
print_msg "$GREEN" "✅ ${SERVICE} 回滚完成"
|
||
done
|
||
|
||
# 启动服务
|
||
print_msg "$YELLOW" "启动服务..."
|
||
ssh_cmd "
|
||
cd ${SERVER_PATH} && \
|
||
docker-compose -f docker-compose.prod.yml --profile prod up -d
|
||
"
|
||
|
||
sleep 10
|
||
|
||
print_step "📊 回滚结果"
|
||
|
||
ssh_cmd "
|
||
echo ''
|
||
docker-compose -f docker-compose.prod.yml ps
|
||
echo ''
|
||
echo -n 'Gateway 健康检查: '
|
||
curl -s http://localhost:8080/health > /dev/null && echo '✅ OK' || echo '⚠️ 检查失败'
|
||
"
|
||
|
||
print_msg "$GREEN" "✅ 回滚完成!当前版本: v${version}"
|
||
}
|
||
|
||
# ==================== 5. 查看历史 ====================
|
||
do_history() {
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
print_msg "$RED" "错误: 请设置 SERVER_HOST"
|
||
exit 1
|
||
fi
|
||
|
||
print_step "📜 部署历史"
|
||
|
||
ssh_cmd "
|
||
if [ -f ${SERVER_PATH}/deploy_history.json ]; then
|
||
cat ${SERVER_PATH}/deploy_history.json
|
||
else
|
||
echo '暂无部署历史'
|
||
fi
|
||
"
|
||
|
||
echo ""
|
||
print_msg "$YELLOW" "查看实时日志: ssh ${SERVER_USER}@${SERVER_HOST} 'docker-compose -f ${SERVER_PATH}/docker-compose.prod.yml logs -f'"
|
||
}
|
||
|
||
# ==================== 6. 清理本地镜像 ====================
|
||
do_clean() {
|
||
print_step "🧹 清理本地镜像"
|
||
|
||
print_msg "$RED" "警告: 将删除所有 topfans 镜像"
|
||
print_msg "$YELLOW" "列出当前镜像:"
|
||
|
||
docker images | grep topfans || echo "无 topfans 镜像"
|
||
|
||
echo ""
|
||
read -p "确认删除? (y/N): " confirm
|
||
if [ "$confirm" != "y" ]; then
|
||
print_msg "$YELLOW" "已取消"
|
||
exit 0
|
||
fi
|
||
|
||
docker images | grep topfans | awk '{print $3}' | xargs -r docker rmi -f
|
||
print_msg "$GREEN" "✅ 清理完成"
|
||
}
|
||
|
||
# ==================== 主函数 ====================
|
||
main() {
|
||
if [ $# -eq 0 ]; then
|
||
show_help
|
||
exit 0
|
||
fi
|
||
|
||
local command=$1
|
||
shift
|
||
|
||
local version=""
|
||
local skip_build=false
|
||
local skip_push=false
|
||
local force=false
|
||
|
||
# 解析剩余参数
|
||
while [[ $# -gt 0 ]]; do
|
||
case $1 in
|
||
--server)
|
||
SERVER_HOST="$2"
|
||
shift 2
|
||
;;
|
||
--skip-build)
|
||
skip_build=true
|
||
shift
|
||
;;
|
||
--skip-push)
|
||
skip_push=true
|
||
shift
|
||
;;
|
||
--force)
|
||
force=true
|
||
shift
|
||
;;
|
||
-h|--help)
|
||
show_help
|
||
exit 0
|
||
;;
|
||
v*)
|
||
version="${1#v}"
|
||
shift
|
||
;;
|
||
*)
|
||
echo -e "${RED}错误: 未知参数 '$1'${NC}"
|
||
exit 1
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# 检查配置
|
||
check_config || true
|
||
|
||
case $command in
|
||
build)
|
||
# 构建 + 推送
|
||
if [ -z "$version" ]; then
|
||
echo -e "${RED}错误: 请指定版本号${NC}"
|
||
echo "用法: $0 build v1.0.0"
|
||
exit 1
|
||
fi
|
||
|
||
echo -e "${CYAN}版本: v${version}${NC}"
|
||
echo -e "${CYAN}目标: ${SERVER_USER}@${SERVER_HOST}${NC}"
|
||
|
||
if [ "$skip_build" = false ]; then
|
||
do_build
|
||
fi
|
||
|
||
if [ "$skip_push" = false ]; then
|
||
do_push "$version"
|
||
fi
|
||
;;
|
||
|
||
deploy)
|
||
# 远程部署
|
||
if [ -z "$version" ]; then
|
||
echo -e "${RED}错误: 请指定版本号${NC}"
|
||
echo "用法: $0 deploy v1.0.0"
|
||
exit 1
|
||
fi
|
||
|
||
echo -e "${CYAN}版本: v${version}${NC}"
|
||
echo -e "${CYAN}目标: ${SERVER_USER}@${SERVER_HOST}${NC}"
|
||
|
||
do_deploy "$version"
|
||
;;
|
||
|
||
rollback)
|
||
# 回滚
|
||
if [ -z "$version" ]; then
|
||
echo -e "${RED}错误: 请指定要回滚的版本${NC}"
|
||
echo "用法: $0 rollback v1.0.0"
|
||
exit 1
|
||
fi
|
||
|
||
echo -e "${RED}⚠️ 确认回滚到 v${version}?${NC}"
|
||
[ "$force" = false ] && read -p "确认? (y/N): " confirm && [ "$confirm" != "y" ] && exit 0
|
||
|
||
do_rollback "$version"
|
||
;;
|
||
|
||
history)
|
||
do_history
|
||
;;
|
||
|
||
clean)
|
||
do_clean
|
||
;;
|
||
|
||
upload-config)
|
||
# 上传配置文件
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
print_msg "$RED" "错误: 请设置 SERVER_HOST 或使用 --server 参数"
|
||
exit 1
|
||
fi
|
||
|
||
print_step "📤 上传配置文件到 ${SERVER_HOST}"
|
||
|
||
scp_cmd "${SCRIPT_DIR}/docker-compose.prod.yml" "${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/"
|
||
print_msg "$GREEN" "✅ docker-compose.prod.yml 上传完成"
|
||
|
||
scp_cmd "${SCRIPT_DIR}/.env.prod" "${SERVER_USER}@${SERVER_HOST}:${SERVER_PATH}/"
|
||
print_msg "$GREEN" "✅ .env.prod 上传完成"
|
||
|
||
print_msg "$YELLOW" "请运行以下命令重启服务:"
|
||
print_msg "$CYAN" "ssh ${SERVER_USER}@${SERVER_HOST} 'cd ${SERVER_PATH} && docker-compose -f docker-compose.prod.yml down && docker-compose -f docker-compose.prod.yml up -d'"
|
||
;;
|
||
|
||
restart)
|
||
# 重启服务
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
print_msg "$RED" "错误: 请设置 SERVER_HOST 或使用 --server 参数"
|
||
exit 1
|
||
fi
|
||
|
||
print_step "🔄 重启服务"
|
||
ssh_cmd "cd ${SERVER_PATH} && docker-compose -f docker-compose.prod.yml down && docker-compose -f docker-compose.prod.yml up -d"
|
||
sleep 10
|
||
print_msg "$GREEN" "✅ 服务重启完成"
|
||
;;
|
||
|
||
all)
|
||
# 构建 + 推送 + 部署
|
||
if [ -z "$version" ]; then
|
||
echo -e "${RED}错误: 请指定版本号${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
if [ -z "$SERVER_HOST" ]; then
|
||
echo -e "${RED}错误: 请设置 SERVER_HOST 或使用 --server 参数${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
echo -e "${MAGENTA}一键部署流程:${NC}"
|
||
echo " 1. 构建镜像"
|
||
echo " 2. 打包传输到服务器"
|
||
echo " 3. 部署到 ${SERVER_HOST}"
|
||
echo ""
|
||
|
||
[ "$force" = false ] && read -p "继续? (y/N): " confirm && [ "$confirm" != "y" ] && exit 0
|
||
|
||
do_build
|
||
do_push "$version"
|
||
do_deploy "$version"
|
||
|
||
print_step "🎉 全部完成!"
|
||
;;
|
||
|
||
*)
|
||
echo -e "${RED}错误: 未知命令 '$command'${NC}"
|
||
show_help
|
||
exit 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
main "$@"
|