fix(db): Open 自动创建父目录(自定义 DATA_DIR 首启不报错);add docker-compose.dev.yml(PG+pgvector 必需 + Ollama embedding 可选)

This commit is contained in:
Aska committed 2026-09-06 10:39:27 +08:00
1 parent cee2d26205
commit 1d9c14300d
2 files changed
+59

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
# Cyrene v2 本地开发依赖(docker compose)
# 用法:
# 1) 先停掉之前手动起的容器,避免端口冲突:
# docker rm -f cyrene-pg # 若有旧的手动容器
# 2) 启动:
# docker compose -f docker-compose.dev.yml up -d
# 3) 验证 pgvector:
# docker exec cyrene-pg psql -U cyrene -d cyrene_ai \
# -c "CREATE EXTENSION IF NOT EXISTS vector; SELECT extversion FROM pg_extension WHERE extname='vector';"
#
# 注:SQLite 为默认内嵌库(文件,不需要容器);PG+pgvector 为可选增强(向量检索)。
# 服务 `embedding`(Ollama)为可选:用于真语义嵌入(EMBEDDING_API_URL),不需要就注释掉/不加。
services:
# 主数据库:PostgreSQL 16 + pgvector(向量索引走这里)
pg:
image: pgvector/pgvector:pg16
container_name: cyrene-pg
environment:
POSTGRES_USER: cyrene # 该用户会在镜像里被创建为 superuser(本地开发方便建 vector 扩展)
POSTGRES_PASSWORD: cyrene_pass
POSTGRES_DB: cyrene_ai
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U cyrene -d cyrene_ai"]
interval: 5s
timeout: 3s
retries: 12
# 可选:本地 embedding(真语义向量)。用 Ollama 跑 bge-m3。
# 启用后需拉模型:docker exec -it cyrene-embedding ollama pull bge-m3
# 并让 .env 指到它:EMBEDDING_API_URL=http://localhost:11434/v1, EMBEDDING_MODEL=bge-m3
embedding:
image: ollama/ollama:latest
container_name: cyrene-embedding
profiles: ["embedding"] # 默认不启动;需要时 `docker compose --profile embedding up -d`
ports:
- "11434:11434"
volumes:
- ollama:/root/.ollama
volumes:
pgdata:
ollama:
+12
View File
@@ -22,6 +22,8 @@ import (
"fmt"
"io"
"log/slog"
"os"
"path/filepath"
"strings"
_ "modernc.org/sqlite" // pure-Go SQLite driver, registers driver name "sqlite"
@@ -66,6 +68,16 @@ func Open(ctx context.Context, path string, log *slog.Logger) (*sql.DB, error) {
}
log = discardLogger(log)
// Ensure the parent directory exists for file-backed databases so a custom
// DATA_DIR (e.g. ./data) works on first run without a pre-made directory.
if !isMemory(path) {
if dir := filepath.Dir(path); dir != "" && dir != "." {
if err := os.MkdirAll(dir, 0o755); err != nil {
return nil, fmt.Errorf("db: create dir %q: %w", dir, err)
}
}
}
db, err := sql.Open("sqlite", buildDSN(path))
if err != nil {
return nil, fmt.Errorf("db: open %q: %w", path, err)