forked from undefcc/MiniChat
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJenkinsfile
More file actions
196 lines (180 loc) · 9.35 KB
/
Jenkinsfile
File metadata and controls
196 lines (180 loc) · 9.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// Jenkinsfile: 拉取阿里云镜像并部署 MiniChat(简化版:仅 signaling + web)
// 查看容器环境变量: docker exec minichat-web env
// 查看容器日志: docker logs minichat-web
pipeline {
agent any
environment {
REGISTRY = 'crpi-zpvonb2nha7j0qgy.cn-shenzhen.personal.cr.aliyuncs.com'
IMAGE_NAMESPACE = 'cc4ever'
ECS_HOST = '47.115.57.172' // 替换为实际 ECS 公网IP
ECS_USER = 'root' // 或 ubuntu/ecs-user
}
stages {
stage('Prepare Deployment') {
steps {
script {
echo "准备部署 MiniChat 到 ECS..."
echo "Registry: ${REGISTRY}"
echo "ECS Host: ${ECS_HOST}"
}
}
}
stage('Deploy to ECS') {
steps {
withCredentials([
usernamePassword(credentialsId: 'aliyun-docker', usernameVariable: 'ALIYUN_DOCKER_USERNAME', passwordVariable: 'ALIYUN_DOCKER_PASSWORD'),
sshUserPrivateKey(credentialsId: 'ecs-server-key', keyFileVariable: 'SSH_KEY'),
string(credentialsId: 'minichat-cors-origin', variable: 'CORS_ORIGIN'),
string(credentialsId: 'redis-password', variable: 'REDIS_PASSWORD'),
string(credentialsId: 'mongodb-password', variable: 'MONGODB_PASSWORD')
]) {
sh '''
# 部署应用
ssh -i $SSH_KEY -o StrictHostKeyChecking=no $ECS_USER@$ECS_HOST bash << EOF
# 设置环境变量
export REGISTRY="$REGISTRY"
export IMAGE_NAMESPACE="$IMAGE_NAMESPACE"
# 登录到阿里云 Docker Registry
echo "登录到 Docker Registry..."
docker login --username=$ALIYUN_DOCKER_USERNAME --password=$ALIYUN_DOCKER_PASSWORD \$REGISTRY
# 清理旧镜像缓存,强制拉取最新
echo "清理旧镜像..."
docker rmi \$REGISTRY/\$IMAGE_NAMESPACE/minichat-web:latest 2>/dev/null || true
docker rmi \$REGISTRY/\$IMAGE_NAMESPACE/minichat-signaling:latest 2>/dev/null || true
docker rmi \$REGISTRY/\$IMAGE_NAMESPACE/minichat-gateway:latest 2>/dev/null || true
# 拉取最新镜像
echo "拉取最新镜像..."
docker pull \$REGISTRY/\$IMAGE_NAMESPACE/minichat-web:latest
docker pull \$REGISTRY/\$IMAGE_NAMESPACE/minichat-signaling:latest
docker pull \$REGISTRY/\$IMAGE_NAMESPACE/minichat-gateway:latest
# 创建网络(如果不存在)
echo "创建 Docker 网络..."
docker network create minichat-network || echo "网络已存在"
# 停止并删除旧容器
echo "停止旧容器..."
docker stop minichat-web 2>/dev/null || true
docker rm minichat-web 2>/dev/null || true
docker stop minichat-signaling 2>/dev/null || true
docker rm minichat-signaling 2>/dev/null || true
docker stop minichat-gateway 2>/dev/null || true
docker rm minichat-gateway 2>/dev/null || true
# 验证镜像
echo "验证镜像..."
docker images | grep minichat
# 启动 Signaling
echo "启动 Signaling..."
docker run -d \\
--name minichat-signaling \\
--network minichat-network \\
--add-host=host.docker.internal:host-gateway \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
--log-opt compress=true \
-e NODE_ENV=production \
-e PORT=3101 \
-e REDIS_URL="redis://host.docker.internal:6379" \
-e REDIS_PASSWORD=$REDIS_PASSWORD \
-e CORS_ORIGIN=$CORS_ORIGIN \\
-p 3101:3101 \\
--restart unless-stopped \\
\$REGISTRY/\$IMAGE_NAMESPACE/minichat-signaling:latest
# 启动 Gateway
echo "启动 Gateway..."
docker run -d \\
--name minichat-gateway \\
--network minichat-network \\
--add-host=host.docker.internal:host-gateway \
--log-driver json-file \\
--log-opt max-size=10m \\
--log-opt max-file=3 \\
--log-opt compress=true \\
-e NODE_ENV=production \\
-e PORT=4000 \\
-e CORS_ORIGIN=$CORS_ORIGIN \\
-e MONGODB_URI="mongodb://host.docker.internal:27017/minichat" \\
-p 4000:4000 \\
--restart unless-stopped \\
\$REGISTRY/\$IMAGE_NAMESPACE/minichat-gateway:latest
# 启动 Web(使用 next start)
echo "启动 Web..."
docker run -d \\
--name minichat-web \\
--network minichat-network \\
--log-driver json-file \\
--log-opt max-size=10m \\
--log-opt max-file=3 \\
--log-opt compress=true \\
-e NODE_ENV=production \\
-e PORT=3100 \\
-e HOSTNAME=0.0.0.0 \\
-p 3100:3100 \\
--restart unless-stopped \\
\$REGISTRY/\$IMAGE_NAMESPACE/minichat-web:latest
# 检查服务状态
echo "检查服务状态..."
sleep 5
docker ps --filter "name=minichat-"
# 清理悬空镜像(<none> 标签)
echo "清理悬空镜像..."
docker image prune -f
echo "部署完成!"
EOF
'''
}
}
}
stage('Health Check') {
steps {
withCredentials([
sshUserPrivateKey(credentialsId: 'ecs-server-key', keyFileVariable: 'SSH_KEY')
]) {
sh '''
ssh -i $SSH_KEY -o StrictHostKeyChecking=no $ECS_USER@$ECS_HOST << EOF
echo "检查容器健康状态..."
docker ps --filter "name=minichat-" --format "table {{.Names}}\\t{{.Status}}\\t{{.Ports}}"
echo ""
echo "检查 signaling 服务..."
docker logs --tail 20 minichat-signaling || echo "signaling 日志获取失败"
echo ""
echo "检查 gateway 服务..."
docker logs --tail 20 minichat-gateway || echo "gateway 日志获取失败"
echo ""
echo "检查 web 服务..."
docker logs --tail 20 minichat-web || echo "web 日志获取失败"
EOF
'''
}
}
}
}
post {
success {
echo '✅ MiniChat 部署成功!'
echo '访问地址: https://chat.caelus.cc'
echo '信令服务: https://chat.caelus.cc/socket.io/ (通过 NPM 代理)'
}
failure {
echo '❌ 部署失败!'
withCredentials([
sshUserPrivateKey(credentialsId: 'ecs-server-key', keyFileVariable: 'SSH_KEY')
]) {
sh '''
ssh -i $SSH_KEY -o StrictHostKeyChecking=no $ECS_USER@$ECS_HOST << EOF
echo "显示错误日志..."
echo "所有 minichat 容器状态:"
docker ps -a --filter "name=minichat-" || echo "未找到 minichat 相关容器"
echo ""
echo "查看容器日志:"
for container in minichat-web minichat-signaling minichat-gateway; do
if docker ps -a --format "{{.Names}}" | grep -q "^\$container\$"; then
echo "=== \$container 日志 ==="
docker logs --tail 30 \$container 2>&1 || echo "无法获取日志"
fi
done
EOF
'''
}
}
}
}