107 lines
2.8 KiB
Markdown
107 lines
2.8 KiB
Markdown
# 数据库迁移策略
|
||
|
||
## 问题背景
|
||
|
||
在容器化部署中,如果应用在数据库迁移完成之前启动,新版本的代码可能会尝试访问不存在的数据库字段或表,导致运行时错误。
|
||
|
||
## 解决方案
|
||
|
||
### 启动脚本自动迁移
|
||
|
||
我们使用 Docker 启动脚本 (`docker-entrypoint.sh`) 在应用启动前自动执行数据库迁移:
|
||
|
||
```
|
||
容器启动 → 执行迁移 → 迁移成功 → 启动应用
|
||
↓
|
||
迁移失败 → 容器退出 → 部署脚本检测到并回滚
|
||
```
|
||
|
||
### 工作流程
|
||
|
||
1. **容器启动时**:`docker-entrypoint.sh` 脚本首先执行
|
||
2. **执行迁移**:运行 `artisan migrate` 命令
|
||
3. **迁移成功**:继续启动应用
|
||
4. **迁移失败**:容器退出(exit 1),部署脚本检测到并回滚
|
||
|
||
### 优势
|
||
|
||
- ✅ **避免字段不存在错误** - 迁移在应用启动前完成
|
||
- ✅ **自动执行** - 无需手动操作
|
||
- ✅ **失败自动回滚** - 迁移失败时容器退出,部署脚本自动回滚
|
||
- ✅ **幂等操作** - Goravel 的 migrate 是安全的,可以重复执行
|
||
|
||
### 配置选项
|
||
|
||
#### 跳过迁移(不推荐)
|
||
|
||
如果需要在某些情况下跳过迁移:
|
||
|
||
```bash
|
||
# 在 docker-compose.yml 中设置环境变量
|
||
environment:
|
||
- SKIP_MIGRATE=true
|
||
```
|
||
|
||
**注意:** 跳过迁移可能导致应用启动后访问不存在的字段而报错。
|
||
|
||
### 部署脚本中的处理
|
||
|
||
部署脚本 (`docker-blue-green.sh`) 会:
|
||
|
||
1. 启动新版本容器
|
||
2. 等待容器启动(包括迁移完成)
|
||
3. 验证应用是否已启动(如果迁移失败,应用不会启动)
|
||
4. 如果容器退出,自动检测并回滚
|
||
|
||
### 健康检查
|
||
|
||
健康检查的 `start_period` 设置为 60 秒,给迁移足够的时间完成:
|
||
|
||
```yaml
|
||
healthcheck:
|
||
start_period: 60s # 等待迁移和应用启动
|
||
```
|
||
|
||
### 单独执行迁移
|
||
|
||
如果需要单独执行迁移(不重启容器):
|
||
|
||
```bash
|
||
# 在运行中的容器中执行迁移
|
||
./scripts/deploy/migrate.sh
|
||
```
|
||
|
||
### 故障排查
|
||
|
||
如果迁移失败:
|
||
|
||
1. **查看容器日志**:
|
||
```bash
|
||
docker logs goravel-admin-blue
|
||
```
|
||
|
||
2. **检查迁移状态**:
|
||
```bash
|
||
docker exec goravel-admin-blue /www/main artisan migrate:status
|
||
```
|
||
|
||
3. **手动执行迁移**:
|
||
```bash
|
||
docker exec goravel-admin-blue /www/main artisan migrate
|
||
```
|
||
|
||
### 最佳实践
|
||
|
||
1. **迁移应该是幂等的** - 确保迁移可以安全地重复执行
|
||
2. **测试迁移** - 在测试环境先测试迁移
|
||
3. **备份数据库** - 在生产环境执行迁移前备份数据库
|
||
4. **监控迁移** - 关注容器日志,确保迁移成功
|
||
|
||
### 相关文件
|
||
|
||
- `docker-entrypoint.sh` - 容器启动脚本
|
||
- `Dockerfile` - Docker 镜像构建文件
|
||
- `scripts/deploy/docker-blue-green.sh` - 部署脚本
|
||
- `scripts/deploy/migrate.sh` - 单独执行迁移脚本
|
||
|