docs: 添加 config.db Docker 启动失败 bug 修复文档 (#210)

## 问题描述
Docker Compose 首次启动时,config.db 被创建为目录而非文件,
导致 SQLite 数据库初始化失败,容器不断重启。

错误信息: "unable to open database file: is a directory"

## 发现时间
2025-11-02 00:14 (UTC+8)

## 根本原因
docker-compose.yml 中的卷挂载配置:
  - ./config.db:/app/config.db

当本地 config.db 不存在时,Docker 会自动创建同名**目录**。

## 临时解决方案
1. docker-compose down
2. rm -rf config.db
3. touch config.db
4. docker-compose up -d

## 修复时间
2025-11-02 00:22 (UTC+8)

## 新增文件
- BUGFIX_CONFIG_DB_2025-11-02.md: 详细的 bug 修复报告

## 建议改进
- 在 DOCKER_DEPLOY.md 中添加预启动步骤说明
- 考虑在 Dockerfile 中添加自动初始化脚本

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: shy <shy@nofx.local>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Theshyx11
2025-11-05 18:21:05 +08:00
committed by GitHub
parent 77c99499d7
commit df4af06bc7

View File

@@ -0,0 +1,193 @@
# Bug修复报告config.db 数据库初始化失败
## 问题发现时间
**2025年11月2日 00:14 (UTC+8)**
## 问题描述
### 错误现象
Docker容器 `nofx-trading` 启动后不断重启,后端服务无法正常运行。
### 错误日志
```
2025/11/02 00:14:18 ❌ 初始化数据库失败: 创建表失败: 执行SQL失败 [CREATE TABLE IF NOT EXISTS ai_models (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL DEFAULT 'default',
name TEXT NOT NULL,
provider TEXT NOT NULL,
enabled BOOLEAN DEFAULT 0,
api_key TEXT DEFAULT '',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
)]: unable to open database file: is a directory
```
### 根本原因
在Docker Compose首次启动时如果本地没有 `config.db` 文件docker-compose.yml 中的卷挂载配置:
```yaml
volumes:
- ./config.db:/app/config.db
```
会**自动创建一个同名目录**而不是文件这导致SQLite无法正常打开数据库文件。
## 解决方案
### 临时修复步骤(手动)
1. 停止所有Docker容器
```bash
docker-compose down
```
2. 删除错误创建的 `config.db` 目录
```bash
rm -rf config.db
```
3. 创建空的 `config.db` 文件
```bash
touch config.db
```
4. 重新启动容器
```bash
docker-compose up -d
```
### 长期解决方案(建议)
#### 方案1修改 docker-compose.yml推荐
在启动容器前,使用 `entrypoint``command` 确保文件存在:
```yaml
services:
nofx:
# ... 其他配置
entrypoint: ["/bin/sh", "-c"]
command:
- |
if [ ! -f /app/config.db ]; then
touch /app/config.db
fi
./nofx
```
#### 方案2添加初始化脚本
创建 `docker/init-db.sh`
```bash
#!/bin/sh
if [ ! -f /app/config.db ]; then
echo "Creating config.db file..."
touch /app/config.db
fi
exec "$@"
```
修改 Dockerfile
```dockerfile
COPY docker/init-db.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/init-db.sh
ENTRYPOINT ["init-db.sh"]
CMD ["./nofx"]
```
#### 方案3文档说明
`DOCKER_DEPLOY.md` 中添加预启动步骤:
```markdown
## 启动前准备
在首次运行 docker-compose 之前,请执行:
\`\`\`bash
touch config.db
\`\`\`
这将创建空的数据库文件,防止 Docker 自动创建同名目录。
```
## 修复验证
### 修复后的日志
```
2025/11/02 00:22:06 📋 初始化配置数据库: config.db
2025/11/02 00:22:06 ✓ 配置数据库初始化成功
2025/11/02 00:22:06 🌐 API服务器启动在 http://localhost:8080
```
### 容器状态
```bash
$ docker-compose ps
NAME STATUS
nofx-trading Up (healthy)
nofx-frontend Up (healthy)
```
## 影响范围
### 受影响的版本
- dev 分支2025-11-01之后的版本
- 所有使用新数据库架构的版本
### 受影响的用户
- 首次通过 Docker Compose 部署的用户
- 删除过 `config.db` 后重新启动的用户
### 不受影响的场景
- 使用 PM2 直接运行的部署
- 已经成功启动过一次的 Docker 部署config.db 文件已存在)
## 相关文件
- `docker-compose.yml` - 卷挂载配置
- `config/database.go` - 数据库初始化逻辑
- `main.go` - 应用启动入口
## 建议改进
1.**立即**: 在文档中添加预启动步骤说明
2. ⚠️ **短期**: 修改 Dockerfile 添加自动初始化脚本
3. 💡 **长期**: 考虑使用 Docker 命名卷named volume代替绑定挂载
## 测试清单
- [x] Docker Compose 首次启动
- [x] 删除 config.db 后重新启动
- [x] 数据库表自动创建
- [x] API 服务正常响应
- [x] Web 界面可访问
## 提交信息
```
fix: Docker启动时config.db被创建为目录导致数据库初始化失败
问题描述:
- Docker Compose 首次启动时,卷挂载会将不存在的 config.db 创建为目录
- 导致 SQLite 无法打开数据库文件,容器不断重启
- 错误信息:"unable to open database file: is a directory"
解决方案:
- 手动删除 config.db 目录并创建空文件
- 建议在文档中添加预启动步骤说明
发现时间2025-11-02 00:14 (UTC+8)
修复时间2025-11-02 00:22 (UTC+8)
影响范围:所有使用 Docker Compose 首次部署的用户
```
## 备注
此问题是 Docker Compose 的已知行为:当绑定挂载的源文件不存在时,会自动创建同名**目录**。
参考https://docs.docker.com/storage/bind-mounts/#differences-between--v-and---mount-behavior