This commit is contained in:
Joe
2026-01-16 15:49:34 +08:00
commit 550d3e1f42
380 changed files with 62024 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
# 端口配置改进说明
## ✅ 改进内容
现在所有端口配置统一在 **`scripts/deploy/deploy-config.sh`** 文件中管理,只需修改一个地方即可。
## 📝 修改端口的方法
### 方法一:修改配置文件(推荐)
编辑 `scripts/deploy/deploy-config.sh`
```bash
vim scripts/deploy/deploy-config.sh
# 修改为:
export BLUE_PORT="${BLUE_PORT:-4000}" # 蓝环境端口
export GREEN_PORT="${GREEN_PORT:-4001}" # 绿环境端口
export CONTAINER_PORT="${CONTAINER_PORT:-3000}" # 容器内部端口(通常不改)
```
### 方法二:使用环境变量(临时)
```bash
export BLUE_PORT=4000
export GREEN_PORT=4001
./scripts/deploy/docker-blue-green.sh
```
## 🔄 自动应用的文件
修改配置后,以下文件会自动使用新端口:
1.`docker-compose.blue.yml` - 蓝环境配置
2.`docker-compose.green.yml` - 绿环境配置
3.`scripts/deploy/docker-blue-green.sh` - 部署脚本
4.`scripts/deploy/rollback.sh` - 回滚脚本
5. ✅ Nginx 配置更新(如果配置了)
## 📋 配置变量说明
- **BLUE_PORT**: 蓝环境在宿主机上映射的端口(默认 3000)
- **GREEN_PORT**: 绿环境在宿主机上映射的端口(默认 3001)
- **CONTAINER_PORT**: 容器内部应用监听的端口(默认 3000,通常不需要修改)
## ⚠️ 注意事项
1. 修改端口后需要确保端口未被占用
2. 如果使用 Nginx,需要更新 Nginx 配置中的 upstream
3. 修改端口后需要重新构建和启动容器
## 🔍 检查端口占用
```bash
# 检查端口是否被占用
netstat -tlnp | grep 4000
ss -tlnp | grep 4000
```
+79
View File
@@ -0,0 +1,79 @@
# 端口配置说明
## 📍 统一配置端口
所有端口配置现在统一在 **`scripts/deploy/deploy-config.sh`** 文件中管理。
## 🔧 修改端口
只需修改 `scripts/deploy/deploy-config.sh` 文件中的端口配置:
```bash
# 编辑配置文件
vim scripts/deploy/deploy-config.sh
# 修改这些变量:
export BLUE_PORT="${BLUE_PORT:-3000}" # 蓝环境端口(宿主机端口)
export GREEN_PORT="${GREEN_PORT:-3001}" # 绿环境端口(宿主机端口)
export CONTAINER_PORT="${CONTAINER_PORT:-3000}" # 容器内部端口(应用监听端口)
```
## 📝 配置说明
- **BLUE_PORT**: 蓝环境在宿主机上映射的端口(默认 3000)
- **GREEN_PORT**: 绿环境在宿主机上映射的端口(默认 3001)
- **CONTAINER_PORT**: 容器内部应用监听的端口(默认 3000,通常不需要修改)
## 🔄 使用环境变量覆盖
也可以通过环境变量临时覆盖配置(无需修改文件):
```bash
# 临时使用其他端口
export BLUE_PORT=4000
export GREEN_PORT=4001
./scripts/deploy/docker-blue-green.sh
```
## 📋 自动应用范围
修改配置后,以下文件会自动使用新端口:
-`docker-compose.blue.yml` - 蓝环境配置
-`docker-compose.green.yml` - 绿环境配置
-`scripts/deploy/docker-blue-green.sh` - 部署脚本
-`scripts/deploy/rollback.sh` - 回滚脚本
- ✅ Nginx 配置更新(如果配置了)
## ⚠️ 注意事项
1. **容器内部端口** (`CONTAINER_PORT`) 通常不需要修改,除非应用配置了其他端口
2. **宿主机端口** (`BLUE_PORT`, `GREEN_PORT`) 需要确保端口未被占用
3. 修改端口后,如果使用 Nginx,需要更新 Nginx 配置中的 upstream
4. 修改端口后需要重新构建镜像和启动容器
## 💡 示例
### 修改为 4000 和 4001
```bash
# 编辑配置文件
vim scripts/deploy/deploy-config.sh
# 修改为:
export BLUE_PORT="${BLUE_PORT:-4000}"
export GREEN_PORT="${GREEN_PORT:-4001}"
```
### 检查端口是否被占用
```bash
# 检查端口是否被占用
netstat -tlnp | grep 4000
netstat -tlnp | grep 4001
# 或使用 ss 命令
ss -tlnp | grep 4000
ss -tlnp | grep 4001
```
+213
View File
@@ -0,0 +1,213 @@
# Docker 蓝绿部署脚本
## 文件说明
- `deploy-config.sh` - **端口配置文件**(统一管理所有端口配置)
- `docker-blue-green.sh` - 蓝绿部署主脚本,执行零停机部署
- `git-deploy.sh` - 从 Git 拉取代码并自动部署的脚本
- `rollback.sh` - 快速回滚到上一个版本
- `rollback-git.sh` - 从 Git 回滚到指定版本并部署
- `migrate.sh` - 单独执行数据库迁移脚本
- `seed.sh` - 单独执行数据填充脚本
## 端口配置
**重要:** 所有端口配置统一在 `deploy-config.sh` 文件中管理。
### 修改端口
只需修改 `scripts/deploy/deploy-config.sh` 文件:
```bash
# 编辑配置文件
vim scripts/deploy/deploy-config.sh
# 修改端口配置:
export BLUE_PORT="${BLUE_PORT:-3000}" # 蓝环境端口
export GREEN_PORT="${GREEN_PORT:-3001}" # 绿环境端口
export CONTAINER_PORT="${CONTAINER_PORT:-3000}" # 容器内部端口
```
### 通过环境变量覆盖
```bash
# 临时使用其他端口
export BLUE_PORT=4000
export GREEN_PORT=4001
./scripts/deploy/docker-blue-green.sh
```
详细说明请参考:`scripts/deploy/README-PORT-CONFIG.md`
## 使用方法
### 方式一:手动部署(已拉取代码)
```bash
cd /www/goravel-admin
chmod +x scripts/deploy/docker-blue-green.sh
./scripts/deploy/docker-blue-green.sh
```
### 方式二:从 Git 拉取并部署
```bash
# 设置环境变量(可选)
export GIT_REPO_URL="https://github.com/your-username/goravel-admin.git"
export GIT_BRANCH="main"
export DEPLOY_DIR="/www/goravel-admin"
# 执行部署
chmod +x scripts/deploy/git-deploy.sh
./scripts/deploy/git-deploy.sh
```
或者直接修改脚本中的配置:
```bash
# 编辑脚本
vim scripts/deploy/git-deploy.sh
# 修改这些变量:
# GIT_REPO_URL="你的仓库地址"
# GIT_BRANCH="main"
# DEPLOY_DIR="/www/goravel-admin"
```
## 部署流程
1. **检测当前版本** - 自动检测运行的是 blue 还是 green
2. **构建新版本** - 在备用环境构建新镜像(包含启动脚本)
3. **启动新版本** - 启动新版本容器(不同端口)
4. **自动执行迁移** - 容器启动脚本会在应用启动前自动执行数据库迁移
5. **数据填充(可选)** - 提示是否执行数据填充
6. **健康检查** - 等待新版本通过健康检查
7. **切换流量** - 更新 Nginx 配置(如果存在)
8. **停止旧版本** - 停止旧版本容器
## 数据库迁移和填充
### 自动迁移(容器启动时执行)
**重要:** 迁移在容器启动时自动执行,确保在应用启动前完成:
-**启动前执行** - 容器启动脚本会在应用启动前执行迁移,避免字段不存在错误
-**自动执行** - 无需手动操作,每次容器启动都会执行
-**幂等操作** - Goravel 的 `migrate` 命令是安全的,可以重复执行
-**失败退出** - 如果迁移失败,容器会退出,部署脚本会自动检测并回滚
- ⚙️ **可配置** - 通过环境变量 `SKIP_MIGRATE=true` 可以跳过迁移
### 数据填充
部署脚本会提示是否执行数据填充:
- ⚠️ **需要确认** - 会提示用户是否执行
- ⚠️ **可能重复** - 填充可能会重复插入数据,请谨慎使用
- 💡 **建议** - 通常只在首次部署或需要更新基础数据时执行
### 通过环境变量控制
可以通过环境变量跳过填充提示:
```bash
# 自动执行填充(不提示)
export RUN_SEED=true
./scripts/deploy/docker-blue-green.sh
# 跳过填充(不提示)
export RUN_SEED=false
./scripts/deploy/docker-blue-green.sh
```
### 单独执行迁移或填充
如果需要单独执行迁移或填充:
```bash
# 执行数据库迁移
chmod +x scripts/deploy/migrate.sh
./scripts/deploy/migrate.sh # 自动检测容器
./scripts/deploy/migrate.sh goravel-admin-blue # 指定容器
# 执行数据填充
chmod +x scripts/deploy/seed.sh
./scripts/deploy/seed.sh # 自动检测容器
./scripts/deploy/seed.sh goravel-admin-blue # 指定容器
```
## 前置要求
- Docker 和 Docker Compose 已安装
- 服务器上已配置 `.env` 文件
- 如果需要 Nginx 切换,需要配置 Nginx
## 健康检查
应用需要提供 `/health` 端点,已在 `routes/web.go` 中配置。
## 故障处理
如果部署失败,脚本会自动回滚:
- 停止新版本容器
- 保持旧版本运行
## 回滚操作
### 快速回滚
如果刚部署的版本有问题,可以快速回滚到上一个版本:
```bash
cd /www/goravel-admin
chmod +x scripts/deploy/rollback.sh
./scripts/deploy/rollback.sh
```
**特点:**
- 自动检测当前运行的版本(blue/green)
- 切换到另一个环境
- 如果旧容器已删除,可以选择从 Git 回滚或重新构建
- 自动切换 Nginx 流量(如果配置了)
### Git 版本回滚
回滚到特定的 Git 提交、标签或分支:
```bash
cd /www/goravel-admin
chmod +x scripts/deploy/rollback-git.sh
# 查看最近提交(不带参数)
./scripts/deploy/rollback-git.sh
# 回滚到上一个提交
./scripts/deploy/rollback-git.sh HEAD~1
# 回滚到指定提交
./scripts/deploy/rollback-git.sh abc1234
# 回滚到指定标签
./scripts/deploy/rollback-git.sh v1.0.0
# 回滚到远程分支
./scripts/deploy/rollback-git.sh origin/main
```
**特点:**
- 支持提交哈希、标签、分支
- 自动执行部署流程
- 需要确认操作
## 查看日志
```bash
# 查看运行中的容器日志
docker logs -f goravel-admin-blue
docker logs -f goravel-admin-green
# 查看容器状态
docker ps | grep goravel-admin
# 查看容器健康状态
docker inspect --format='{{.State.Health.Status}}' goravel-admin-blue
docker inspect --format='{{.State.Health.Status}}' goravel-admin-green
```
+13
View File
@@ -0,0 +1,13 @@
#!/bin/bash
# 部署配置文件
# 在这里统一配置端口,所有脚本都会读取此配置
# 蓝绿部署端口配置
export BLUE_PORT="${BLUE_PORT:-3000}" # 蓝环境端口(宿主机端口)
export GREEN_PORT="${GREEN_PORT:-3001}" # 绿环境端口(宿主机端口)
export CONTAINER_PORT="${CONTAINER_PORT:-3000}" # 容器内部端口(应用监听端口)
# 其他配置
export DEPLOY_DIR="${DEPLOY_DIR:-/www/goravel-admin}"
export NGINX_CONF="${NGINX_CONF:-/etc/nginx/sites-available/goravel-admin}"
+226
View File
@@ -0,0 +1,226 @@
#!/bin/bash
# Docker Compose 蓝绿部署脚本
# 在服务器上执行此脚本
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/../../" # 回到项目根目录
# 加载部署配置
source "$SCRIPT_DIR/deploy-config.sh"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# 检测当前运行的版本
detect_current_version() {
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-blue"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-blue 2>/dev/null)" = "true" ]; then
echo "blue"
return
fi
fi
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-green"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-green 2>/dev/null)" = "true" ]; then
echo "green"
return
fi
fi
echo "blue" # 默认从 blue 开始
}
CURRENT_COLOR=$(detect_current_version)
NEXT_COLOR=$([ "$CURRENT_COLOR" = "blue" ] && echo "green" || echo "blue")
CURRENT_PORT=$([ "$CURRENT_COLOR" = "blue" ] && echo "$BLUE_PORT" || echo "$GREEN_PORT")
NEXT_PORT=$([ "$NEXT_COLOR" = "blue" ] && echo "$BLUE_PORT" || echo "$GREEN_PORT")
echo -e "${GREEN}=== Docker Compose 蓝绿部署 ===${NC}"
echo -e "当前运行: ${YELLOW}$CURRENT_COLOR${NC} (端口: $CURRENT_PORT)"
echo -e "部署到: ${YELLOW}$NEXT_COLOR${NC} (端口: $NEXT_PORT)"
echo ""
# 1. 检查 Docker 和 Docker Compose
if ! command -v docker &> /dev/null; then
echo -e "${RED}错误: Docker 未安装${NC}"
exit 1
fi
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
echo -e "${RED}错误: Docker Compose 未安装${NC}"
exit 1
fi
# 使用 docker compose 或 docker-compose
COMPOSE_CMD="docker-compose"
if ! command -v docker-compose &> /dev/null; then
COMPOSE_CMD="docker compose"
fi
# 导出端口配置到环境变量(供 docker-compose 使用)
export BLUE_PORT GREEN_PORT CONTAINER_PORT
# 2. 构建新版本镜像
echo -e "${GREEN}[1/7] 构建新版本镜像...${NC}"
echo "注意: 镜像包含启动脚本,会在应用启动前自动执行数据库迁移"
$COMPOSE_CMD -f docker-compose.${NEXT_COLOR}.yml build --no-cache
if [ $? -ne 0 ]; then
echo -e "${RED}构建失败!${NC}"
exit 1
fi
# 3. 启动新版本容器
echo -e "${GREEN}[2/7] 启动新版本容器 (端口 $NEXT_PORT)...${NC}"
$COMPOSE_CMD -f docker-compose.${NEXT_COLOR}.yml up -d
if [ $? -ne 0 ]; then
echo -e "${RED}启动失败!${NC}"
exit 1
fi
# 4. 等待容器启动(启动脚本会自动执行迁移)
echo -e "${GREEN}[3/7] 等待容器启动并执行迁移...${NC}"
echo "注意: 容器启动脚本会在应用启动前自动执行数据库迁移"
# 等待容器启动并完成迁移
# 启动脚本会在应用启动前执行迁移,所以我们需要等待应用完全启动
for i in {1..30}; do
# 检查容器是否运行
if ! docker ps --format "{{.Names}}" | grep -q "goravel-admin-${NEXT_COLOR}"; then
echo "容器未运行,等待中... ($i/30)"
sleep 2
continue
fi
# 检查应用是否已启动(迁移完成后应用才会启动)
if docker exec goravel-admin-${NEXT_COLOR} /www/main artisan --version > /dev/null 2>&1; then
echo -e "${GREEN}✓ 容器已启动,迁移已完成,应用已就绪${NC}"
break
fi
if [ $i -eq 30 ]; then
echo -e "${RED}✗ 容器启动超时,可能迁移失败${NC}"
echo "查看容器日志:"
docker logs --tail 50 goravel-admin-${NEXT_COLOR}
$COMPOSE_CMD -f docker-compose.${NEXT_COLOR}.yml down
exit 1
fi
echo "等待容器启动和迁移完成... ($i/30)"
sleep 2
done
# 验证迁移是否成功(可选,作为双重检查)
echo "验证数据库迁移状态..."
if docker exec goravel-admin-${NEXT_COLOR} /www/main artisan migrate:status > /dev/null 2>&1; then
echo -e "${GREEN}✓ 数据库迁移验证通过${NC}"
else
echo -e "${YELLOW}警告: 无法验证迁移状态,但应用已启动${NC}"
fi
# 6. 询问是否执行数据填充(可选)
echo -e "${GREEN}[5/7] 数据填充(可选)...${NC}"
if [ -z "$RUN_SEED" ]; then
read -p "是否执行数据填充?这可能会重复插入数据 (y/N): " seed_confirm
if [ "$seed_confirm" = "y" ] || [ "$seed_confirm" = "Y" ]; then
RUN_SEED="true"
else
RUN_SEED="false"
fi
fi
if [ "$RUN_SEED" = "true" ]; then
echo "执行数据填充..."
if docker exec goravel-admin-${NEXT_COLOR} /www/main artisan db:seed; then
echo -e "${GREEN}✓ 数据填充成功${NC}"
else
echo -e "${YELLOW}警告: 数据填充失败,但继续部署${NC}"
fi
else
echo -e "${YELLOW}跳过数据填充${NC}"
fi
# 7. 健康检查
echo -e "${GREEN}[6/7] 执行健康检查...${NC}"
HEALTH_CHECK_FAILED=true
for i in {1..30}; do
# 检查容器是否运行
if ! docker ps --format "{{.Names}}" | grep -q "goravel-admin-${NEXT_COLOR}"; then
echo "容器未运行,等待中... ($i/30)"
sleep 2
continue
fi
# 检查健康状态
HEALTH=$(docker inspect --format='{{.State.Health.Status}}' goravel-admin-${NEXT_COLOR} 2>/dev/null || echo "none")
# 尝试 HTTP 健康检查
if curl -f -s http://localhost:$NEXT_PORT/health > /dev/null 2>&1 || \
curl -f -s http://localhost:$NEXT_PORT/ > /dev/null 2>&1; then
echo -e "${GREEN}✓ 新版本健康检查通过 (尝试 $i/30)${NC}"
HEALTH_CHECK_FAILED=false
break
fi
if [ "$HEALTH" = "healthy" ]; then
echo -e "${GREEN}✓ 新版本健康检查通过 (Docker 健康检查)${NC}"
HEALTH_CHECK_FAILED=false
break
fi
echo "等待健康检查... ($i/30)"
sleep 2
done
if [ "$HEALTH_CHECK_FAILED" = "true" ]; then
echo -e "${RED}✗ 健康检查失败,停止新版本并回滚${NC}"
$COMPOSE_CMD -f docker-compose.${NEXT_COLOR}.yml down
exit 1
fi
# 8. 切换 Nginx 流量(如果有 Nginx
echo -e "${GREEN}[7/7] 切换 Nginx 流量...${NC}"
NGINX_CONF="/etc/nginx/sites-available/goravel-admin"
if [ -f "$NGINX_CONF" ]; then
# 备份配置
BACKUP_FILE="${NGINX_CONF}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$NGINX_CONF" "$BACKUP_FILE"
echo "已备份 Nginx 配置到: $BACKUP_FILE"
# 更新 upstream 配置
sed -i "s/server 127.0.0.1:$BLUE_PORT/server 127.0.0.1:$NEXT_PORT/" "$NGINX_CONF"
sed -i "s/server 127.0.0.1:$GREEN_PORT/server 127.0.0.1:$NEXT_PORT/" "$NGINX_CONF"
# 测试并重载 Nginx
if nginx -t 2>/dev/null; then
nginx -s reload
echo -e "${GREEN}✓ Nginx 流量已切换到端口 $NEXT_PORT${NC}"
else
echo -e "${YELLOW}警告: Nginx 配置测试失败,恢复备份${NC}"
mv "$BACKUP_FILE" "$NGINX_CONF"
fi
else
echo -e "${YELLOW}提示: Nginx 配置文件不存在,跳过流量切换${NC}"
echo -e "${YELLOW}请手动配置负载均衡指向端口 $NEXT_PORT${NC}"
fi
# 9. 等待流量切换完成
echo -e "${GREEN}等待流量切换完成...${NC}"
sleep 5
# 10. 停止旧版本服务
echo -e "${GREEN}停止旧版本服务 ($CURRENT_COLOR)...${NC}"
$COMPOSE_CMD -f docker-compose.${CURRENT_COLOR}.yml down
echo ""
echo -e "${GREEN}=== 部署完成 ===${NC}"
echo -e "当前运行版本: ${YELLOW}$NEXT_COLOR${NC} (端口: $NEXT_PORT)"
echo -e "旧版本: ${YELLOW}$CURRENT_COLOR${NC} (已停止)"
echo ""
echo "查看日志: docker logs -f goravel-admin-${NEXT_COLOR}"
echo "查看状态: docker ps | grep goravel-admin"
+86
View File
@@ -0,0 +1,86 @@
#!/bin/bash
# 从 Git 拉取代码并部署
# 在服务器上执行此脚本
set -e
# 配置(根据实际情况修改)
GIT_REPO_URL="${GIT_REPO_URL:-https://github.com/your-username/goravel-admin.git}" # 修改为你的 Git 仓库
GIT_BRANCH="${GIT_BRANCH:-main}" # 或 master
DEPLOY_DIR="${DEPLOY_DIR:-/www/goravel-admin}"
# 颜色输出
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${GREEN}=== 从 Git 拉取并部署 ===${NC}"
echo "仓库: $GIT_REPO_URL"
echo "分支: $GIT_BRANCH"
echo "目录: $DEPLOY_DIR"
echo ""
# 1. 检查部署目录
if [ ! -d "$DEPLOY_DIR" ]; then
echo "创建部署目录: $DEPLOY_DIR"
mkdir -p "$DEPLOY_DIR"
fi
cd "$DEPLOY_DIR"
# 2. 如果是第一次,克隆仓库
if [ ! -d ".git" ]; then
echo -e "${GREEN}首次部署,克隆仓库...${NC}"
if [ -z "$GIT_REPO_URL" ] || [ "$GIT_REPO_URL" = "https://github.com/your-username/goravel-admin.git" ]; then
echo -e "${RED}错误: 请设置 GIT_REPO_URL 环境变量或修改脚本中的仓库地址${NC}"
exit 1
fi
git clone -b "$GIT_BRANCH" "$GIT_REPO_URL" .
else
echo -e "${GREEN}拉取最新代码...${NC}"
git fetch origin
git reset --hard origin/$GIT_BRANCH
git pull origin $GIT_BRANCH || {
echo -e "${YELLOW}警告: git pull 失败,尝试强制重置${NC}"
git fetch origin
git reset --hard origin/$GIT_BRANCH
}
fi
# 3. 检查必要文件
if [ ! -f "Dockerfile" ]; then
echo -e "${RED}错误: 未找到 Dockerfile${NC}"
exit 1
fi
if [ ! -f "docker-compose.blue.yml" ] || [ ! -f "docker-compose.green.yml" ]; then
echo -e "${RED}错误: 未找到 Docker Compose 配置文件${NC}"
exit 1
fi
# 4. 确保 .env 文件存在
if [ ! -f ".env" ]; then
echo -e "${YELLOW}警告: .env 文件不存在${NC}"
if [ -f ".env.example" ]; then
echo "从 .env.example 复制..."
cp .env.example .env
echo -e "${YELLOW}请编辑 .env 文件并设置正确的配置${NC}"
else
echo -e "${RED}错误: 未找到 .env 或 .env.example 文件${NC}"
exit 1
fi
fi
# 5. 确保部署脚本可执行
if [ -f "scripts/deploy/docker-blue-green.sh" ]; then
chmod +x scripts/deploy/docker-blue-green.sh
echo -e "${GREEN}执行部署脚本...${NC}"
./scripts/deploy/docker-blue-green.sh
else
echo -e "${RED}错误: 未找到 deploy.sh${NC}"
exit 1
fi
echo -e "${GREEN}=== 部署完成 ===${NC}"
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
# 数据库迁移脚本
# 在运行中的容器中执行数据库迁移
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 检测当前运行的版本
detect_current_version() {
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-blue"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-blue 2>/dev/null)" = "true" ]; then
echo "blue"
return
fi
fi
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-green"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-green 2>/dev/null)" = "true" ]; then
echo "green"
return
fi
fi
echo "none"
}
CONTAINER_NAME=$1
# 如果没有指定容器名,自动检测
if [ -z "$CONTAINER_NAME" ]; then
CURRENT_COLOR=$(detect_current_version)
if [ "$CURRENT_COLOR" = "none" ]; then
echo -e "${RED}错误: 未找到运行中的容器${NC}"
echo "用法: $0 <container-name>"
echo "示例: $0 goravel-admin-blue"
exit 1
fi
CONTAINER_NAME="goravel-admin-${CURRENT_COLOR}"
echo -e "${YELLOW}自动检测到运行中的容器: $CONTAINER_NAME${NC}"
fi
# 检查容器是否存在
if ! docker ps --format "{{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
echo -e "${RED}错误: 容器 $CONTAINER_NAME 不存在或未运行${NC}"
exit 1
fi
echo -e "${GREEN}=== 执行数据库迁移 ===${NC}"
echo -e "容器: ${YELLOW}$CONTAINER_NAME${NC}"
echo ""
# 执行迁移
echo "执行数据库迁移..."
if docker exec $CONTAINER_NAME /www/main artisan migrate; then
echo -e "${GREEN}✓ 数据库迁移成功${NC}"
exit 0
else
echo -e "${RED}✗ 数据库迁移失败${NC}"
exit 1
fi
+103
View File
@@ -0,0 +1,103 @@
#!/bin/bash
# 从 Git 回滚到指定版本并部署
# 用于回滚到特定的 Git 提交
set -e
# 配置
GIT_BRANCH="${GIT_BRANCH:-main}"
DEPLOY_DIR="${DEPLOY_DIR:-/www/goravel-admin}"
# 颜色输出
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${YELLOW}=== Git 版本回滚 ===${NC}"
# 检查参数
if [ -z "$1" ]; then
echo -e "${BLUE}用法: $0 <commit-hash|tag|branch>${NC}"
echo "示例:"
echo " $0 abc1234 # 回滚到指定提交"
echo " $0 v1.0.0 # 回滚到指定标签"
echo " $0 HEAD~1 # 回滚到上一个提交"
echo " $0 origin/main # 回滚到远程分支"
echo ""
echo -e "${YELLOW}最近的提交历史:${NC}"
cd "$DEPLOY_DIR" 2>/dev/null || cd "$(dirname "$0")/../../"
git log --oneline -10 2>/dev/null || echo "无法获取 Git 历史"
exit 1
fi
TARGET_VERSION="$1"
# 检查部署目录
if [ ! -d "$DEPLOY_DIR" ]; then
# 尝试使用当前目录
if [ -d ".git" ]; then
DEPLOY_DIR="$(pwd)"
else
echo -e "${RED}错误: 部署目录不存在: $DEPLOY_DIR${NC}"
exit 1
fi
fi
cd "$DEPLOY_DIR"
# 检查是否是 Git 仓库
if [ ! -d ".git" ]; then
echo -e "${RED}错误: 当前目录不是 Git 仓库${NC}"
exit 1
fi
# 显示当前状态
CURRENT_COMMIT=$(git rev-parse --short HEAD)
echo -e "当前提交: ${YELLOW}$CURRENT_COMMIT${NC}"
echo -e "目标版本: ${YELLOW}$TARGET_VERSION${NC}"
echo ""
# 确认回滚
read -p "确认要回滚到 $TARGET_VERSION 吗? (y/N): " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
echo -e "${YELLOW}取消回滚${NC}"
exit 0
fi
# 检查目标版本是否存在
if ! git rev-parse --verify "$TARGET_VERSION" > /dev/null 2>&1; then
echo -e "${RED}错误: 未找到版本 $TARGET_VERSION${NC}"
echo -e "${YELLOW}提示: 尝试先执行 git fetch origin${NC}"
exit 1
fi
# 回滚到目标版本
echo -e "${GREEN}回滚到 $TARGET_VERSION...${NC}"
git fetch origin 2>/dev/null || true
git checkout "$TARGET_VERSION"
if [ $? -ne 0 ]; then
echo -e "${RED}回滚失败!${NC}"
exit 1
fi
NEW_COMMIT=$(git rev-parse --short HEAD)
echo -e "${GREEN}✓ 已回滚到 $NEW_COMMIT${NC}"
echo ""
# 执行部署
if [ -f "scripts/deploy/docker-blue-green.sh" ]; then
echo -e "${GREEN}执行部署...${NC}"
chmod +x scripts/deploy/docker-blue-green.sh
./scripts/deploy/docker-blue-green.sh
else
echo -e "${RED}错误: 未找到部署脚本${NC}"
exit 1
fi
echo ""
echo -e "${GREEN}=== Git 回滚完成 ===${NC}"
echo -e "当前版本: ${YELLOW}$NEW_COMMIT${NC}"
+205
View File
@@ -0,0 +1,205 @@
#!/bin/bash
# Docker Compose 蓝绿部署回滚脚本
# 快速回滚到上一个版本
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR/../../" # 回到项目根目录
# 加载部署配置
source "$SCRIPT_DIR/deploy-config.sh"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# 检测当前运行的版本
detect_current_version() {
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-blue"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-blue 2>/dev/null)" = "true" ]; then
echo "blue"
return
fi
fi
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-green"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-green 2>/dev/null)" = "true" ]; then
echo "green"
return
fi
fi
echo "none"
}
CURRENT_COLOR=$(detect_current_version)
if [ "$CURRENT_COLOR" = "none" ]; then
echo -e "${RED}错误: 未检测到运行中的容器${NC}"
exit 1
fi
PREVIOUS_COLOR=$([ "$CURRENT_COLOR" = "blue" ] && echo "green" || echo "blue")
CURRENT_PORT=$([ "$CURRENT_COLOR" = "blue" ] && echo "$BLUE_PORT" || echo "$GREEN_PORT")
PREVIOUS_PORT=$([ "$PREVIOUS_COLOR" = "blue" ] && echo "$BLUE_PORT" || echo "$GREEN_PORT")
echo -e "${YELLOW}=== Docker Compose 蓝绿部署回滚 ===${NC}"
echo -e "当前运行: ${YELLOW}$CURRENT_COLOR${NC} (端口: $CURRENT_PORT)"
echo -e "回滚到: ${YELLOW}$PREVIOUS_COLOR${NC} (端口: $PREVIOUS_PORT)"
echo ""
# 检查 Docker 和 Docker Compose
if ! command -v docker &> /dev/null; then
echo -e "${RED}错误: Docker 未安装${NC}"
exit 1
fi
if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
echo -e "${RED}错误: Docker Compose 未安装${NC}"
exit 1
fi
# 使用 docker compose 或 docker-compose
COMPOSE_CMD="docker-compose"
if ! command -v docker-compose &> /dev/null; then
COMPOSE_CMD="docker compose"
fi
# 导出端口配置到环境变量(供 docker-compose 使用)
export BLUE_PORT GREEN_PORT CONTAINER_PORT
# 检查上一个版本的容器是否存在(可能已停止但未删除)
PREVIOUS_CONTAINER_EXISTS=false
if docker ps -a --format "{{.Names}}" | grep -q "goravel-admin-${PREVIOUS_COLOR}"; then
PREVIOUS_CONTAINER_EXISTS=true
fi
# 如果上一个版本的容器不存在,需要重新构建
if [ "$PREVIOUS_CONTAINER_EXISTS" = "false" ]; then
echo -e "${YELLOW}警告: 上一个版本的容器不存在,需要重新构建${NC}"
echo -e "${BLUE}选项:${NC}"
echo "1. 从 Git 回滚到上一个提交并重新构建"
echo "2. 使用当前代码重新构建上一个版本"
echo "3. 取消回滚"
read -p "请选择 (1/2/3): " choice
case $choice in
1)
echo -e "${GREEN}从 Git 回滚...${NC}"
read -p "请输入要回滚的 Git 提交哈希 (或按 Enter 使用 HEAD~1): " commit_hash
commit_hash=${commit_hash:-HEAD~1}
git checkout $commit_hash
echo -e "${GREEN}构建回滚版本...${NC}"
$COMPOSE_CMD -f docker-compose.${PREVIOUS_COLOR}.yml build --no-cache
;;
2)
echo -e "${GREEN}使用当前代码重新构建...${NC}"
$COMPOSE_CMD -f docker-compose.${PREVIOUS_COLOR}.yml build --no-cache
;;
3)
echo -e "${YELLOW}取消回滚${NC}"
exit 0
;;
*)
echo -e "${RED}无效选择${NC}"
exit 1
;;
esac
fi
# 1. 启动上一个版本
echo -e "${GREEN}[1/4] 启动上一个版本容器 (端口 $PREVIOUS_PORT)...${NC}"
$COMPOSE_CMD -f docker-compose.${PREVIOUS_COLOR}.yml up -d
if [ $? -ne 0 ]; then
echo -e "${RED}启动失败!${NC}"
exit 1
fi
# 2. 等待容器启动
echo -e "${GREEN}[2/4] 等待容器启动...${NC}"
sleep 5
# 3. 健康检查
echo -e "${GREEN}[3/4] 执行健康检查...${NC}"
HEALTH_CHECK_FAILED=true
for i in {1..30}; do
# 检查容器是否运行
if ! docker ps --format "{{.Names}}" | grep -q "goravel-admin-${PREVIOUS_COLOR}"; then
echo "容器未运行,等待中... ($i/30)"
sleep 2
continue
fi
# 检查健康状态
HEALTH=$(docker inspect --format='{{.State.Health.Status}}' goravel-admin-${PREVIOUS_COLOR} 2>/dev/null || echo "none")
# 尝试 HTTP 健康检查
if curl -f -s http://localhost:$PREVIOUS_PORT/health > /dev/null 2>&1 || \
curl -f -s http://localhost:$PREVIOUS_PORT/ > /dev/null 2>&1; then
echo -e "${GREEN}✓ 回滚版本健康检查通过 (尝试 $i/30)${NC}"
HEALTH_CHECK_FAILED=false
break
fi
if [ "$HEALTH" = "healthy" ]; then
echo -e "${GREEN}✓ 回滚版本健康检查通过 (Docker 健康检查)${NC}"
HEALTH_CHECK_FAILED=false
break
fi
echo "等待健康检查... ($i/30)"
sleep 2
done
if [ "$HEALTH_CHECK_FAILED" = "true" ]; then
echo -e "${RED}✗ 健康检查失败,回滚中止${NC}"
echo -e "${YELLOW}保持当前版本运行${NC}"
$COMPOSE_CMD -f docker-compose.${PREVIOUS_COLOR}.yml down
exit 1
fi
# 4. 切换 Nginx 流量
echo -e "${GREEN}[4/4] 切换 Nginx 流量...${NC}"
NGINX_CONF="/etc/nginx/sites-available/goravel-admin"
if [ -f "$NGINX_CONF" ]; then
# 备份配置
BACKUP_FILE="${NGINX_CONF}.backup.rollback.$(date +%Y%m%d_%H%M%S)"
cp "$NGINX_CONF" "$BACKUP_FILE"
echo "已备份 Nginx 配置到: $BACKUP_FILE"
# 更新 upstream 配置
sed -i "s/server 127.0.0.1:$BLUE_PORT/server 127.0.0.1:$PREVIOUS_PORT/" "$NGINX_CONF"
sed -i "s/server 127.0.0.1:$GREEN_PORT/server 127.0.0.1:$PREVIOUS_PORT/" "$NGINX_CONF"
# 测试并重载 Nginx
if nginx -t 2>/dev/null; then
nginx -s reload
echo -e "${GREEN}✓ Nginx 流量已切换到端口 $PREVIOUS_PORT${NC}"
else
echo -e "${YELLOW}警告: Nginx 配置测试失败,恢复备份${NC}"
mv "$BACKUP_FILE" "$NGINX_CONF"
fi
else
echo -e "${YELLOW}提示: Nginx 配置文件不存在,跳过流量切换${NC}"
echo -e "${YELLOW}请手动配置负载均衡指向端口 $PREVIOUS_PORT${NC}"
fi
# 5. 等待流量切换完成
echo -e "${GREEN}等待流量切换完成...${NC}"
sleep 5
# 6. 停止当前版本
echo -e "${GREEN}停止当前版本 ($CURRENT_COLOR)...${NC}"
$COMPOSE_CMD -f docker-compose.${CURRENT_COLOR}.yml down
echo ""
echo -e "${GREEN}=== 回滚完成 ===${NC}"
echo -e "当前运行版本: ${YELLOW}$PREVIOUS_COLOR${NC} (端口: $PREVIOUS_PORT)"
echo -e "已停止版本: ${YELLOW}$CURRENT_COLOR${NC}"
echo ""
echo "查看日志: docker logs -f goravel-admin-${PREVIOUS_COLOR}"
echo "查看状态: docker ps | grep goravel-admin"
+72
View File
@@ -0,0 +1,72 @@
#!/bin/bash
# 数据填充脚本
# 在运行中的容器中执行数据填充
set -e
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
# 检测当前运行的版本
detect_current_version() {
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-blue"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-blue 2>/dev/null)" = "true" ]; then
echo "blue"
return
fi
fi
if docker ps --format "{{.Names}}" | grep -q "goravel-admin-green"; then
if [ "$(docker inspect -f '{{.State.Running}}' goravel-admin-green 2>/dev/null)" = "true" ]; then
echo "green"
return
fi
fi
echo "none"
}
CONTAINER_NAME=$1
# 如果没有指定容器名,自动检测
if [ -z "$CONTAINER_NAME" ]; then
CURRENT_COLOR=$(detect_current_version)
if [ "$CURRENT_COLOR" = "none" ]; then
echo -e "${RED}错误: 未找到运行中的容器${NC}"
echo "用法: $0 <container-name>"
echo "示例: $0 goravel-admin-blue"
exit 1
fi
CONTAINER_NAME="goravel-admin-${CURRENT_COLOR}"
echo -e "${YELLOW}自动检测到运行中的容器: $CONTAINER_NAME${NC}"
fi
# 检查容器是否存在
if ! docker ps --format "{{.Names}}" | grep -q "^${CONTAINER_NAME}$"; then
echo -e "${RED}错误: 容器 $CONTAINER_NAME 不存在或未运行${NC}"
exit 1
fi
echo -e "${YELLOW}=== 执行数据填充 ===${NC}"
echo -e "容器: ${YELLOW}$CONTAINER_NAME${NC}"
echo -e "${YELLOW}警告: 数据填充可能会重复插入数据${NC}"
echo ""
# 确认操作
read -p "确认要执行数据填充吗?(y/N): " confirm
if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
echo -e "${YELLOW}取消数据填充${NC}"
exit 0
fi
# 执行填充
echo "执行数据填充..."
if docker exec $CONTAINER_NAME /www/main artisan db:seed; then
echo -e "${GREEN}✓ 数据填充成功${NC}"
exit 0
else
echo -e "${RED}✗ 数据填充失败${NC}"
exit 1
fi