feat(redcap): REDCap 15.8.0 Docker本地开发环境部署完成
核心成果: - REDCap 15.8.0成功部署在Docker环境 - 登录功能正常,管理员账户: Admin/Admin123! - MySQL 8.0 + PHP 8.1 + Apache 2.4环境验证通过 问题解决: 1. 修复ERR_CONTENT_DECODING_FAILED错误 - 强制禁用Apache deflate模块 - PHP配置关闭zlib.output_compression - 自动注释REDCap源码中的压缩设置 2. 修复Base URL配置错误 - 更新redcap_config表中的redcap_base_url - 统一DocumentRoot与访问路径 3. 修复登录失败问题(CRLF污染) - 删除database.php末尾的PHP结束标签 - 创建.gitattributes规范换行符 - 验证REDCap官方源码无此问题 技术改进: - 添加密码重置工具脚本 - 完善docker-entrypoint.sh启动脚本 - 创建详细的部署问题解决记录 - 建立PHP配置文件最佳实践 部署文档: - REDCap本地Docker开发环境部署方案 - REDCap生产环境部署决策报告(ECS vs SAE) - 部署问题解决记录(含根因分析) 下一步: - Day 2: 开发REDCap API Adapter - 实现与IIT Manager Agent的数据对接
This commit is contained in:
69
redcap-docker-dev/scripts/clean-redcap.ps1
Normal file
69
redcap-docker-dev/scripts/clean-redcap.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# REDCap Docker环境清理脚本
|
||||
# 版本:v1.0
|
||||
# 日期:2026-01-01
|
||||
# ⚠️ 警告:此脚本会删除所有数据!
|
||||
|
||||
Write-Host "🗑️ REDCap Docker环境清理" -ForegroundColor Red
|
||||
Write-Host ""
|
||||
Write-Host "⚠️ 警告:此操作将删除所有数据!" -ForegroundColor Red
|
||||
Write-Host " • 容器将被删除" -ForegroundColor Yellow
|
||||
Write-Host " • 数据卷将被删除(包括数据库、上传文件)" -ForegroundColor Yellow
|
||||
Write-Host " • Docker镜像将被删除" -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# 切换到项目目录
|
||||
$ScriptDir = Split-Path -Parent $PSCommandPath
|
||||
$ProjectDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $ProjectDir
|
||||
|
||||
# 二次确认
|
||||
$confirm1 = Read-Host "确认要删除所有数据吗?(输入 YES 继续)"
|
||||
if ($confirm1 -ne "YES") {
|
||||
Write-Host "❌ 清理已取消。" -ForegroundColor Yellow
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
$confirm2 = Read-Host "最后确认:真的要删除所有数据吗?(再次输入 YES)"
|
||||
if ($confirm2 -ne "YES") {
|
||||
Write-Host "❌ 清理已取消。" -ForegroundColor Yellow
|
||||
exit 0
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "🗑️ 开始清理..." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# 停止并删除容器
|
||||
Write-Host " 1. 停止并删除容器..." -ForegroundColor Gray
|
||||
docker-compose down
|
||||
|
||||
# 删除数据卷
|
||||
Write-Host " 2. 删除数据卷..." -ForegroundColor Gray
|
||||
docker-compose down --volumes
|
||||
|
||||
# 删除镜像
|
||||
Write-Host " 3. 删除Docker镜像..." -ForegroundColor Gray
|
||||
$images = docker images --filter=reference="redcap-docker-dev*" -q
|
||||
if ($images) {
|
||||
docker rmi $images 2>&1 | Out-Null
|
||||
}
|
||||
|
||||
# 显示Docker卷列表
|
||||
Write-Host " 4. 验证清理结果..." -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
Write-Host "剩余的REDCap相关卷:" -ForegroundColor Cyan
|
||||
docker volume ls | Select-String "redcap"
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "============================================" -ForegroundColor Green
|
||||
Write-Host " ✅ 清理完成!" -ForegroundColor Green
|
||||
Write-Host "============================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "💡 提示:" -ForegroundColor Cyan
|
||||
Write-Host " • 如需重新部署:.\scripts\setup-redcap.ps1" -ForegroundColor Gray
|
||||
Write-Host " • 数据已完全删除,无法恢复" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
|
||||
|
||||
47
redcap-docker-dev/scripts/create-redcap-password.php
Normal file
47
redcap-docker-dev/scripts/create-redcap-password.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* REDCap密码哈希生成脚本
|
||||
* 直接在数据库中更新Admin密码
|
||||
*/
|
||||
|
||||
// REDCap密码哈希算法(SHA-512 + Salt)
|
||||
$username = 'Admin';
|
||||
$new_password = 'Admin123!';
|
||||
|
||||
// 生成新的salt(REDCap使用100字符的随机salt)
|
||||
$salt = '';
|
||||
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_=+[]{}|;:,.<>?~';
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$salt .= $characters[random_int(0, strlen($characters) - 1)];
|
||||
}
|
||||
|
||||
// 生成密码哈希(SHA-512(password + salt))
|
||||
$password_hash = hash('sha512', $new_password . $salt);
|
||||
|
||||
// 数据库连接信息
|
||||
$db_host = getenv('REDCAP_DB_HOST') ?: 'redcap-mysql';
|
||||
$db_name = getenv('REDCAP_DB_NAME') ?: 'redcap';
|
||||
$db_user = getenv('REDCAP_DB_USER') ?: 'redcap_user';
|
||||
$db_pass = getenv('REDCAP_DB_PASS') ?: 'redcap_pass_dev_456';
|
||||
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
|
||||
// 更新密码
|
||||
$stmt = $pdo->prepare("UPDATE redcap_auth SET password = ?, password_salt = ? WHERE username = ?");
|
||||
$result = $stmt->execute([$password_hash, $salt, $username]);
|
||||
|
||||
if ($result) {
|
||||
echo "✅ Password updated successfully!\n\n";
|
||||
echo "Username: $username\n";
|
||||
echo "New Password: $new_password\n\n";
|
||||
echo "You can now login at: http://localhost:8080/\n";
|
||||
} else {
|
||||
echo "❌ Failed to update password\n";
|
||||
}
|
||||
|
||||
} catch (PDOException $e) {
|
||||
echo "❌ Database error: " . $e->getMessage() . "\n";
|
||||
}
|
||||
|
||||
60
redcap-docker-dev/scripts/logs-redcap.ps1
Normal file
60
redcap-docker-dev/scripts/logs-redcap.ps1
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# REDCap Docker日志查看脚本
|
||||
# 版本:v1.0
|
||||
# 日期:2026-01-01
|
||||
|
||||
param(
|
||||
[string]$Service = "", # 指定服务名(redcap-web, redcap-db, phpmyadmin)
|
||||
[switch]$Follow, # 实时跟踪日志
|
||||
[int]$Tail = 50 # 显示最近N行日志
|
||||
)
|
||||
|
||||
Write-Host "📝 REDCap Docker日志" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# 切换到项目目录
|
||||
$ScriptDir = Split-Path -Parent $PSCommandPath
|
||||
$ProjectDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $ProjectDir
|
||||
|
||||
# 构建docker-compose logs命令
|
||||
$logCmd = "docker-compose logs"
|
||||
|
||||
if ($Follow) {
|
||||
$logCmd += " -f"
|
||||
} else {
|
||||
$logCmd += " --tail=$Tail"
|
||||
}
|
||||
|
||||
if ($Service) {
|
||||
$logCmd += " $Service"
|
||||
Write-Host "查看服务:$Service" -ForegroundColor Yellow
|
||||
} else {
|
||||
Write-Host "查看所有服务日志" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
if ($Follow) {
|
||||
Write-Host "实时跟踪模式(按Ctrl+C退出)" -ForegroundColor Gray
|
||||
} else {
|
||||
Write-Host "显示最近 $Tail 行日志" -ForegroundColor Gray
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "============================================" -ForegroundColor Gray
|
||||
|
||||
# 执行命令
|
||||
Invoke-Expression $logCmd
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "💡 提示:" -ForegroundColor Cyan
|
||||
Write-Host " • 查看特定服务:.\scripts\logs-redcap.ps1 -Service redcap-web" -ForegroundColor Gray
|
||||
Write-Host " • 实时跟踪:.\scripts\logs-redcap.ps1 -Follow" -ForegroundColor Gray
|
||||
Write-Host " • 显示更多行:.\scripts\logs-redcap.ps1 -Tail 100" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
Write-Host "可用服务名:" -ForegroundColor Cyan
|
||||
Write-Host " • redcap-web(REDCap Web服务)" -ForegroundColor Gray
|
||||
Write-Host " • redcap-db(MySQL数据库)" -ForegroundColor Gray
|
||||
Write-Host " • phpmyadmin(数据库管理工具)" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
|
||||
|
||||
23
redcap-docker-dev/scripts/reset-admin-password.php
Normal file
23
redcap-docker-dev/scripts/reset-admin-password.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* REDCap Admin密码重置脚本
|
||||
* 用途:重置Admin用户密码
|
||||
*/
|
||||
|
||||
require_once '/var/www/html/redcap/redcap_connect.php';
|
||||
require_once APP_PATH_CLASSES . 'Authentication.php';
|
||||
|
||||
$username = 'Admin';
|
||||
$new_password = 'Admin123!';
|
||||
|
||||
echo "Resetting password for user: $username\n";
|
||||
$result = Authentication::setPassword($username, $new_password, true);
|
||||
|
||||
if ($result) {
|
||||
echo "✅ Password reset successful!\n";
|
||||
echo "Username: Admin\n";
|
||||
echo "New Password: Admin123!\n";
|
||||
} else {
|
||||
echo "❌ Password reset failed!\n";
|
||||
}
|
||||
|
||||
161
redcap-docker-dev/scripts/setup-redcap.ps1
Normal file
161
redcap-docker-dev/scripts/setup-redcap.ps1
Normal file
@@ -0,0 +1,161 @@
|
||||
# REDCap Docker一键部署脚本
|
||||
param([switch]$SkipCheck, [switch]$Force)
|
||||
|
||||
Write-Host "============================================" -ForegroundColor Cyan
|
||||
Write-Host " REDCap Docker环境一键部署脚本" -ForegroundColor Cyan
|
||||
Write-Host "============================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
$ScriptDir = Split-Path -Parent $PSCommandPath
|
||||
$ProjectDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $ProjectDir
|
||||
Write-Host "工作目录: $ProjectDir" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# 步骤 1: 环境检查
|
||||
if (-not $SkipCheck) {
|
||||
Write-Host "步骤 1/7: 环境检查..." -ForegroundColor Yellow
|
||||
|
||||
Write-Host " 检查Docker..." -NoNewline
|
||||
$null = docker --version 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host " X" -ForegroundColor Red
|
||||
Write-Host "Docker未安装或未运行!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Write-Host " OK" -ForegroundColor Green
|
||||
|
||||
Write-Host " 检查Docker Compose..." -NoNewline
|
||||
$null = docker-compose --version 2>&1
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host " X" -ForegroundColor Red
|
||||
Write-Host "Docker Compose未安装!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Write-Host " OK" -ForegroundColor Green
|
||||
|
||||
Write-Host " 检查REDCap源码..." -NoNewline
|
||||
if (-not (Test-Path "..\redcap15.8.0\redcap\index.php")) {
|
||||
Write-Host " X" -ForegroundColor Red
|
||||
Write-Host "REDCap源码未找到!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Write-Host " OK" -ForegroundColor Green
|
||||
Write-Host "环境检查通过!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# 步骤 2: 创建.env文件
|
||||
Write-Host "步骤 2/7: 配置环境变量..." -ForegroundColor Yellow
|
||||
|
||||
$envExists = Test-Path ".env"
|
||||
if (-not $envExists) {
|
||||
Write-Host " 从模板创建.env文件..." -ForegroundColor Gray
|
||||
$templateExists = Test-Path "env.template"
|
||||
if (-not $templateExists) {
|
||||
Write-Host " 未找到env.template!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
Copy-Item "env.template" ".env"
|
||||
Write-Host " .env文件已创建" -ForegroundColor Green
|
||||
}
|
||||
if ($envExists) {
|
||||
Write-Host " .env文件已存在" -ForegroundColor Green
|
||||
}
|
||||
Write-Host ""
|
||||
|
||||
# 步骤 3: 检查端口
|
||||
Write-Host "步骤 3/7: 检查端口占用..." -ForegroundColor Yellow
|
||||
|
||||
$ports = @(8080, 3306, 8081)
|
||||
$portsInUse = @()
|
||||
|
||||
foreach ($port in $ports) {
|
||||
$check = netstat -ano | Select-String ":$port " | Select-Object -First 1
|
||||
if ($check) {
|
||||
Write-Host " 端口 $port 已被占用" -ForegroundColor Yellow
|
||||
$portsInUse += $port
|
||||
continue
|
||||
}
|
||||
Write-Host " 端口 $port 可用" -ForegroundColor Green
|
||||
}
|
||||
|
||||
if ($portsInUse.Count -gt 0) {
|
||||
Write-Host ""
|
||||
Write-Host "警告: 部分端口被占用!" -ForegroundColor Yellow
|
||||
if (-not $Force) {
|
||||
$continue = Read-Host "是否继续? (Y/N)"
|
||||
if ($continue -ne "Y") {
|
||||
Write-Host "部署已取消" -ForegroundColor Yellow
|
||||
exit 0
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Host ""
|
||||
|
||||
# 步骤 4: 清理旧容器
|
||||
if ($Force) {
|
||||
Write-Host "步骤 4/7: 清理旧容器..." -ForegroundColor Yellow
|
||||
docker-compose down 2>&1 | Out-Null
|
||||
Write-Host " 旧容器已清理" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
}
|
||||
if (-not $Force) {
|
||||
Write-Host "步骤 4/7: 跳过清理 (使用 -Force 强制清理)" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# 步骤 5: 构建镜像
|
||||
Write-Host "步骤 5/7: 构建Docker镜像..." -ForegroundColor Yellow
|
||||
Write-Host " 这可能需要几分钟..." -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
|
||||
docker-compose build
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "Docker镜像构建失败!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "Docker镜像构建成功!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# 步骤 6: 启动容器
|
||||
Write-Host "步骤 6/7: 启动容器..." -ForegroundColor Yellow
|
||||
|
||||
docker-compose up -d
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host "容器启动失败!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Host "容器启动成功!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# 步骤 7: 等待服务就绪
|
||||
Write-Host "步骤 7/7: 等待服务就绪..." -ForegroundColor Yellow
|
||||
Write-Host " 等待MySQL启动 (30秒)..." -ForegroundColor Gray
|
||||
Start-Sleep -Seconds 30
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "容器状态:" -ForegroundColor Cyan
|
||||
docker-compose ps
|
||||
|
||||
# 部署完成
|
||||
Write-Host ""
|
||||
Write-Host "============================================" -ForegroundColor Green
|
||||
Write-Host " REDCap Docker环境部署完成!" -ForegroundColor Green
|
||||
Write-Host "============================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "服务访问地址:" -ForegroundColor Cyan
|
||||
Write-Host " REDCap: http://localhost:8080" -ForegroundColor White
|
||||
Write-Host " phpMyAdmin: http://localhost:8081" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "下一步操作:" -ForegroundColor Cyan
|
||||
Write-Host " 1. 访问 http://localhost:8080/install.php" -ForegroundColor White
|
||||
Write-Host " 2. 数据库配置:" -ForegroundColor White
|
||||
Write-Host " Host: redcap-db" -ForegroundColor Gray
|
||||
Write-Host " Database: redcap" -ForegroundColor Gray
|
||||
Write-Host " User: redcap_user" -ForegroundColor Gray
|
||||
Write-Host " Password: redcap_pass_dev_456" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
45
redcap-docker-dev/scripts/start-redcap.ps1
Normal file
45
redcap-docker-dev/scripts/start-redcap.ps1
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# REDCap Docker环境启动脚本
|
||||
# 版本:v1.0
|
||||
# 日期:2026-01-01
|
||||
|
||||
Write-Host "🚀 启动REDCap Docker环境..." -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# 切换到项目目录
|
||||
$ScriptDir = Split-Path -Parent $PSCommandPath
|
||||
$ProjectDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $ProjectDir
|
||||
|
||||
# 检查Docker是否运行
|
||||
$dockerRunning = docker info 2>&1 | Select-String "Server Version"
|
||||
if (-not $dockerRunning) {
|
||||
Write-Host "❌ Docker未运行。请先启动Docker Desktop。" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# 启动容器
|
||||
docker-compose up -d
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host ""
|
||||
Write-Host "⏳ 等待服务就绪(10秒)..." -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds 10
|
||||
|
||||
Write-Host ""
|
||||
Write-Host "✅ REDCap环境已启动!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "📋 服务访问地址:" -ForegroundColor Cyan
|
||||
Write-Host " • REDCap: http://localhost:8080" -ForegroundColor White
|
||||
Write-Host " • phpMyAdmin: http://localhost:8081" -ForegroundColor White
|
||||
Write-Host ""
|
||||
Write-Host "📊 容器状态:" -ForegroundColor Cyan
|
||||
docker-compose ps
|
||||
Write-Host ""
|
||||
} else {
|
||||
Write-Host "❌ 启动失败!" -ForegroundColor Red
|
||||
Write-Host "请检查日志:.\scripts\logs-redcap.ps1" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
31
redcap-docker-dev/scripts/stop-redcap.ps1
Normal file
31
redcap-docker-dev/scripts/stop-redcap.ps1
Normal file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env pwsh
|
||||
# REDCap Docker环境停止脚本
|
||||
# 版本:v1.0
|
||||
# 日期:2026-01-01
|
||||
|
||||
Write-Host "⏹️ 停止REDCap Docker环境..." -ForegroundColor Yellow
|
||||
Write-Host ""
|
||||
|
||||
# 切换到项目目录
|
||||
$ScriptDir = Split-Path -Parent $PSCommandPath
|
||||
$ProjectDir = Split-Path -Parent $ScriptDir
|
||||
Set-Location $ProjectDir
|
||||
|
||||
# 停止容器(保留数据)
|
||||
docker-compose stop
|
||||
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host ""
|
||||
Write-Host "✅ REDCap环境已停止!" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "💡 提示:" -ForegroundColor Cyan
|
||||
Write-Host " • 数据已保留在Docker卷中" -ForegroundColor Gray
|
||||
Write-Host " • 重新启动:.\scripts\start-redcap.ps1" -ForegroundColor Gray
|
||||
Write-Host " • 完全清理(删除数据):.\scripts\clean-redcap.ps1" -ForegroundColor Gray
|
||||
Write-Host ""
|
||||
} else {
|
||||
Write-Host "❌ 停止失败!" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user