Features - User Management (Phase 4.1): - Database: Add user_modules table for fine-grained module permissions - Database: Add 4 user permissions (view/create/edit/delete) to role_permissions - Backend: UserService (780 lines) - CRUD with tenant isolation - Backend: UserController + UserRoutes (648 lines) - 13 API endpoints - Backend: Batch import users from Excel - Frontend: UserListPage (412 lines) - list/filter/search/pagination - Frontend: UserFormPage (341 lines) - create/edit with module config - Frontend: UserDetailPage (393 lines) - details/tenant/module management - Frontend: 3 modal components (592 lines) - import/assign/configure - API: GET/POST/PUT/DELETE /api/admin/users/* endpoints Architecture Upgrade - Module Permission System: - Backend: Add getUserModules() method in auth.service - Backend: Login API returns modules array in user object - Frontend: AuthContext adds hasModule() method - Frontend: Navigation filters modules based on user.modules - Frontend: RouteGuard checks requiredModule instead of requiredVersion - Frontend: Remove deprecated version-based permission system - UX: Only show accessible modules in navigation (clean UI) - UX: Smart redirect after login (avoid 403 for regular users) Fixes: - Fix UTF-8 encoding corruption in ~100 docs files - Fix pageSize type conversion in userService (String to Number) - Fix authUser undefined error in TopNavigation - Fix login redirect logic with role-based access check - Update Git commit guidelines v1.2 with UTF-8 safety rules Database Changes: - CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled) - ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code) - INSERT 4 permissions + role assignments - UPDATE PUBLIC tenant with 8 module subscriptions Technical: - Backend: 5 new files (~2400 lines) - Frontend: 10 new files (~2500 lines) - Docs: 1 development record + 2 status updates + 1 guideline update - Total: ~4900 lines of code Status: User management 100% complete, module permission system operational
1852 lines
46 KiB
Markdown
1852 lines
46 KiB
Markdown
# REDCap Docker部署方案(开发/生产一致性架构)
|
||
|
||
> **文档版本:** v2.0
|
||
> **创建日期:** 2026-01-01
|
||
> **最后更新:** 2026-01-01(根据ECS决议报告修订)
|
||
> **文档目的:** 指导IIT Manager Agent项目的REDCap Docker环境搭建(开发/生产架构一致)
|
||
> **阅读时间:** 25分钟
|
||
> **重要性:** ⭐⭐⭐⭐⭐ **Day 2开发前必读**
|
||
> **预计部署时间:** 1.5小时
|
||
> **架构决策依据:** [REDCap生产环境部署:ECS vs SAE深度决议报告](./REDCap%20生产环境部署:ECS%20vs%20SAE%20深度决议报告.md)
|
||
|
||
---
|
||
|
||
## 📋 文档说明
|
||
|
||
### 核心理念:**本地开发即生产环境** 🎯
|
||
|
||
本文档基于IIT Manager Agent项目的**混合架构决策**,采用Docker容器化部署REDCap,实现:
|
||
- ✅ **开发环境 = 测试环境 = 生产环境**(无环境漂移)
|
||
- ✅ **Docker配置可直接用于阿里云ECS生产部署**
|
||
- ✅ **Docker配置可直接用于医院内网私有化部署**
|
||
- ✅ **2人团队可维护的简单架构**
|
||
|
||
### 架构定位
|
||
|
||
```yaml
|
||
数据平面 (Data Layer) - REDCap部署策略:
|
||
├─ 本地开发:Docker Compose (Windows/Mac)
|
||
├─ 阿里云测试/生产:ECS + Docker + RDS MySQL
|
||
└─ 医院私有化:服务器 + Docker + 本地MySQL
|
||
|
||
控制平面 (AI Agent Layer) - 部署策略:
|
||
├─ Node.js后端:阿里云SAE (Serverless)
|
||
├─ Python微服务:阿里云SAE
|
||
└─ React前端:阿里云SAE
|
||
|
||
为什么REDCap用ECS而不是SAE?
|
||
❌ REDCap有三个"致命特性"不适合Serverless:
|
||
1. Cron依赖(心跳任务)
|
||
2. Session粘滞(本地会话)
|
||
3. POSIX文件系统依赖(本地存储)
|
||
|
||
详见:REDCap生产环境部署:ECS vs SAE深度决议报告.md
|
||
```
|
||
|
||
### 适用场景
|
||
|
||
**本地开发环境**:
|
||
- ✅ REDCap API Adapter开发与测试
|
||
- ✅ External Module开发与调试
|
||
- ✅ IIT试验项目原型验证
|
||
- ✅ API Token测试和数据格式验证
|
||
|
||
**生产环境**(相同Docker配置 + 额外配置):
|
||
- ✅ 阿里云ECS生产部署(+ RDS + OSS + SLB)
|
||
- ✅ 医院内网私有化部署(+ SSL + 备份)
|
||
- ✅ 多院区标准化交付
|
||
|
||
---
|
||
|
||
## 🎯 一、核心架构设计
|
||
|
||
### 1.1 容器架构(开发/生产一致)
|
||
|
||
#### 生产级核心容器(必需)
|
||
|
||
```
|
||
REDCap Docker环境(开发/生产通用)
|
||
├─ 容器1: MySQL 8.0 数据库 【redcap-db】
|
||
│ ├─ 本地开发:Docker容器
|
||
│ └─ 生产环境:阿里云RDS MySQL(推荐)或Docker容器
|
||
│
|
||
└─ 容器2: Apache + PHP 8.1 + REDCap 【redcap-web】
|
||
├─ 包含Cron定时任务
|
||
├─ 包含External Modules
|
||
└─ 本地存储(edocs/、modules/、temp/)
|
||
|
||
网络:redcap-network(bridge模式)
|
||
存储:Docker命名卷(持久化数据)
|
||
```
|
||
|
||
#### 开发辅助容器(仅开发环境,生产禁用)
|
||
|
||
```
|
||
⚠️ 以下容器仅用于本地开发调试,生产环境出于安全考虑应禁用:
|
||
|
||
容器3: phpMyAdmin(可选) 【phpmyadmin】
|
||
├─ 用途:数据库可视化管理、调试
|
||
├─ 端口:8081
|
||
└─ 生产环境:❌ 不部署(安全风险)
|
||
|
||
说明:
|
||
生产环境数据库管理应通过:
|
||
✅ 阿里云RDS控制台
|
||
✅ MySQL命令行(SSH连接)
|
||
✅ 受限的DMS数据管理服务
|
||
```
|
||
|
||
### 1.2 架构优势
|
||
|
||
```
|
||
✅ 开发/生产环境一致(消除"在我机器上能跑"问题)
|
||
✅ MySQL在Docker内,无需本机安装(开发环境)
|
||
✅ 可无缝切换到RDS MySQL(生产环境)
|
||
✅ 所有依赖隔离,不污染主机环境
|
||
✅ 一键启动/停止,2人团队可维护
|
||
✅ 环境可重复构建(容器化标准交付)
|
||
✅ 易于销毁重建(测试友好)
|
||
✅ 数据持久化(Docker卷 或 RDS)
|
||
✅ 支持多版本并存(不同端口)
|
||
✅ 直接可用于医院内网部署(离线交付)
|
||
```
|
||
|
||
### 1.3 端口分配
|
||
|
||
| 服务 | 容器端口 | 主机端口 | 访问地址 | 生产环境 |
|
||
|------|---------|---------|---------|---------|
|
||
| REDCap Web | 80 | 8080 | http://localhost:8080 | ✅ 部署(端口80) |
|
||
| MySQL | 3306 | 3306 | localhost:3306 | ⚠️ 或使用RDS |
|
||
| phpMyAdmin | 80 | 8081 | http://localhost:8081 | ❌ 禁用 |
|
||
|
||
**生产环境端口调整**:
|
||
- REDCap Web:使用标准80/443端口(通过SLB)
|
||
- MySQL:如使用RDS,无需暴露端口(内网连接)
|
||
- phpMyAdmin:不部署
|
||
|
||
---
|
||
|
||
## 🗂️ 二、文件结构规划
|
||
|
||
### 2.1 项目目录结构
|
||
|
||
```
|
||
AIclinicalresearch/
|
||
├─ redcap15.8.0/ # ✅ 已有REDCap源码
|
||
│ └─ redcap/ # REDCap核心文件
|
||
│
|
||
├─ redcap-docker-dev/ # 🆕 Docker部署目录(需创建)
|
||
│ ├─ docker-compose.yml # Docker编排配置(核心)
|
||
│ ├─ Dockerfile.redcap # REDCap容器镜像定义
|
||
│ ├─ .env # 环境变量(数据库密码等)
|
||
│ │
|
||
│ ├─ config/ # 配置文件目录
|
||
│ │ ├─ apache/
|
||
│ │ │ └─ redcap.conf # Apache虚拟主机配置
|
||
│ │ ├─ php/
|
||
│ │ │ └─ php.ini # PHP配置
|
||
│ │ └─ database.php # REDCap数据库连接配置
|
||
│ │
|
||
│ ├─ scripts/ # 自动化脚本
|
||
│ │ ├─ setup-redcap.ps1 # 🔧 一键部署脚本(PowerShell)
|
||
│ │ ├─ start-redcap.ps1 # 🚀 启动脚本
|
||
│ │ ├─ stop-redcap.ps1 # ⏹️ 停止脚本
|
||
│ │ ├─ logs-redcap.ps1 # 📝 查看日志
|
||
│ │ └─ clean-redcap.ps1 # 🗑️ 清理环境
|
||
│ │
|
||
│ └─ README.md # 部署文档
|
||
```
|
||
|
||
### 2.2 目录说明
|
||
|
||
| 目录/文件 | 用途 | 开发环境 | 生产环境 |
|
||
|----------|------|---------|---------|
|
||
| `docker-compose.yml` | 定义多容器应用 | ✅ 必需 | ✅ 必需(需调整) |
|
||
| `Dockerfile.redcap` | 自定义REDCap镜像 | ✅ 必需 | ✅ 必需 |
|
||
| `.env` | 敏感信息(密码) | ✅ 必需 | ✅ 必需(强密码) |
|
||
| `config/apache/` | Web服务器配置 | ✅ 必需 | ✅ 必需(+SSL) |
|
||
| `config/php/` | PHP运行时配置 | ✅ 必需 | ✅ 必需 |
|
||
| `config/database.php` | REDCap数据库连接 | ✅ 必需 | ✅ 必需(RDS连接) |
|
||
| `scripts/` | 运维脚本 | ⭐ 推荐 | ✅ 必需 |
|
||
|
||
**生产环境额外需要**:
|
||
- SSL证书文件(Let's Encrypt或商业证书)
|
||
- 备份脚本(数据库 + 文件)
|
||
- 监控配置(CloudMonitor Agent)
|
||
- 日志轮转配置
|
||
|
||
---
|
||
|
||
## 🔧 三、关键配置说明
|
||
|
||
### 3.1 MySQL配置(容器内)
|
||
|
||
#### 3.1.1 基本配置
|
||
|
||
```yaml
|
||
# docker-compose.yml - MySQL服务
|
||
services:
|
||
redcap-db:
|
||
image: mysql:8.0
|
||
container_name: redcap-mysql
|
||
restart: unless-stopped
|
||
environment:
|
||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||
MYSQL_DATABASE: ${MYSQL_DATABASE}
|
||
MYSQL_USER: ${MYSQL_USER}
|
||
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||
volumes:
|
||
- redcap-db-data:/var/lib/mysql # 数据持久化
|
||
ports:
|
||
- "3306:3306"
|
||
networks:
|
||
- redcap-network
|
||
command: --default-authentication-plugin=mysql_native_password
|
||
```
|
||
|
||
#### 3.1.2 环境变量(.env文件)
|
||
|
||
```bash
|
||
# 数据库配置(开发环境)
|
||
MYSQL_ROOT_PASSWORD=redcap_root_123
|
||
MYSQL_DATABASE=redcap
|
||
MYSQL_USER=redcap_user
|
||
MYSQL_PASSWORD=redcap_pass_456
|
||
|
||
# ⚠️ 警告:这些是开发环境密码!
|
||
# 生产环境必须使用强密码!
|
||
```
|
||
|
||
#### 3.1.3 认证插件说明
|
||
|
||
```bash
|
||
# 为什么使用 mysql_native_password?
|
||
# REDCap 15.8.0兼容性要求
|
||
# 如果使用MySQL 8.0默认的caching_sha2_password会导致连接失败
|
||
```
|
||
|
||
---
|
||
|
||
### 3.2 PHP + Apache配置
|
||
|
||
#### 3.2.1 PHP配置(php.ini)
|
||
|
||
```ini
|
||
# config/php/php.ini
|
||
|
||
# ========== 文件上传(REDCap必需)==========
|
||
upload_max_filesize = 32M # REDCap文件上传限制
|
||
post_max_size = 32M # 表单提交大小
|
||
max_file_uploads = 20 # 同时上传文件数
|
||
|
||
# ========== 执行时间(数据导出需要)==========
|
||
max_execution_time = 300 # 5分钟(大数据导出)
|
||
max_input_time = 300 # 输入解析时间
|
||
|
||
# ========== 内存(REDCap最低要求)==========
|
||
memory_limit = 256M # REDCap推荐256MB
|
||
|
||
# ========== 时区(重要!)==========
|
||
date.timezone = Asia/Shanghai # 北京时间
|
||
|
||
# ========== 错误报告(开发环境)==========
|
||
display_errors = On # 开发环境显示错误
|
||
error_reporting = E_ALL # 报告所有错误
|
||
|
||
# ========== Session配置 ==========
|
||
session.gc_maxlifetime = 3600 # Session过期时间(1小时)
|
||
session.cookie_lifetime = 0 # Cookie浏览器关闭时过期
|
||
```
|
||
|
||
#### 3.2.2 PHP扩展(必需)
|
||
|
||
```dockerfile
|
||
# Dockerfile.redcap 中安装扩展
|
||
|
||
# 核心扩展(REDCap必需)
|
||
RUN docker-php-ext-install \
|
||
mysqli # MySQL连接(必需)
|
||
pdo_mysql # PDO支持(必需)
|
||
gd # 图片处理(验证码、图表)
|
||
zip # 数据导出压缩
|
||
mbstring # 多字节字符串(UTF-8)
|
||
curl # API调用
|
||
soap # Web Service集成(可选)
|
||
ldap # LDAP认证(可选)
|
||
|
||
# Apache模块
|
||
RUN a2enmod rewrite ssl headers
|
||
```
|
||
|
||
#### 3.2.3 Apache配置(redcap.conf)
|
||
|
||
```apache
|
||
# config/apache/redcap.conf
|
||
|
||
<VirtualHost *:80>
|
||
ServerName localhost
|
||
DocumentRoot /var/www/html/redcap
|
||
|
||
<Directory /var/www/html/redcap>
|
||
Options -Indexes +FollowSymLinks
|
||
AllowOverride All
|
||
Require all granted
|
||
|
||
# 防止目录遍历
|
||
Options -Indexes
|
||
|
||
# 允许.htaccess
|
||
AllowOverride All
|
||
</Directory>
|
||
|
||
# 日志配置
|
||
ErrorLog ${APACHE_LOG_DIR}/redcap-error.log
|
||
CustomLog ${APACHE_LOG_DIR}/redcap-access.log combined
|
||
|
||
# 安全头(开发环境可选)
|
||
# Header always set X-Frame-Options "SAMEORIGIN"
|
||
# Header always set X-Content-Type-Options "nosniff"
|
||
</VirtualHost>
|
||
```
|
||
|
||
---
|
||
|
||
### 3.3 REDCap database.php配置
|
||
|
||
#### 3.3.1 数据库连接配置
|
||
|
||
```php
|
||
<?php
|
||
// config/database.php
|
||
|
||
/**
|
||
* REDCap数据库连接配置(Docker环境)
|
||
* 此文件需要复制到REDCap源码的redcap/目录下
|
||
*/
|
||
|
||
global $log_all_errors;
|
||
$log_all_errors = TRUE; // 开发环境开启详细日志
|
||
|
||
// ========== MYSQL DATABASE CONNECTION ==========
|
||
// Docker容器内连接配置
|
||
$hostname = 'redcap-db'; # 容器服务名(不是localhost!)
|
||
$db = 'redcap'; # 数据库名
|
||
$username = 'redcap_user'; # 用户名
|
||
$password = 'redcap_pass_456'; # 密码
|
||
|
||
// ========== SALT VARIABLE(重要!)==========
|
||
// 用于数据去标识化哈希
|
||
// ⚠️ 一旦设置,永远不可更改!
|
||
$salt = 'iit_dev_salt_2026_redcap_v15'; // 至少8个字符
|
||
|
||
// ========== SSL连接(开发环境不需要)==========
|
||
$db_ssl_key = '';
|
||
$db_ssl_cert = '';
|
||
$db_ssl_ca = '';
|
||
$db_ssl_capath = NULL;
|
||
$db_ssl_cipher = NULL;
|
||
$db_ssl_verify_server_cert = false;
|
||
|
||
?>
|
||
```
|
||
|
||
#### 3.3.2 Salt值说明
|
||
|
||
```
|
||
什么是Salt?
|
||
- 用于REDCap数据导出时的去标识化
|
||
- 影响哈希数据的生成
|
||
- 一旦设置后不可更改(会导致历史数据无法解密)
|
||
|
||
开发环境建议:
|
||
- 使用固定的Salt值(便于多次重建环境)
|
||
- 包含项目标识(如'iit_dev_salt_2026')
|
||
- 至少8个字符,建议20+字符
|
||
|
||
生产环境要求:
|
||
- 使用强随机Salt(32+字符)
|
||
- 包含大小写字母、数字、特殊字符
|
||
- 妥善备份(丢失会导致数据无法解密)
|
||
```
|
||
|
||
---
|
||
|
||
## 📧 四、邮件服务配置策略
|
||
|
||
### 4.1 三种配置方案对比
|
||
|
||
| 方案 | 复杂度 | 功能 | 推荐场景 |
|
||
|------|--------|------|---------|
|
||
| **方案A:跳过配置** | ⭐ 最简单 | 无邮件功能 | ✅ Day 2-8 API开发 |
|
||
| **方案B:MailHog** | ⭐⭐ 简单 | 本地邮件拦截 | Day 9-10 邮件测试 |
|
||
| **方案C:真实SMTP** | ⭐⭐⭐ 复杂 | 真实邮件发送 | 后期集成测试 |
|
||
|
||
### 4.2 方案A:跳过配置(推荐用于Day 2-8)
|
||
|
||
```yaml
|
||
优势:
|
||
✅ 配置最简单
|
||
✅ 启动最快
|
||
✅ 不影响API开发
|
||
✅ REDCap可正常运行
|
||
|
||
限制:
|
||
❌ 无法发送调查邀请
|
||
❌ 无法发送密码重置邮件
|
||
❌ 无法发送系统通知
|
||
|
||
实施方法:
|
||
1. REDCap安装时跳过SMTP配置步骤
|
||
2. 控制中心 → Email & Notification → 留空
|
||
3. 直接进行API开发
|
||
|
||
适用于:
|
||
✅ REDCap API Adapter开发
|
||
✅ External Module开发(不涉及邮件)
|
||
✅ 数据导入导出测试
|
||
```
|
||
|
||
### 4.3 方案B:MailHog(本地邮件测试)
|
||
|
||
```yaml
|
||
# docker-compose.yml 添加MailHog服务
|
||
services:
|
||
mailhog:
|
||
image: mailhog/mailhog
|
||
container_name: redcap-mailhog
|
||
ports:
|
||
- "1025:1025" # SMTP端口
|
||
- "8025:8025" # Web UI端口
|
||
networks:
|
||
- redcap-network
|
||
|
||
# REDCap SMTP配置
|
||
SMTP Host: mailhog
|
||
SMTP Port: 1025
|
||
SMTP Auth: 无需认证
|
||
|
||
# 访问Web界面查看邮件
|
||
http://localhost:8025
|
||
```
|
||
|
||
**使用场景**:测试调查邀请、密码重置等邮件功能
|
||
|
||
### 4.4 方案C:真实SMTP(Gmail/Outlook)
|
||
|
||
```yaml
|
||
# REDCap控制中心配置
|
||
|
||
# Gmail示例
|
||
SMTP Host: smtp.gmail.com
|
||
SMTP Port: 587
|
||
SMTP Auth: TLS
|
||
Username: your-email@gmail.com
|
||
Password: app-specific-password # 不是Gmail密码!
|
||
|
||
# 限制
|
||
- Gmail:每天100封(免费账户)
|
||
- Outlook:每天300封
|
||
- 需要开启"不够安全的应用访问"或使用应用专用密码
|
||
```
|
||
|
||
**推荐策略**:
|
||
- **Day 2-8**:使用方案A(跳过)
|
||
- **Day 9-10**:如需测试邮件,临时切换到方案B
|
||
- **生产环境**:使用企业SMTP或云服务(SendGrid、阿里云DirectMail)
|
||
|
||
---
|
||
|
||
## 🌐 五、本地 vs 云端部署
|
||
|
||
### 5.1 Docker镜像可移植性分析
|
||
|
||
#### 本地Docker → 阿里云ECS:是否可以?
|
||
|
||
```
|
||
答案:可以,但不推荐直接迁移!
|
||
|
||
可以这样做:
|
||
1. 导出Docker镜像
|
||
docker save redcap-local:1.0 -o redcap.tar
|
||
2. 上传到ECS
|
||
scp redcap.tar user@ecs-ip:/tmp/
|
||
3. 在ECS导入
|
||
docker load -i /tmp/redcap.tar
|
||
4. 运行容器
|
||
docker run -d -p 80:80 redcap-local:1.0
|
||
|
||
但为什么不推荐?
|
||
❌ 性能:Docker多一层虚拟化,损失10-20%性能
|
||
❌ 稳定性:容器层增加复杂度和故障点
|
||
❌ 运维:医疗系统需要最大可控性
|
||
❌ 备份:容器数据备份更复杂
|
||
❌ 监控:直接部署更易于监控和调试
|
||
```
|
||
|
||
### 5.2 推荐的云端部署策略
|
||
|
||
```
|
||
本地开发(Docker)→ 云端生产(标准部署)
|
||
|
||
阶段1:本地Docker开发(当前)
|
||
- 目的:API Adapter开发、External Module开发
|
||
- 环境:Windows + Docker Desktop
|
||
- 数据:测试数据(可随时销毁)
|
||
|
||
阶段2:ECS标准部署(未来)
|
||
- 目的:生产环境、真实医疗数据
|
||
- 环境:Ubuntu 22.04 + LAMP
|
||
- 数据:RDS MySQL(高可用)+ OSS存储
|
||
|
||
迁移路径:
|
||
1. 在本地Docker完成External Module开发
|
||
2. 验证API Adapter功能
|
||
3. 在ECS上标准安装REDCap(LAMP)
|
||
4. 复制External Module代码到ECS
|
||
5. 配置生产级数据库和SMTP
|
||
6. 配置SSL证书和域名
|
||
```
|
||
|
||
### 5.3 环境对比表
|
||
|
||
| 对比项 | 本地Docker | 阿里云ECS(标准部署) |
|
||
|--------|-----------|---------------------|
|
||
| **部署方式** | Docker Compose | LAMP手动安装 |
|
||
| **访问地址** | localhost:8080 | https://redcap.domain.com |
|
||
| **数据库** | Docker容器 | RDS MySQL(推荐)或本地 |
|
||
| **存储** | Docker卷 | OSS或本地磁盘 |
|
||
| **邮件** | 跳过或MailHog | 阿里云DirectMail/SendGrid |
|
||
| **SSL** | 不需要 | Let's Encrypt证书 |
|
||
| **性能** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||
| **稳定性** | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
|
||
| **成本** | $0 | $50-200/月 |
|
||
| **适用场景** | 开发测试 | 生产环境 |
|
||
|
||
---
|
||
|
||
## 🔑 六、关键注意事项
|
||
|
||
### 6.1 坑点1:文件权限问题 ⚠️
|
||
|
||
#### 症状
|
||
```bash
|
||
安装时提示:
|
||
"Unable to write to /var/www/html/edocs directory"
|
||
"Unable to write to /var/www/html/temp directory"
|
||
```
|
||
|
||
#### 原因
|
||
```
|
||
Apache运行用户(www-data)对目录无写权限
|
||
Docker容器内文件权限与主机不同步
|
||
```
|
||
|
||
#### 解决方案
|
||
```bash
|
||
# 方法1:启动后手动修复(推荐)
|
||
docker exec -it redcap-web chown -R www-data:www-data /var/www/html/edocs
|
||
docker exec -it redcap-web chown -R www-data:www-data /var/www/html/temp
|
||
docker exec -it redcap-web chown -R www-data:www-data /var/www/html/modules
|
||
|
||
# 方法2:在Dockerfile中预先配置
|
||
RUN mkdir -p /var/www/html/edocs /var/www/html/temp /var/www/html/modules && \
|
||
chown -R www-data:www-data /var/www/html
|
||
```
|
||
|
||
#### 预防措施
|
||
```bash
|
||
# 检查权限
|
||
docker exec -it redcap-web ls -la /var/www/html/
|
||
|
||
# 应该看到:
|
||
drwxr-xr-x www-data www-data edocs
|
||
drwxr-xr-x www-data www-data temp
|
||
drwxr-xr-x www-data www-data modules
|
||
```
|
||
|
||
---
|
||
|
||
### 6.2 坑点2:数据库连接失败 ⚠️
|
||
|
||
#### 症状
|
||
```bash
|
||
安装页面提示:
|
||
"Cannot connect to database"
|
||
"Access denied for user 'redcap_user'@'redcap-web.redcap-network'"
|
||
```
|
||
|
||
#### 原因
|
||
```
|
||
原因1: MySQL容器未完全启动
|
||
原因2: database.php配置错误(hostname)
|
||
原因3: 认证插件不兼容(caching_sha2_password)
|
||
```
|
||
|
||
#### 解决方案
|
||
|
||
**问题1:MySQL未就绪**
|
||
```bash
|
||
# 查看MySQL日志,等待"ready for connections"
|
||
docker-compose logs redcap-db | grep "ready for connections"
|
||
|
||
# 输出示例:
|
||
# 2026-01-01 10:00:00 [Server] /usr/sbin/mysqld: ready for connections.
|
||
|
||
# 建议等待30秒后再访问install.php
|
||
```
|
||
|
||
**问题2:hostname配置错误**
|
||
```php
|
||
// ❌ 错误配置
|
||
$hostname = 'localhost'; // 容器内localhost不是MySQL
|
||
$hostname = '127.0.0.1'; // 同上
|
||
$hostname = 'redcap-mysql'; // 容器名,但应使用服务名
|
||
|
||
// ✅ 正确配置
|
||
$hostname = 'redcap-db'; // Docker Compose服务名
|
||
```
|
||
|
||
**问题3:认证插件**
|
||
```bash
|
||
# 确保docker-compose.yml中包含:
|
||
command: --default-authentication-plugin=mysql_native_password
|
||
|
||
# 或在MySQL容器内手动修改用户
|
||
docker exec -it redcap-mysql mysql -uroot -p
|
||
ALTER USER 'redcap_user'@'%' IDENTIFIED WITH mysql_native_password BY 'redcap_pass_456';
|
||
FLUSH PRIVILEGES;
|
||
```
|
||
|
||
---
|
||
|
||
### 6.3 坑点3:PHP扩展缺失 ⚠️
|
||
|
||
#### 症状
|
||
```bash
|
||
install.php检查页面提示:
|
||
"The GD extension is not loaded"
|
||
"The ZIP extension is not loaded"
|
||
"The MySQLi extension is not loaded"
|
||
```
|
||
|
||
#### 原因
|
||
```
|
||
php:8.1-apache基础镜像只包含核心扩展
|
||
REDCap需要额外安装10+个扩展
|
||
```
|
||
|
||
#### 解决方案
|
||
|
||
**Dockerfile中预装(推荐)**
|
||
```dockerfile
|
||
FROM php:8.1-apache
|
||
|
||
# 安装系统依赖
|
||
RUN apt-get update && apt-get install -y \
|
||
libpng-dev \
|
||
libjpeg-dev \
|
||
libfreetype6-dev \
|
||
libzip-dev \
|
||
libldap2-dev \
|
||
&& rm -rf /var/lib/apt/lists/*
|
||
|
||
# 安装PHP扩展
|
||
RUN docker-php-ext-configure gd --with-freetype --with-jpeg && \
|
||
docker-php-ext-install -j$(nproc) \
|
||
mysqli \
|
||
pdo_mysql \
|
||
gd \
|
||
zip \
|
||
mbstring \
|
||
curl \
|
||
soap \
|
||
ldap
|
||
|
||
# 启用Apache模块
|
||
RUN a2enmod rewrite ssl headers
|
||
```
|
||
|
||
**验证安装**
|
||
```bash
|
||
# 进入容器检查
|
||
docker exec -it redcap-web php -m | grep -E '(mysqli|gd|zip|mbstring)'
|
||
|
||
# 应该看到:
|
||
gd
|
||
mbstring
|
||
mysqli
|
||
zip
|
||
```
|
||
|
||
---
|
||
|
||
### 6.4 坑点4:Windows路径映射 ⚠️
|
||
|
||
#### 症状
|
||
```bash
|
||
容器启动失败或无法访问文件
|
||
Error: "no such file or directory"
|
||
```
|
||
|
||
#### 原因
|
||
```
|
||
Windows路径格式与Linux不兼容
|
||
反斜杠(\)与正斜杠(/)冲突
|
||
绝对路径在Docker Desktop中可能有问题
|
||
```
|
||
|
||
#### 解决方案
|
||
|
||
**使用相对路径(推荐)**
|
||
```yaml
|
||
# ✅ 正确:相对路径
|
||
volumes:
|
||
- ../redcap15.8.0/redcap:/var/www/html/redcap
|
||
- ./config/apache/redcap.conf:/etc/apache2/sites-available/000-default.conf
|
||
|
||
# ❌ 错误:Windows绝对路径
|
||
volumes:
|
||
- D:\MyCursor\AIclinicalresearch\redcap15.8.0\redcap:/var/www/html/redcap
|
||
|
||
# 🟡 可能可以:WSL路径(如果使用WSL2后端)
|
||
volumes:
|
||
- /mnt/d/MyCursor/AIclinicalresearch/redcap15.8.0/redcap:/var/www/html/redcap
|
||
```
|
||
|
||
**PowerShell中转换路径**
|
||
```powershell
|
||
# 获取当前目录的相对路径
|
||
$currentDir = Get-Location
|
||
$redcapSource = Join-Path $currentDir.Parent.FullName "redcap15.8.0\redcap"
|
||
Write-Host "REDCap Source: $redcapSource"
|
||
```
|
||
|
||
---
|
||
|
||
### 6.5 坑点5:端口冲突 ⚠️
|
||
|
||
#### 症状
|
||
```bash
|
||
docker-compose up -d 失败
|
||
Error: "Bind for 0.0.0.0:8080 failed: port is already allocated"
|
||
```
|
||
|
||
#### 原因
|
||
```
|
||
本机已有服务占用相同端口
|
||
- 8080: 可能有其他Web服务
|
||
- 3306: 可能已安装本地MySQL
|
||
- 8081: 可能有其他管理工具
|
||
```
|
||
|
||
#### 解决方案
|
||
|
||
**检查端口占用(Windows)**
|
||
```powershell
|
||
# 检查8080端口
|
||
netstat -ano | findstr :8080
|
||
|
||
# 输出示例:
|
||
# TCP 0.0.0.0:8080 0.0.0.0:0 LISTENING 1234
|
||
|
||
# 查看占用进程
|
||
tasklist | findstr 1234
|
||
|
||
# 结束进程(谨慎!)
|
||
taskkill /F /PID 1234
|
||
```
|
||
|
||
**修改端口映射**
|
||
```yaml
|
||
# 如果8080被占用,改用8888
|
||
services:
|
||
redcap-web:
|
||
ports:
|
||
- "8888:80" # 主机8888 → 容器80
|
||
|
||
# 如果3306被占用,改用3307
|
||
redcap-db:
|
||
ports:
|
||
- "3307:3306"
|
||
```
|
||
|
||
**最佳实践**
|
||
```bash
|
||
# 预先检查所有端口
|
||
netstat -ano | findstr :8080
|
||
netstat -ano | findstr :3306
|
||
netstat -ano | findstr :8081
|
||
|
||
# 如果都空闲,使用默认端口
|
||
# 如果有冲突,提前修改docker-compose.yml
|
||
```
|
||
|
||
---
|
||
|
||
### 6.6 坑点6:数据持久化误区 ⚠️
|
||
|
||
#### 症状
|
||
```bash
|
||
容器删除后,数据丢失
|
||
docker-compose down 后无法恢复项目
|
||
```
|
||
|
||
#### 原因
|
||
```
|
||
误用了--volumes参数删除了数据卷
|
||
没有理解Docker命名卷的概念
|
||
```
|
||
|
||
#### 正确理解
|
||
|
||
**Docker数据卷类型**
|
||
```yaml
|
||
# 类型1:命名卷(推荐,开发环境)
|
||
volumes:
|
||
- redcap-db-data:/var/lib/mysql
|
||
# 特点:Docker管理,跨容器持久化,删除容器不影响
|
||
|
||
# 类型2:绑定挂载(不推荐,Windows性能差)
|
||
volumes:
|
||
- ./mysql-data:/var/lib/mysql
|
||
# 特点:主机目录,可见但性能差
|
||
|
||
# 类型3:tmpfs(临时,不持久化)
|
||
tmpfs:
|
||
- /var/lib/mysql
|
||
# 特点:内存存储,容器停止即丢失
|
||
```
|
||
|
||
**安全操作**
|
||
```bash
|
||
# ✅ 停止容器(保留数据)
|
||
docker-compose stop
|
||
|
||
# ✅ 停止并删除容器(保留数据)
|
||
docker-compose down
|
||
|
||
# ⚠️ 删除容器和网络,但保留卷(安全)
|
||
docker-compose down --volumes=false
|
||
|
||
# ❌ 删除所有(包括数据卷,危险!)
|
||
docker-compose down --volumes
|
||
docker-compose down -v # 同上
|
||
```
|
||
|
||
**数据备份**
|
||
```bash
|
||
# 备份MySQL数据卷
|
||
docker run --rm -v redcap-db-data:/data -v $(pwd):/backup \
|
||
ubuntu tar czf /backup/redcap-db-backup.tar.gz /data
|
||
|
||
# 恢复数据卷
|
||
docker run --rm -v redcap-db-data:/data -v $(pwd):/backup \
|
||
ubuntu tar xzf /backup/redcap-db-backup.tar.gz -C /
|
||
```
|
||
|
||
---
|
||
|
||
## 🚀 七、部署流程(详细步骤)
|
||
|
||
### 7.1 阶段1:准备配置文件(15分钟)
|
||
|
||
#### 步骤1:创建项目目录
|
||
```powershell
|
||
# 进入项目根目录
|
||
cd D:\MyCursor\AIclinicalresearch
|
||
|
||
# 创建Docker部署目录
|
||
New-Item -ItemType Directory -Path "redcap-docker-dev" -Force
|
||
cd redcap-docker-dev
|
||
|
||
# 创建子目录
|
||
New-Item -ItemType Directory -Path "config\apache" -Force
|
||
New-Item -ItemType Directory -Path "config\php" -Force
|
||
New-Item -ItemType Directory -Path "scripts" -Force
|
||
```
|
||
|
||
#### 步骤2:生成配置文件
|
||
```powershell
|
||
# 此步骤将由自动化脚本完成,生成:
|
||
# - docker-compose.yml
|
||
# - Dockerfile.redcap
|
||
# - .env
|
||
# - config/apache/redcap.conf
|
||
# - config/php/php.ini
|
||
# - config/database.php
|
||
# - scripts/*.ps1
|
||
```
|
||
|
||
#### 步骤3:验证REDCap源码
|
||
```powershell
|
||
# 确认源码存在
|
||
Test-Path ..\redcap15.8.0\redcap\install.php
|
||
|
||
# 输出:True(表示源码存在)
|
||
```
|
||
|
||
---
|
||
|
||
### 7.2 阶段2:启动容器(10分钟)
|
||
|
||
#### 步骤1:构建镜像
|
||
```powershell
|
||
# 构建自定义REDCap镜像
|
||
docker-compose build
|
||
|
||
# 输出示例:
|
||
# Building redcap-web...
|
||
# Step 1/10 : FROM php:8.1-apache
|
||
# ...
|
||
# Successfully built abc123def456
|
||
# Successfully tagged redcap-docker-dev_redcap-web:latest
|
||
```
|
||
|
||
#### 步骤2:启动所有容器
|
||
```powershell
|
||
# 后台启动
|
||
docker-compose up -d
|
||
|
||
# 输出示例:
|
||
# Creating network "redcap-docker-dev_redcap-network" ... done
|
||
# Creating volume "redcap-docker-dev_redcap-db-data" ... done
|
||
# Creating redcap-mysql ... done
|
||
# Creating redcap-web ... done
|
||
# Creating redcap-phpmyadmin ... done
|
||
```
|
||
|
||
#### 步骤3:等待MySQL就绪
|
||
```powershell
|
||
# 查看MySQL日志
|
||
docker-compose logs redcap-db | Select-String "ready for connections"
|
||
|
||
# 等待看到:
|
||
# [Server] /usr/sbin/mysqld: ready for connections.
|
||
|
||
# 建议等待30秒
|
||
Start-Sleep -Seconds 30
|
||
```
|
||
|
||
#### 步骤4:修复文件权限
|
||
```powershell
|
||
# 自动修复权限脚本(已包含在setup-redcap.ps1中)
|
||
docker exec -it redcap-web chown -R www-data:www-data /var/www/html/edocs
|
||
docker exec -it redcap-web chown -R www-data:www-data /var/www/html/temp
|
||
docker exec -it redcap-web chown -R www-data:www-data /var/www/html/modules
|
||
```
|
||
|
||
#### 步骤5:验证容器状态
|
||
```powershell
|
||
# 检查所有容器运行状态
|
||
docker-compose ps
|
||
|
||
# 应该看到:
|
||
# Name State Ports
|
||
# redcap-mysql Up 0.0.0.0:3306->3306/tcp
|
||
# redcap-web Up 0.0.0.0:8080->80/tcp
|
||
# redcap-phpmyadmin Up 0.0.0.0:8081->80/tcp
|
||
```
|
||
|
||
---
|
||
|
||
### 7.3 阶段3:REDCap安装(30分钟)
|
||
|
||
#### 步骤1:访问安装向导
|
||
```
|
||
打开浏览器访问:
|
||
http://localhost:8080/install.php
|
||
```
|
||
|
||
#### 步骤2:系统要求检查
|
||
```
|
||
REDCap会自动检查:
|
||
✅ PHP版本 8.1.x
|
||
✅ MySQL连接
|
||
✅ PHP扩展(mysqli, gd, zip, etc.)
|
||
✅ 文件权限(edocs, temp可写)
|
||
|
||
如果有红叉❌,根据提示修复
|
||
```
|
||
|
||
#### 步骤3:数据库配置
|
||
```
|
||
MySQL Hostname: redcap-db
|
||
MySQL Database: redcap
|
||
MySQL Username: redcap_user
|
||
MySQL Password: redcap_pass_456
|
||
Table Prefix: (留空,使用默认)
|
||
|
||
Salt: iit_dev_salt_2026_redcap_v15
|
||
```
|
||
|
||
#### 步骤4:管理员账户
|
||
```
|
||
Username: admin
|
||
Password: Admin@123456 # 开发环境密码
|
||
Email: dev@example.com
|
||
First Name: Admin
|
||
Last Name: User
|
||
```
|
||
|
||
#### 步骤5:SMTP配置
|
||
```
|
||
选择:Skip SMTP Configuration(跳过)
|
||
原因:Day 2-8不需要邮件功能
|
||
```
|
||
|
||
#### 步骤6:完成安装
|
||
```
|
||
点击 "Complete Installation"
|
||
等待数据库表创建(约2-3分钟)
|
||
看到 "Installation Complete!" 消息
|
||
```
|
||
|
||
#### 步骤7:首次登录
|
||
```
|
||
访问:http://localhost:8080/
|
||
用户名:admin
|
||
密码:Admin@123456
|
||
|
||
✅ 登录成功,看到REDCap主页
|
||
```
|
||
|
||
---
|
||
|
||
### 7.4 阶段4:创建测试项目(30分钟)
|
||
|
||
#### 步骤1:新建项目
|
||
```
|
||
1. 点击 "New Project"
|
||
2. 项目标题:IIT Test Project
|
||
3. 项目目的:Research
|
||
4. 模板:Empty Project(从头创建)
|
||
5. 点击 "Create Project"
|
||
```
|
||
|
||
#### 步骤2:设计数据字典
|
||
|
||
**创建表单1:患者信息(Demographics)**
|
||
```
|
||
字段列表:
|
||
1. record_id (Record ID)
|
||
- 类型:Text Box
|
||
- 验证:Integer
|
||
- 标识符:Yes
|
||
|
||
2. patient_name (患者姓名)
|
||
- 类型:Text Box
|
||
- 标识符:Yes
|
||
|
||
3. age (年龄)
|
||
- 类型:Text Box
|
||
- 验证:Integer
|
||
- 范围:1-120
|
||
|
||
4. gender (性别)
|
||
- 类型:Radio Buttons
|
||
- 选项:1, 男 | 2, 女
|
||
|
||
5. enrollment_date (入组日期)
|
||
- 类型:Text Box
|
||
- 验证:Date (Y-M-D)
|
||
```
|
||
|
||
**创建表单2:随访记录(Follow-up)**
|
||
```
|
||
字段列表:
|
||
1. followup_date (随访日期)
|
||
- 类型:Text Box
|
||
- 验证:Date (Y-M-D)
|
||
|
||
2. followup_type (随访类型)
|
||
- 类型:Dropdown
|
||
- 选项:1, 门诊 | 2, 电话 | 3, 线上
|
||
|
||
3. adverse_event (不良事件)
|
||
- 类型:Yes-No
|
||
- 默认:No
|
||
|
||
4. notes (备注)
|
||
- 类型:Notes Box (Paragraph Text)
|
||
```
|
||
|
||
#### 步骤3:创建测试数据
|
||
```
|
||
添加5条测试受试者记录:
|
||
|
||
Record 1:
|
||
- patient_name: 张三
|
||
- age: 45
|
||
- gender: 男
|
||
- enrollment_date: 2025-12-01
|
||
|
||
Record 2:
|
||
- patient_name: 李四
|
||
- age: 52
|
||
- gender: 女
|
||
- enrollment_date: 2025-12-05
|
||
|
||
... (省略3条)
|
||
```
|
||
|
||
#### 步骤4:启用API访问
|
||
```
|
||
1. 进入项目
|
||
2. 左侧菜单 → Applications → API
|
||
3. 点击 "Enable API Access"
|
||
4. 勾选 "Export"、"Import" 权限
|
||
5. 点击 "Request API Token"
|
||
6. 系统生成Token(自动批准,因为是管理员)
|
||
7. 复制Token保存:
|
||
示例:A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6
|
||
```
|
||
|
||
#### 步骤5:测试API调用
|
||
```bash
|
||
# PowerShell测试导出数据
|
||
$apiUrl = "http://localhost:8080/api/"
|
||
$token = "YOUR_API_TOKEN_HERE"
|
||
|
||
$body = @{
|
||
token = $token
|
||
content = 'record'
|
||
format = 'json'
|
||
type = 'flat'
|
||
}
|
||
|
||
Invoke-RestMethod -Uri $apiUrl -Method Post -Body $body
|
||
|
||
# 应该返回JSON数组,包含5条测试数据
|
||
```
|
||
|
||
---
|
||
|
||
### 7.5 阶段5:配置后端环境变量(15分钟)
|
||
|
||
#### 步骤1:更新后端.env
|
||
```bash
|
||
# AIclinicalresearch/backend/.env
|
||
|
||
# ========== REDCap配置(新增)==========
|
||
REDCAP_API_URL=http://localhost:8080/api/
|
||
REDCAP_API_TOKEN=A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6
|
||
REDCAP_PROJECT_ID=1
|
||
|
||
# 注意:localhost在Docker容器内需要改为host.docker.internal
|
||
# 如果后端也在Docker内,应使用容器IP或服务名
|
||
```
|
||
|
||
#### 步骤2:创建API测试脚本
|
||
```typescript
|
||
// backend/src/modules/iit-manager/test-redcap-api.ts
|
||
|
||
import axios from 'axios';
|
||
|
||
const REDCAP_API_URL = process.env.REDCAP_API_URL || 'http://localhost:8080/api/';
|
||
const REDCAP_API_TOKEN = process.env.REDCAP_API_TOKEN || '';
|
||
|
||
async function testREDCapAPI() {
|
||
console.log('🔍 Testing REDCap API Connection...');
|
||
|
||
try {
|
||
const response = await axios.post(REDCAP_API_URL, new URLSearchParams({
|
||
token: REDCAP_API_TOKEN,
|
||
content: 'record',
|
||
format: 'json',
|
||
type: 'flat'
|
||
}));
|
||
|
||
console.log('✅ API Connection Successful!');
|
||
console.log(`📊 Retrieved ${response.data.length} records`);
|
||
console.log('Sample Record:', response.data[0]);
|
||
} catch (error: any) {
|
||
console.error('❌ API Connection Failed:', error.message);
|
||
}
|
||
}
|
||
|
||
testREDCapAPI();
|
||
```
|
||
|
||
#### 步骤3:运行测试
|
||
```powershell
|
||
cd D:\MyCursor\AIclinicalresearch\backend
|
||
npx ts-node src/modules/iit-manager/test-redcap-api.ts
|
||
|
||
# 预期输出:
|
||
# 🔍 Testing REDCap API Connection...
|
||
# ✅ API Connection Successful!
|
||
# 📊 Retrieved 5 records
|
||
# Sample Record: { record_id: '1', patient_name: '张三', ... }
|
||
```
|
||
|
||
---
|
||
|
||
### 7.6 部署完成验证清单
|
||
|
||
```
|
||
验证项 状态
|
||
─────────────────────────────────────────────────
|
||
✅ Docker容器全部运行 [ ]
|
||
✅ MySQL数据库可连接 [ ]
|
||
✅ REDCap安装成功 [ ]
|
||
✅ 管理员账户可登录 [ ]
|
||
✅ 测试项目已创建 [ ]
|
||
✅ API Token已生成 [ ]
|
||
✅ API调用测试通过 [ ]
|
||
✅ 后端环境变量已配置 [ ]
|
||
✅ phpMyAdmin可访问(可选) [ ]
|
||
|
||
全部勾选✅,表示部署成功!
|
||
```
|
||
|
||
---
|
||
|
||
## 💡 八、运维管理脚本
|
||
|
||
### 8.1 启动脚本(start-redcap.ps1)
|
||
|
||
```powershell
|
||
#!/usr/bin/env pwsh
|
||
# start-redcap.ps1 - 启动REDCap开发环境
|
||
|
||
Write-Host "🚀 Starting REDCap Development Environment..." -ForegroundColor Cyan
|
||
|
||
# 检查Docker是否运行
|
||
$dockerRunning = docker info 2>&1 | Select-String "Server Version"
|
||
if (-not $dockerRunning) {
|
||
Write-Host "❌ Docker is not running. Please start Docker Desktop." -ForegroundColor Red
|
||
exit 1
|
||
}
|
||
|
||
# 启动容器
|
||
docker-compose up -d
|
||
|
||
# 等待MySQL就绪
|
||
Write-Host "⏳ Waiting for MySQL to be ready..." -ForegroundColor Yellow
|
||
Start-Sleep -Seconds 10
|
||
|
||
docker-compose logs redcap-db | Select-String "ready for connections"
|
||
|
||
# 显示服务状态
|
||
Write-Host ""
|
||
Write-Host "✅ REDCap Environment Started!" -ForegroundColor Green
|
||
Write-Host ""
|
||
Write-Host "📋 Service URLs:" -ForegroundColor Cyan
|
||
Write-Host " REDCap: http://localhost:8080" -ForegroundColor White
|
||
Write-Host " phpMyAdmin: http://localhost:8081" -ForegroundColor White
|
||
Write-Host ""
|
||
Write-Host "📊 Container Status:" -ForegroundColor Cyan
|
||
docker-compose ps
|
||
```
|
||
|
||
### 8.2 停止脚本(stop-redcap.ps1)
|
||
|
||
```powershell
|
||
#!/usr/bin/env pwsh
|
||
# stop-redcap.ps1 - 停止REDCap开发环境
|
||
|
||
Write-Host "⏹️ Stopping REDCap Development Environment..." -ForegroundColor Yellow
|
||
|
||
# 停止容器(保留数据)
|
||
docker-compose stop
|
||
|
||
Write-Host "✅ REDCap Environment Stopped!" -ForegroundColor Green
|
||
Write-Host ""
|
||
Write-Host "💡 Data volumes are preserved." -ForegroundColor Cyan
|
||
Write-Host " Run 'start-redcap.ps1' to restart." -ForegroundColor Cyan
|
||
```
|
||
|
||
### 8.3 查看日志脚本(logs-redcap.ps1)
|
||
|
||
```powershell
|
||
#!/usr/bin/env pwsh
|
||
# logs-redcap.ps1 - 查看REDCap日志
|
||
|
||
param(
|
||
[string]$Service = "",
|
||
[switch]$Follow
|
||
)
|
||
|
||
Write-Host "📝 REDCap Container Logs" -ForegroundColor Cyan
|
||
Write-Host ""
|
||
|
||
if ($Follow) {
|
||
# 实时跟踪日志
|
||
if ($Service) {
|
||
docker-compose logs -f $Service
|
||
} else {
|
||
docker-compose logs -f
|
||
}
|
||
} else {
|
||
# 显示最近日志
|
||
if ($Service) {
|
||
docker-compose logs --tail=50 $Service
|
||
} else {
|
||
docker-compose logs --tail=50
|
||
}
|
||
}
|
||
```
|
||
|
||
### 8.4 清理脚本(clean-redcap.ps1)
|
||
|
||
```powershell
|
||
#!/usr/bin/env pwsh
|
||
# clean-redcap.ps1 - 清理REDCap环境(危险操作!)
|
||
|
||
Write-Host "🗑️ REDCap Environment Cleanup" -ForegroundColor Red
|
||
Write-Host ""
|
||
Write-Host "⚠️ WARNING: This will DELETE ALL DATA!" -ForegroundColor Red
|
||
Write-Host ""
|
||
|
||
$confirm = Read-Host "Type 'YES' to confirm deletion"
|
||
|
||
if ($confirm -ne "YES") {
|
||
Write-Host "❌ Cleanup cancelled." -ForegroundColor Yellow
|
||
exit 0
|
||
}
|
||
|
||
Write-Host ""
|
||
Write-Host "🗑️ Removing containers..." -ForegroundColor Yellow
|
||
docker-compose down
|
||
|
||
Write-Host "🗑️ Removing volumes (DATA LOSS!)..." -ForegroundColor Red
|
||
docker-compose down --volumes
|
||
|
||
Write-Host "🗑️ Removing images..." -ForegroundColor Yellow
|
||
docker rmi redcap-docker-dev_redcap-web
|
||
|
||
Write-Host ""
|
||
Write-Host "✅ Cleanup Complete!" -ForegroundColor Green
|
||
Write-Host " Run 'setup-redcap.ps1' to redeploy." -ForegroundColor Cyan
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 九、决策清单
|
||
|
||
在实施部署前,请确认以下决策:
|
||
|
||
### 9.1 必需决策
|
||
|
||
| 决策项 | 选项 | 推荐 | 您的选择 |
|
||
|--------|------|------|---------|
|
||
| **部署位置** | `redcap-docker-dev/` | ✅ 推荐 | [ ] |
|
||
| **REDCap端口** | 8080 / 其他 | 8080 | [ ] |
|
||
| **MySQL端口** | 3306 / 其他 | 3306 | [ ] |
|
||
| **phpMyAdmin** | 需要 / 不需要 | 需要 | [ ] |
|
||
| **SMTP配置** | 跳过 / 配置 | 跳过 | [ ] |
|
||
| **数据持久化** | 命名卷 / 绑定挂载 | 命名卷 | [ ] |
|
||
|
||
### 9.2 环境变量
|
||
|
||
```bash
|
||
# 确认以下密码(开发环境)
|
||
MYSQL_ROOT_PASSWORD=redcap_root_123 # 同意 [ ]
|
||
MYSQL_DATABASE=redcap # 同意 [ ]
|
||
MYSQL_USER=redcap_user # 同意 [ ]
|
||
MYSQL_PASSWORD=redcap_pass_456 # 同意 [ ]
|
||
|
||
# Salt值(重要!一旦设置不可更改)
|
||
REDCAP_SALT=iit_dev_salt_2026_redcap_v15 # 同意 [ ]
|
||
```
|
||
|
||
### 9.3 端口冲突检查
|
||
|
||
```powershell
|
||
# 请先运行以下命令检查端口
|
||
netstat -ano | findstr :8080 # REDCap
|
||
netstat -ano | findstr :3306 # MySQL
|
||
netstat -ano | findstr :8081 # phpMyAdmin
|
||
|
||
# 如果有冲突,记录需要修改的端口:
|
||
# REDCap端口改为:_______
|
||
# MySQL端口改为:_______
|
||
# phpMyAdmin端口改为:_______
|
||
```
|
||
|
||
---
|
||
|
||
## 📝 十、后续步骤
|
||
|
||
### 10.1 Day 2开发准备
|
||
|
||
部署完成后,立即可以开始:
|
||
|
||
```
|
||
✅ REDCap API Adapter开发
|
||
- exportRecords() 实现
|
||
- importRecords() 实现
|
||
- exportMetadata() 实现
|
||
|
||
✅ 真实API测试
|
||
- 使用实际API Token
|
||
- 验证JSON响应格式
|
||
- 测试错误处理
|
||
|
||
✅ SyncManager开发
|
||
- 混合同步模式(Webhook + Polling)
|
||
- 数据增量拉取
|
||
- pg-boss任务调度
|
||
```
|
||
|
||
### 10.2 External Module开发(Day 8)
|
||
|
||
```
|
||
当需要开发External Module时:
|
||
1. 在 redcap15.8.0/redcap/modules/ 创建模块目录
|
||
2. 编写 config.json 和 Module.php
|
||
3. 容器会自动挂载(因为使用卷映射)
|
||
4. REDCap控制中心启用模块
|
||
```
|
||
|
||
### 10.3 迁移到生产环境(未来)
|
||
|
||
```
|
||
本地开发验证通过后:
|
||
1. 在阿里云ECS标准安装REDCap(LAMP)
|
||
2. 配置RDS MySQL(高可用)
|
||
3. 配置OSS存储(edocs目录)
|
||
4. 配置SSL证书(Let's Encrypt)
|
||
5. 配置SMTP(阿里云DirectMail)
|
||
6. 复制External Module到生产环境
|
||
7. 导入测试项目(或从头创建)
|
||
```
|
||
|
||
---
|
||
|
||
## 🔗 十一、相关文档
|
||
|
||
### 11.1 项目文档
|
||
|
||
- [REDCap二次开发深度指南](./REDCap%20二次开发深度指南.md) - REDCap架构和EM开发
|
||
- [REDCap部署指南与环境要求](./02-REDCap部署指南与环境要求.md) - 生产环境部署
|
||
- [IIT Manager Agent技术方案 V1.1](../IIT%20Manager%20Agent/02-技术设计/IIT%20Manager%20Agent%20完整技术开发方案%20(V1.1).md) - REDCap集成方案
|
||
- [MVP开发任务清单](../IIT%20Manager%20Agent/04-开发计划/MVP开发任务清单.md) - Day 2任务
|
||
|
||
### 11.2 官方文档
|
||
|
||
- REDCap官网:https://projectredcap.org/
|
||
- REDCap API文档:https://redcap.vanderbilt.edu/api/help/
|
||
- External Module文档:https://github.com/vanderbilt-redcap/external-module-framework-docs
|
||
|
||
### 11.3 Docker文档
|
||
|
||
- Docker Compose:https://docs.docker.com/compose/
|
||
- Docker PHP镜像:https://hub.docker.com/_/php
|
||
- Docker MySQL镜像:https://hub.docker.com/_/mysql
|
||
|
||
---
|
||
|
||
## 📞 十二、故障排查
|
||
|
||
### 12.1 容器无法启动
|
||
|
||
```powershell
|
||
# 检查Docker状态
|
||
docker info
|
||
|
||
# 查看容器日志
|
||
docker-compose logs
|
||
|
||
# 检查端口占用
|
||
netstat -ano | findstr :8080
|
||
netstat -ano | findstr :3306
|
||
|
||
# 重建容器
|
||
docker-compose down
|
||
docker-compose up -d --force-recreate
|
||
```
|
||
|
||
### 12.2 无法访问REDCap
|
||
|
||
```powershell
|
||
# 检查容器运行状态
|
||
docker-compose ps
|
||
|
||
# 检查Apache日志
|
||
docker-compose logs redcap-web
|
||
|
||
# 进入容器诊断
|
||
docker exec -it redcap-web bash
|
||
curl localhost
|
||
```
|
||
|
||
### 12.3 数据库连接失败
|
||
|
||
```powershell
|
||
# 检查MySQL日志
|
||
docker-compose logs redcap-db
|
||
|
||
# 测试MySQL连接
|
||
docker exec -it redcap-mysql mysql -uredcap_user -predcap_pass_456 -e "SHOW DATABASES;"
|
||
|
||
# 检查database.php配置
|
||
docker exec -it redcap-web cat /var/www/html/redcap/database.php
|
||
```
|
||
|
||
### 12.4 API调用失败
|
||
|
||
```powershell
|
||
# 验证API Token
|
||
# REDCap → Applications → API → 查看Token
|
||
|
||
# 测试API连接
|
||
curl -X POST http://localhost:8080/api/ `
|
||
-d "token=YOUR_TOKEN" `
|
||
-d "content=version"
|
||
|
||
# 应该返回REDCap版本号
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ 十三、部署成功标志
|
||
|
||
当您看到以下所有指标时,表示部署成功:
|
||
|
||
```
|
||
✅ 核心容器状态(必需)
|
||
- redcap-mysql: Up
|
||
- redcap-web: Up
|
||
|
||
⭐ 辅助容器状态(可选,仅开发环境)
|
||
- redcap-phpmyadmin: Up(可选,生产环境禁用)
|
||
|
||
✅ 服务可访问
|
||
- http://localhost:8080 → REDCap登录页(核心)
|
||
- http://localhost:8081 → phpMyAdmin界面(可选,调试用)
|
||
|
||
✅ 功能验证
|
||
- 管理员登录成功
|
||
- 测试项目已创建
|
||
- API Token已生成
|
||
- API调用返回数据
|
||
|
||
✅ 后端集成
|
||
- .env配置完成
|
||
- API测试脚本通过
|
||
- Node.js可访问REDCap
|
||
|
||
说明:
|
||
- phpMyAdmin是可选的开发调试工具
|
||
- 生产环境出于安全考虑应禁用
|
||
- 不影响REDCap核心功能
|
||
```
|
||
|
||
---
|
||
|
||
## 🏗️ 十四、生产环境部署指南
|
||
|
||
### 14.1 本地开发 → 生产环境迁移路径
|
||
|
||
```yaml
|
||
阶段1: 本地开发环境(当前)
|
||
├─ 目的:API开发、EM调试
|
||
├─ 环境:Windows/Mac + Docker Desktop
|
||
├─ 数据库:Docker MySQL容器
|
||
├─ 辅助工具:phpMyAdmin(调试)
|
||
└─ 成本:$0
|
||
|
||
阶段2: 阿里云测试环境
|
||
├─ 目的:集成测试、性能测试
|
||
├─ 服务器:阿里云ECS(2核4GB)
|
||
├─ 数据库:阿里云RDS MySQL基础版
|
||
├─ 存储:云盘(40GB ESSD)
|
||
├─ 域名:test-redcap.yourdomain.com
|
||
└─ 成本:¥500-700/月
|
||
|
||
阶段3: 阿里云生产环境
|
||
├─ 目的:正式生产运行
|
||
├─ 服务器:阿里云ECS(4核8GB)
|
||
├─ 数据库:阿里云RDS MySQL高可用版
|
||
├─ 存储:云盘(100GB ESSD) + OSS备份
|
||
├─ 负载均衡:阿里云SLB + SSL证书
|
||
├─ 监控:CloudMonitor + 日志服务
|
||
├─ 域名:redcap.yourdomain.com
|
||
└─ 成本:¥1500-2000/月
|
||
|
||
阶段4: 医院私有化部署
|
||
├─ 目的:医院内网运行
|
||
├─ 服务器:医院提供服务器
|
||
├─ 数据库:Docker MySQL 或 医院MySQL服务器
|
||
├─ 部署方式:Docker离线镜像包
|
||
├─ 交付物:一键部署脚本 + 培训手册
|
||
└─ 成本:一次性部署费用
|
||
```
|
||
|
||
### 14.2 生产环境Docker配置调整
|
||
|
||
#### 调整1:移除phpMyAdmin
|
||
|
||
```yaml
|
||
# docker-compose.yml 生产环境版本
|
||
|
||
services:
|
||
redcap-db:
|
||
# ... MySQL配置保持不变
|
||
|
||
redcap-web:
|
||
# ... REDCap配置保持不变
|
||
|
||
# ❌ 移除phpMyAdmin(安全考虑)
|
||
# phpmyadmin:
|
||
# ...
|
||
|
||
# 生产环境数据库管理方式:
|
||
# 1. 使用阿里云RDS控制台
|
||
# 2. SSH连接ECS后使用mysql命令行
|
||
# 3. 受限的DMS数据管理服务
|
||
```
|
||
|
||
#### 调整2:使用RDS MySQL
|
||
|
||
```yaml
|
||
# docker-compose.yml 生产环境版本
|
||
|
||
services:
|
||
# ❌ 移除redcap-db容器(使用RDS)
|
||
# redcap-db:
|
||
# ...
|
||
|
||
redcap-web:
|
||
image: redcap-web:v1.0
|
||
environment:
|
||
# 连接阿里云RDS
|
||
REDCAP_DB_HOST: rm-xxxxxx.mysql.rds.aliyuncs.com
|
||
REDCAP_DB_PORT: 3306
|
||
REDCAP_DB_NAME: redcap_prod
|
||
REDCAP_DB_USER: redcap_user
|
||
REDCAP_DB_PASS: ${MYSQL_PASSWORD} # 从环境变量读取
|
||
# ... 其他配置
|
||
```
|
||
|
||
#### 调整3:配置SSL证书
|
||
|
||
```yaml
|
||
# docker-compose.yml 生产环境版本
|
||
|
||
services:
|
||
redcap-web:
|
||
volumes:
|
||
# 挂载SSL证书
|
||
- ./ssl/cert.pem:/etc/ssl/certs/redcap.crt:ro
|
||
- ./ssl/key.pem:/etc/ssl/private/redcap.key:ro
|
||
ports:
|
||
- "80:80"
|
||
- "443:443" # HTTPS端口
|
||
```
|
||
|
||
#### 调整4:资源限制
|
||
|
||
```yaml
|
||
# docker-compose.yml 生产环境版本
|
||
|
||
services:
|
||
redcap-web:
|
||
deploy:
|
||
resources:
|
||
limits:
|
||
cpus: '2'
|
||
memory: 4G
|
||
reservations:
|
||
cpus: '1'
|
||
memory: 2G
|
||
restart: always # 自动重启
|
||
```
|
||
|
||
#### 调整5:日志管理
|
||
|
||
```yaml
|
||
# docker-compose.yml 生产环境版本
|
||
|
||
services:
|
||
redcap-web:
|
||
logging:
|
||
driver: "json-file"
|
||
options:
|
||
max-size: "10m"
|
||
max-file: "3"
|
||
```
|
||
|
||
### 14.3 生产环境安全加固
|
||
|
||
```yaml
|
||
必做项:
|
||
├─ 修改所有默认密码(MySQL、REDCap admin)
|
||
├─ 启用HTTPS(强制)
|
||
├─ 配置防火墙规则(仅开放80/443端口)
|
||
├─ 禁用phpMyAdmin(移除容器)
|
||
├─ 配置定期自动备份(数据库 + 文件)
|
||
├─ 配置监控告警(CPU、内存、磁盘、服务状态)
|
||
├─ 限制SSH访问(密钥认证 + IP白名单)
|
||
└─ 定期更新安全补丁
|
||
|
||
推荐项:
|
||
├─ 使用阿里云SLB做负载均衡和SSL卸载
|
||
├─ 配置WAF(Web应用防火墙)
|
||
├─ 启用RDS自动备份(每日备份,保留7天)
|
||
├─ 配置OSS存储备份(异地容灾)
|
||
└─ 使用CloudMonitor实时监控
|
||
```
|
||
|
||
### 14.4 生产环境成本估算
|
||
|
||
```yaml
|
||
阿里云生产环境配置:
|
||
|
||
计算资源:
|
||
├─ ECS 4核8GB:¥400/月
|
||
├─ 云盘 100GB ESSD:¥50/月
|
||
└─ 小计:¥450/月
|
||
|
||
数据库:
|
||
├─ RDS MySQL高可用版 2核4GB:¥600/月
|
||
├─ 存储 100GB:包含
|
||
└─ 小计:¥600/月
|
||
|
||
网络与安全:
|
||
├─ SLB负载均衡:¥60/月
|
||
├─ SSL证书:¥100/年(Let's Encrypt免费)
|
||
├─ 公网流量:¥0.8/GB(估算¥50/月)
|
||
└─ 小计:¥110/月
|
||
|
||
存储与备份:
|
||
├─ OSS存储 100GB:¥10/月
|
||
├─ OSS流量:¥10/月
|
||
└─ 小计:¥20/月
|
||
|
||
监控与日志:
|
||
├─ CloudMonitor:免费
|
||
├─ 日志服务 10GB:¥5/月
|
||
└─ 小计:¥5/月
|
||
|
||
总计:¥1185/月(约¥14,220/年)
|
||
|
||
优化方案(包年):
|
||
├─ ECS 4核8GB(3年):¥3600/年(¥300/月)
|
||
├─ RDS MySQL高可用版:¥600/月
|
||
├─ 其他:¥135/月
|
||
└─ 总计:¥1035/月(约¥12,420/年)
|
||
```
|
||
|
||
### 14.5 医院私有化部署交付清单
|
||
|
||
```yaml
|
||
交付物清单:
|
||
|
||
1. Docker镜像包:
|
||
├─ redcap-web:v1.0.tar(导出的镜像文件)
|
||
├─ mysql:8.0.tar(如医院无数据库)
|
||
└─ docker-compose.yml(配置文件)
|
||
|
||
2. 部署脚本:
|
||
├─ install-docker.sh(Docker安装脚本)
|
||
├─ setup-redcap.sh(一键部署脚本)
|
||
├─ start-redcap.sh(启动脚本)
|
||
├─ stop-redcap.sh(停止脚本)
|
||
└─ backup-redcap.sh(备份脚本)
|
||
|
||
3. 文档:
|
||
├─ 部署指南.pdf(医院IT版)
|
||
├─ 运维手册.pdf(日常操作)
|
||
├─ 故障排查手册.pdf(问题诊断)
|
||
└─ 安全加固指南.pdf(合规要求)
|
||
|
||
4. 配置模板:
|
||
├─ database.php.template(数据库配置)
|
||
├─ php.ini.template(PHP配置)
|
||
├─ apache.conf.template(Apache配置)
|
||
└─ .env.template(环境变量)
|
||
|
||
5. 培训材料:
|
||
├─ 系统架构说明.pptx
|
||
├─ 日常运维培训.pptx
|
||
└─ 操作演示视频.mp4
|
||
|
||
部署流程:
|
||
Step 1: 医院IT安装Docker(30分钟)
|
||
Step 2: 导入Docker镜像(10分钟)
|
||
Step 3: 配置环境变量(10分钟)
|
||
Step 4: 启动容器(5分钟)
|
||
Step 5: 初始化REDCap(30分钟)
|
||
Step 6: 验证功能(30分钟)
|
||
总计:约2小时
|
||
```
|
||
|
||
### 14.6 生产环境监控方案
|
||
|
||
```yaml
|
||
监控指标:
|
||
|
||
系统层:
|
||
├─ CPU使用率(告警阈值:>80% 持续5分钟)
|
||
├─ 内存使用率(告警阈值:>85%)
|
||
├─ 磁盘使用率(告警阈值:>80%)
|
||
└─ 网络流量(异常流量告警)
|
||
|
||
应用层:
|
||
├─ REDCap可用性(HTTP健康检查,5分钟间隔)
|
||
├─ 响应时间(告警阈值:>3秒)
|
||
├─ 错误率(告警阈值:>1%)
|
||
└─ 并发用户数
|
||
|
||
数据库层:
|
||
├─ RDS连接数(告警阈值:>80%)
|
||
├─ 慢查询数(>1秒的查询)
|
||
├─ 磁盘IOPS使用率
|
||
└─ CPU使用率
|
||
|
||
容器层:
|
||
├─ 容器运行状态(自动重启监控)
|
||
├─ 容器资源使用(内存泄漏检测)
|
||
└─ 容器日志错误率
|
||
|
||
告警方式:
|
||
├─ 短信(紧急告警)
|
||
├─ 邮件(一般告警)
|
||
├─ 钉钉/企业微信(团队通知)
|
||
└─ CloudMonitor控制台
|
||
```
|
||
|
||
---
|
||
|
||
## 🎉 结语
|
||
|
||
### 本地开发环境部署完成 ✅
|
||
|
||
**恭喜!您已掌握REDCap Docker部署方案。**
|
||
|
||
这套Docker配置具有以下特点:
|
||
- ✅ **开发/生产架构一致**:消除环境漂移
|
||
- ✅ **可直接用于生产**:经过少量调整即可
|
||
- ✅ **支持离线交付**:医院私有化部署
|
||
- ✅ **2人团队可维护**:简单、透明、可控
|
||
|
||
### 下一步行动
|
||
|
||
**立即开始**:
|
||
- Day 2:开始REDCap API Adapter开发
|
||
- 参考:[MVP开发任务清单](../IIT%20Manager%20Agent/04-开发计划/MVP开发任务清单.md)
|
||
|
||
**未来规划**:
|
||
- Week 2-3:阿里云ECS测试环境部署
|
||
- Month 1-2:医院试点部署
|
||
- Month 3+:标准化交付流程
|
||
|
||
### 需要帮助?
|
||
|
||
- 查看本文档的"故障排查"章节
|
||
- 查看Docker容器日志:`docker-compose logs`
|
||
- 参考REDCap官方文档:https://projectredcap.org/
|
||
- 参考ECS决议报告:[REDCap生产环境部署:ECS vs SAE深度决议报告](./REDCap%20生产环境部署:ECS%20vs%20SAE%20深度决议报告.md)
|
||
|
||
---
|
||
|
||
> **文档维护**:本文档随IIT Manager Agent项目持续更新
|
||
> **版本历史**:
|
||
> - v1.0 (2026-01-01): 初始版本
|
||
> - v2.0 (2026-01-01): 根据ECS决议报告修订,强调开发/生产一致性
|
||
> **最后更新**:2026-01-01
|
||
> **下次审查**:生产环境首次部署后
|
||
|