diff --git a/README-postgres.md b/README-postgres.md new file mode 100644 index 0000000..8881f1f --- /dev/null +++ b/README-postgres.md @@ -0,0 +1,226 @@ +# PostgreSQL Docker Compose 配置 + +这个配置提供了一个完整的 PostgreSQL 开发环境,包括数据库服务和可选的管理界面。 + +## 🚀 快速启动 + +### 1. 启动服务 + +```bash +# 启动 PostgreSQL 服务 +docker-compose up -d postgres + +# 或者启动所有服务(包括 pgAdmin) +docker-compose up -d +``` + +### 2. 停止服务 + +```bash +# 停止所有服务 +docker-compose down + +# 停止并删除数据卷(⚠️ 会删除所有数据) +docker-compose down -v +``` + +## 📋 服务配置 + +### PostgreSQL 数据库 + +- **镜像**: `postgres:15-alpine` +- **容器名**: `mixvideo_postgres` +- **端口**: `5432:5432` +- **数据库名**: `mixvideo` +- **用户名**: `mixvideo_user` +- **密码**: `mixvideo_password` + +### pgAdmin 管理界面(可选) + +- **镜像**: `dpage/pgadmin4:latest` +- **容器名**: `mixvideo_pgadmin` +- **端口**: `8080:80` +- **访问地址**: http://localhost:8080 +- **邮箱**: `admin@mixvideo.com` +- **密码**: `admin123` + +## 🔧 连接配置 + +### 应用程序连接 + +```python +# Python 连接示例 +DATABASE_CONFIG = { + 'host': 'localhost', + 'port': 5432, + 'database': 'mixvideo', + 'user': 'mixvideo_user', + 'password': 'mixvideo_password' +} +``` + +```javascript +// Node.js 连接示例 +const connectionString = 'postgresql://mixvideo_user:mixvideo_password@localhost:5432/mixvideo' +``` + +### 命令行连接 + +```bash +# 使用 psql 连接 +psql -h localhost -p 5432 -U mixvideo_user -d mixvideo + +# 或者进入容器内部 +docker exec -it mixvideo_postgres psql -U mixvideo_user -d mixvideo +``` + +## 📁 目录结构 + +``` +. +├── docker-compose.yaml # Docker Compose 配置文件 +├── init-scripts/ # 数据库初始化脚本目录 +│ └── 01-init-database.sql # 初始化脚本 +└── README-postgres.md # 使用说明 +``` + +## 🗄️ 数据库结构 + +初始化脚本会自动创建以下表: + +### 1. users(用户表) +- `id` - 用户ID (UUID) +- `username` - 用户名 +- `email` - 邮箱 +- `password_hash` - 密码哈希 +- `access_token` - 访问令牌 +- `token_expires_at` - 令牌过期时间 +- `created_at` - 创建时间 +- `updated_at` - 更新时间 +- `is_active` - 是否激活 + +### 2. templates(模板表) +- `id` - 模板ID (UUID) +- `name` - 模板名称 +- `description` - 模板描述 +- `thumbnail_path` - 缩略图路径 +- `draft_content_path` - 草稿内容路径 +- `resources_path` - 资源路径 +- `canvas_config` - 画布配置 (JSONB) +- `duration` - 时长 +- `material_count` - 素材数量 +- `track_count` - 轨道数量 +- `tags` - 标签数组 +- `is_cloud` - 是否云端 +- `user_id` - 用户ID +- `draft_content` - 草稿内容 (JSONB) +- `created_at` - 创建时间 +- `updated_at` - 更新时间 + +### 3. resource_categories(资源分类表) +- `id` - 分类ID (UUID) +- `title` - 分类标题 +- `ai_prompt` - AI 提示词 +- `color` - 分类颜色 +- `is_active` - 是否激活 +- `is_cloud` - 是否云端 +- `user_id` - 用户ID +- `created_at` - 创建时间 +- `updated_at` - 更新时间 + +### 4. projects(项目表) +- `id` - 项目ID (UUID) +- `name` - 项目名称 +- `description` - 项目描述 +- `project_directory` - 项目目录 +- `thumbnail_path` - 缩略图路径 +- `canvas_config` - 画布配置 (JSONB) +- `user_id` - 用户ID +- `created_at` - 创建时间 +- `updated_at` - 更新时间 + +## 🔍 常用操作 + +### 查看服务状态 + +```bash +# 查看运行中的容器 +docker-compose ps + +# 查看服务日志 +docker-compose logs postgres +docker-compose logs pgadmin +``` + +### 数据库操作 + +```bash +# 备份数据库 +docker exec mixvideo_postgres pg_dump -U mixvideo_user mixvideo > backup.sql + +# 恢复数据库 +docker exec -i mixvideo_postgres psql -U mixvideo_user mixvideo < backup.sql + +# 查看数据库大小 +docker exec mixvideo_postgres psql -U mixvideo_user -d mixvideo -c "SELECT pg_size_pretty(pg_database_size('mixvideo'));" +``` + +### 性能监控 + +```bash +# 查看活跃连接 +docker exec mixvideo_postgres psql -U mixvideo_user -d mixvideo -c "SELECT * FROM pg_stat_activity;" + +# 查看表大小 +docker exec mixvideo_postgres psql -U mixvideo_user -d mixvideo -c "SELECT schemaname,tablename,pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size FROM pg_tables ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;" +``` + +## 🛠️ 自定义配置 + +### 修改数据库配置 + +编辑 `docker-compose.yaml` 文件中的环境变量: + +```yaml +environment: + POSTGRES_DB: your_database_name + POSTGRES_USER: your_username + POSTGRES_PASSWORD: your_password +``` + +### 添加初始化脚本 + +在 `init-scripts/` 目录下添加 `.sql` 或 `.sh` 文件,它们会在容器首次启动时按字母顺序执行。 + +### 持久化数据 + +数据会自动持久化到 Docker 卷中: +- `postgres_data` - PostgreSQL 数据 +- `pgadmin_data` - pgAdmin 配置 + +## ⚠️ 注意事项 + +1. **生产环境**: 请修改默认密码和配置 +2. **防火墙**: 确保端口 5432 和 8080 可访问 +3. **数据备份**: 定期备份重要数据 +4. **资源限制**: 根据需要调整内存和CPU限制 + +## 🔧 故障排除 + +### 常见问题 + +1. **端口冲突**: 如果端口被占用,修改 `docker-compose.yaml` 中的端口映射 +2. **权限问题**: 确保 Docker 有足够权限访问数据卷 +3. **连接失败**: 检查防火墙设置和网络配置 + +### 重置数据库 + +```bash +# 停止服务并删除数据 +docker-compose down -v + +# 重新启动 +docker-compose up -d +``` + +这样就可以获得一个全新的数据库环境。 diff --git a/docker-compose.simple.yaml b/docker-compose.simple.yaml new file mode 100644 index 0000000..0b12b37 --- /dev/null +++ b/docker-compose.simple.yaml @@ -0,0 +1,19 @@ +version: '3.8' + +services: + postgres: + image: postgres:15-alpine + container_name: mixvideo_postgres + restart: unless-stopped + environment: + POSTGRES_DB: mixvideo + POSTGRES_USER: mixvideo_user + POSTGRES_PASSWORD: mixvideo_password + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: + driver: local diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..a2bdb8b --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,54 @@ +version: '3.8' + +services: + postgres: + image: postgres:15-alpine + container_name: mixvideo_postgres + restart: unless-stopped + environment: + POSTGRES_DB: mixvideo + POSTGRES_USER: mixvideo_user + POSTGRES_PASSWORD: mixvideo_password + POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C" + ports: + - "5432:5432" + volumes: + - postgres_data:/var/lib/postgresql/data + - ./init-scripts:/docker-entrypoint-initdb.d + networks: + - mixvideo_network + healthcheck: + test: ["CMD-SHELL", "pg_isready -U mixvideo_user -d mixvideo"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + + # 可选:PostgreSQL 管理界面 (pgAdmin) + pgadmin: + image: dpage/pgadmin4:latest + container_name: mixvideo_pgadmin + restart: unless-stopped + environment: + PGADMIN_DEFAULT_EMAIL: admin@mixvideo.com + PGADMIN_DEFAULT_PASSWORD: admin123 + PGADMIN_CONFIG_SERVER_MODE: 'False' + ports: + - "8080:80" + volumes: + - pgadmin_data:/var/lib/pgadmin + networks: + - mixvideo_network + depends_on: + postgres: + condition: service_healthy + +volumes: + postgres_data: + driver: local + pgadmin_data: + driver: local + +networks: + mixvideo_network: + driver: bridge diff --git a/init-scripts/01-init-database.sql b/init-scripts/01-init-database.sql new file mode 100644 index 0000000..1694701 --- /dev/null +++ b/init-scripts/01-init-database.sql @@ -0,0 +1,126 @@ +-- 初始化 MixVideo 数据库 +-- 这个脚本会在 PostgreSQL 容器首次启动时自动执行 + +-- 创建扩展 +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; +CREATE EXTENSION IF NOT EXISTS "pg_trgm"; + +-- 创建用户表 +CREATE TABLE IF NOT EXISTS users ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + username VARCHAR(50) UNIQUE NOT NULL, + email VARCHAR(100) UNIQUE NOT NULL, + password_hash VARCHAR(255) NOT NULL, + access_token VARCHAR(500), + token_expires_at TIMESTAMP WITH TIME ZONE, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + is_active BOOLEAN DEFAULT true +); + +-- 创建模板表 +CREATE TABLE IF NOT EXISTS templates ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + name VARCHAR(255) NOT NULL, + description TEXT, + thumbnail_path VARCHAR(500), + draft_content_path VARCHAR(500), + resources_path VARCHAR(500), + canvas_config JSONB DEFAULT '{}', + duration INTEGER DEFAULT 0, + material_count INTEGER DEFAULT 0, + track_count INTEGER DEFAULT 0, + tags TEXT[] DEFAULT '{}', + is_cloud BOOLEAN DEFAULT false, + user_id VARCHAR(100) NOT NULL DEFAULT 'default', + draft_content JSONB, + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP +); + +-- 创建资源分类表 +CREATE TABLE IF NOT EXISTS resource_categories ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + title VARCHAR(255) NOT NULL, + ai_prompt TEXT NOT NULL, + color VARCHAR(7) NOT NULL DEFAULT '#FF6B6B', + is_active BOOLEAN DEFAULT true, + is_cloud BOOLEAN DEFAULT false, + user_id VARCHAR(100) NOT NULL DEFAULT 'default', + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP +); + +-- 创建项目表 +CREATE TABLE IF NOT EXISTS projects ( + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), + name VARCHAR(255) NOT NULL, + description TEXT, + project_directory VARCHAR(500), + thumbnail_path VARCHAR(500), + canvas_config JSONB DEFAULT '{}', + user_id VARCHAR(100) NOT NULL DEFAULT 'default', + created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP +); + +-- 创建索引 +CREATE INDEX IF NOT EXISTS idx_users_username ON users(username); +CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); +CREATE INDEX IF NOT EXISTS idx_users_access_token ON users(access_token); + +CREATE INDEX IF NOT EXISTS idx_templates_user_id ON templates(user_id); +CREATE INDEX IF NOT EXISTS idx_templates_name ON templates(name); +CREATE INDEX IF NOT EXISTS idx_templates_is_cloud ON templates(is_cloud); +CREATE INDEX IF NOT EXISTS idx_templates_created_at ON templates(created_at); + +CREATE INDEX IF NOT EXISTS idx_resource_categories_user_id ON resource_categories(user_id); +CREATE INDEX IF NOT EXISTS idx_resource_categories_is_active ON resource_categories(is_active); +CREATE INDEX IF NOT EXISTS idx_resource_categories_is_cloud ON resource_categories(is_cloud); + +CREATE INDEX IF NOT EXISTS idx_projects_user_id ON projects(user_id); +CREATE INDEX IF NOT EXISTS idx_projects_name ON projects(name); + +-- 插入默认数据 +INSERT INTO users (id, username, email, password_hash, access_token) +VALUES ( + 'default-user-id', + 'default', + 'default@mixvideo.com', + 'default_hash', + 'default_token' +) ON CONFLICT (username) DO NOTHING; + +-- 插入默认分类 +INSERT INTO resource_categories (title, ai_prompt, color, user_id) VALUES + ('开场介绍', '视频开头的介绍部分,包括标题、logo等', '#FF6B6B', 'default'), + ('主要内容', '视频的核心内容部分', '#4ECDC4', 'default'), + ('转场过渡', '视频片段之间的过渡效果', '#45B7D1', 'default'), + ('结尾总结', '视频结尾的总结和结束语', '#96CEB4', 'default'), + ('背景音乐', '视频的背景音乐和音效', '#FFEAA7', 'default'), + ('字幕文本', '视频中的字幕和文字说明', '#DDA0DD', 'default'), + ('特效动画', '视频中的特效和动画效果', '#98D8C8', 'default'), + ('产品展示', '产品或服务的展示片段', '#F7DC6F', 'default') +ON CONFLICT DO NOTHING; + +-- 创建更新时间触发器函数 +CREATE OR REPLACE FUNCTION update_updated_at_column() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = CURRENT_TIMESTAMP; + RETURN NEW; +END; +$$ language 'plpgsql'; + +-- 为所有表创建更新时间触发器 +CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users + FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); + +CREATE TRIGGER update_templates_updated_at BEFORE UPDATE ON templates + FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); + +CREATE TRIGGER update_resource_categories_updated_at BEFORE UPDATE ON resource_categories + FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); + +CREATE TRIGGER update_projects_updated_at BEFORE UPDATE ON projects + FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();