diff --git a/README.md b/README.md index f01a9450..609defe0 100644 --- a/README.md +++ b/README.md @@ -224,6 +224,18 @@ npm run service:status ## 🐳 Docker 部署(推荐) +### ⚠️ 首次部署必须执行 + +```bash +# 创建空的 .env 文件(非常重要!) +touch .env +``` + +> 🔴 **为什么必须先创建 .env 文件?** +> - Docker 在映射不存在的文件时会创建成**目录**而非文件 +> - .env 文件用于存储加密密钥,必须持久化保存 +> - 如果变成目录,容器将无法启动 + ### 使用 Docker Hub 镜像(最简单) > 🚀 推荐使用官方镜像,自动构建,始终保持最新版本 @@ -287,7 +299,13 @@ docker-compose up -d git clone https://github.com/Wei-Shaw//claude-relay-service.git cd claude-relay-service -# 2. 设置管理员账号密码(可选) +# 2. 初始化环境(重要!首次部署必须执行) +touch .env # 创建空文件,防止 Docker 创建成目录 + +# 如果 .env 已经错误地变成了目录,先删除: +# rm -rf .env && touch .env + +# 3. 设置管理员账号密码(可选) # 方式一:自动生成(查看容器日志获取) docker-compose up -d @@ -296,7 +314,7 @@ export ADMIN_USERNAME=cr_admin_custom export ADMIN_PASSWORD=your-secure-password docker-compose up -d -# 3. 查看管理员凭据 +# 4. 查看管理员凭据 # 自动生成的情况下: docker logs claude-relay-service | grep "管理员" diff --git a/docker-compose-init.sh b/docker-compose-init.sh new file mode 100644 index 00000000..37dee9a5 --- /dev/null +++ b/docker-compose-init.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# Docker Compose 初始化脚本 - 用于 Docker Hub 镜像部署 + +echo "🚀 Claude Relay Service Docker 初始化脚本" +echo "============================================" + +# 检查是否在正确的目录 +if [ -f "docker-compose.yml" ]; then + echo "✅ 检测到 docker-compose.yml,继续初始化..." +else + echo "⚠️ 未检测到 docker-compose.yml 文件" + echo " 请确保在包含 docker-compose.yml 的目录下运行此脚本" + echo "" + echo "如果您是从 Docker Hub 部署,请先创建 docker-compose.yml:" + echo " 参考文档:https://github.com/Wei-Shaw/claude-relay-service#docker-部署推荐" + exit 1 +fi + +# 确保 .env 文件正确创建 +echo "" +echo "📋 检查 .env 文件..." + +if [ -d ".env" ]; then + echo "❌ 检测到 .env 是目录(Docker 创建错误)" + echo " 正在修复..." + rm -rf .env + touch .env + echo "✅ 已删除目录并创建正确的 .env 文件" +elif [ ! -f ".env" ]; then + echo "📝 创建 .env 文件..." + touch .env + echo "✅ .env 文件已创建" +else + echo "✅ .env 文件已存在" +fi + +# 创建必要的目录 +echo "" +echo "📁 创建必要的目录..." +mkdir -p data logs redis_data +echo "✅ 目录创建完成" + +# 显示文件状态 +echo "" +echo "📊 当前文件状态:" +echo " .env: $([ -f .env ] && echo "✅ 文件" || echo "❌ 不存在")" +echo " data/: $([ -d data ] && echo "✅ 目录" || echo "❌ 不存在")" +echo " logs/: $([ -d logs ] && echo "✅ 目录" || echo "❌ 不存在")" +echo " redis_data/: $([ -d redis_data ] && echo "✅ 目录" || echo "❌ 不存在")" + +echo "" +echo "🎉 初始化完成!" +echo "" +echo "下一步操作:" +echo "1. 启动服务:" +echo " docker-compose up -d" +echo "" +echo "2. 查看日志获取管理员密码:" +echo " docker-compose logs claude-relay | grep '管理员'" +echo "" +echo "3. 访问管理界面:" +echo " http://your-server:3000/web" \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index a10bf1c3..4d28380a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,11 @@ version: '3.8' +# ⚠️ 重要提示:首次运行前必须执行以下命令 +# touch .env +# +# 说明:如果不先创建 .env 文件,Docker 会将其创建为目录而非文件, +# 导致容器无法正常启动。该文件用于存储加密密钥,必须持久化。 + services: # 🚀 Claude Relay Service claude-relay: @@ -18,7 +24,7 @@ services: volumes: - ./logs:/app/logs - ./data:/app/data - - ./.env:/app/.env + - ./.env:/app/.env # 必须映射,用于持久化加密密钥 depends_on: - redis networks: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 7bf3e696..9b949e59 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -3,12 +3,13 @@ set -e echo "🚀 Claude Relay Service 启动中..." -# 检查并创建 .env 文件 +# 检查 .env 文件 if [ ! -f "/app/.env" ]; then echo "📋 检测到 .env 不存在,从模板创建..." if [ -f "/app/.env.example" ]; then cp /app/.env.example /app/.env echo "✅ .env 已从模板创建" + echo "⚠️ 注意:.env 文件将在容器内生成,请确保已映射到宿主机以持久化" else echo "❌ 错误: .env.example 不存在" exit 1 @@ -69,7 +70,7 @@ if [ -f "/app/.env" ]; then echo "✅ .env 已配置" else - echo "❌ 错误: .env 文件不存在" + echo "❌ 错误: .env 文件处理失败" exit 1 fi diff --git a/scripts/docker-init.sh b/scripts/docker-init.sh new file mode 100644 index 00000000..ad81c254 --- /dev/null +++ b/scripts/docker-init.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Docker 初始化脚本 - 在宿主机上运行 + +echo "🚀 Claude Relay Service Docker 初始化" + +# 检查 .env 文件 +if [ ! -f ".env" ]; then + echo "📋 检测到 .env 文件不存在,从模板创建..." + + if [ -f ".env.example" ]; then + cp .env.example .env + echo "✅ .env 文件已创建" + + # 生成随机密钥 + echo "🔑 生成安全密钥..." + + # 生成64字符的JWT_SECRET + JWT_SECRET=$(openssl rand -base64 48 | tr -d "=+/" | cut -c1-64) + # 生成32字符的ENCRYPTION_KEY + ENCRYPTION_KEY=$(openssl rand -base64 24 | tr -d "=+/" | cut -c1-32) + + # 替换默认值 + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + sed -i '' "s/JWT_SECRET=.*/JWT_SECRET=$JWT_SECRET/" .env + sed -i '' "s/ENCRYPTION_KEY=.*/ENCRYPTION_KEY=$ENCRYPTION_KEY/" .env + else + # Linux + sed -i "s/JWT_SECRET=.*/JWT_SECRET=$JWT_SECRET/" .env + sed -i "s/ENCRYPTION_KEY=.*/ENCRYPTION_KEY=$ENCRYPTION_KEY/" .env + fi + + echo "✅ 密钥已生成并保存到 .env 文件" + echo "" + echo "📌 请妥善保管 .env 文件,它包含重要的加密密钥!" + else + echo "❌ 错误:.env.example 文件不存在" + echo "请确保在项目根目录下运行此脚本" + exit 1 + fi +else + echo "✅ .env 文件已存在,跳过创建" +fi + +# 创建必要的目录 +echo "📁 创建必要的目录..." +mkdir -p data logs redis_data +echo "✅ 目录创建完成" + +echo "" +echo "🎉 初始化完成!现在可以运行:" +echo " docker-compose up -d" \ No newline at end of file