From 6d2c64e91b39bb9ef6c20def5b5e5b144b97d132 Mon Sep 17 00:00:00 2001 From: Theshyx11 Date: Wed, 5 Nov 2025 18:21:05 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=20config.db=20Docker?= =?UTF-8?q?=20=E5=90=AF=E5=8A=A8=E5=A4=B1=E8=B4=A5=20bug=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=96=87=E6=A1=A3=20(#210)=20##=20=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=20Docker=20Compose=20=E9=A6=96=E6=AC=A1?= =?UTF-8?q?=E5=90=AF=E5=8A=A8=E6=97=B6=EF=BC=8Cconfig.db=20=E8=A2=AB?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=E4=B8=BA=E7=9B=AE=E5=BD=95=E8=80=8C=E9=9D=9E?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=20=E5=AF=BC=E8=87=B4=20SQLite=20?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E5=88=9D=E5=A7=8B=E5=8C=96=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=EF=BC=8C=E5=AE=B9=E5=99=A8=E4=B8=8D=E6=96=AD=E9=87=8D?= =?UTF-8?q?=E5=90=AF=E3=80=82=20=E9=94=99=E8=AF=AF=E4=BF=A1=E6=81=AF:=20"u?= =?UTF-8?q?nable=20to=20open=20database=20file:=20is=20a=20directory"=20##?= =?UTF-8?q?=20=E5=8F=91=E7=8E=B0=E6=97=B6=E9=97=B4=202025-11-02=2000:14=20?= =?UTF-8?q?(UTC+8)=20##=20=E6=A0=B9=E6=9C=AC=E5=8E=9F=E5=9B=A0=20docker-co?= =?UTF-8?q?mpose.yml=20=E4=B8=AD=E7=9A=84=E5=8D=B7=E6=8C=82=E8=BD=BD?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=9A=20=20=20-=20./config.db:/app/config?= =?UTF-8?q?.db=20=E5=BD=93=E6=9C=AC=E5=9C=B0=20config.db=20=E4=B8=8D?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=E6=97=B6=EF=BC=8CDocker=20=E4=BC=9A=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E5=88=9B=E5=BB=BA=E5=90=8C=E5=90=8D**=E7=9B=AE?= =?UTF-8?q?=E5=BD=95**=E3=80=82=20##=20=E4=B8=B4=E6=97=B6=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E6=96=B9=E6=A1=88=201.=20docker-compose=20down=202.?= =?UTF-8?q?=20rm=20-rf=20config.db=203.=20touch=20config.db=204.=20docker-?= =?UTF-8?q?compose=20up=20-d=20##=20=E4=BF=AE=E5=A4=8D=E6=97=B6=E9=97=B4?= =?UTF-8?q?=202025-11-02=2000:22=20(UTC+8)=20##=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20-=20BUGFIX=5FCONFIG=5FDB=5F2025-11-02.md:?= =?UTF-8?q?=20=E8=AF=A6=E7=BB=86=E7=9A=84=20bug=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=8A=A5=E5=91=8A=20##=20=E5=BB=BA=E8=AE=AE=E6=94=B9=E8=BF=9B?= =?UTF-8?q?=20-=20=E5=9C=A8=20DOCKER=5FDEPLOY.md=20=E4=B8=AD=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E9=A2=84=E5=90=AF=E5=8A=A8=E6=AD=A5=E9=AA=A4=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=20-=20=E8=80=83=E8=99=91=E5=9C=A8=20Dockerfile=20?= =?UTF-8?q?=E4=B8=AD=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=8A=A8=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96=E8=84=9A=E6=9C=AC=20Co-authored-by:=20shy=20=20Co-authored-by:=20tinkle-community=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BUGFIX_CONFIG_DB_2025-11-02.md | 193 +++++++++++++++++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 BUGFIX_CONFIG_DB_2025-11-02.md diff --git a/BUGFIX_CONFIG_DB_2025-11-02.md b/BUGFIX_CONFIG_DB_2025-11-02.md new file mode 100644 index 00000000..9947e81a --- /dev/null +++ b/BUGFIX_CONFIG_DB_2025-11-02.md @@ -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