部署验证流程

跑通验证的 6 个步骤

1
2
3
4
5
6
7
8
9
10
11
1. 本地执行部署脚本

2. 代码上传到生产服务器 (47.242.65.47)

3. Docker 容器启动

4. Nginx 配置生效

5. 访问 http://www.chronode.net/ 能正常打开

6. 确认功能 OK

核心思想:别纸上谈兵,先实际部署一次看看

执行步骤

Step 1:本地准备

1
2
3
4
5
6
7
8
9
10
# 1. clone 项目
git clone https://github.com/xiaoxijin/gf_v3
cd gf_v3

# 2. 安装依赖
bun install

# 3. 检查部署脚本
ls -la deploy.sh
cat deploy.sh # 确认配置(服务器 IP、端口等)

Step 2:执行部署

1
2
3
# 运行部署脚本(需要设置密码环境变量)
export SERVER_PASSWORD="你的服务器密码"
bash deploy.sh

Step 3:验证结果

1
2
3
4
5
6
7
8
9
10
11
12
13
# 1. SSH 连上服务器
ssh root@47.242.65.47

# 2. 检查容器状态
docker ps

# 3. 查看日志
docker logs inventory-front
docker logs gfv3-surrealdb

# 4. 本地访问验证
curl http://www.chronode.net/health
# 或直接浏览器打开 http://www.chronode.net/

Step 4:反馈结果

向需求方汇报:

“部署脚本已执行完成:

  • ✅/❌ 容器启动成功
  • ✅/❌ 网站能访问
  • ⚠️ 发现的问题(如果有)
  • 📋 下一步建议”

常见问题排查

问题 原因 解决方案
密码错误 SERVER_PASSWORD 没设对 问需求方要
端口冲突 80/443 被占用 改配置或停掉占用服务
构建失败 Bun 版本不对 bun --version 检查
域名未解析 DNS 没配 检查域名 A 记录

部署脚本模板(GFV3 标准版)

完整模板骨架

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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/bin/bash
# ============================================
# Project Name - 部署脚本
# ============================================
# 功能:
# 1. 完整部署
# 2. 服务启停/重启
# 3. 日志与状态检查
# 4. 健康检查
# ============================================

set -euo pipefail

# ---------------- 配置区域 ----------------
SERVER_HOST="127.0.0.1"
SERVER_PORT="22"
SERVER_USER="root"
SERVER_PASSWORD="${SERVER_PASSWORD:-}" # 必须通过环境变量注入
SERVER_DIR="/opt/project"
PROJECT_NAME="project"
BRANCH="main"
FRONTEND_PORT="80"
DB_PORT="8000"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

# ------------------------------------------
# 日志函数
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
section() { echo -e "\n${CYAN}========================================${NC}"; }

# 环境变量检查
require_env() {
if [ -z "${SERVER_PASSWORD}" ]; then
error "未设置 SERVER_PASSWORD"
exit 1
fi
}

# SSH 远程执行
ssh_cmd() {
local cmd="$1"
require_env
sshpass -p "$SERVER_PASSWORD" ssh -o StrictHostKeyChecking=no -p "${SERVER_PORT}" \
"${SERVER_USER}@${SERVER_HOST}" "$cmd"
}

# 本地依赖检查
check_local_dependencies() {
section
info "检查本地依赖..."
command -v sshpass >/dev/null || { error "缺少 sshpass"; exit 1; }
command -v scp >/dev/null || { error "缺少 scp"; exit 1; }
command -v bun >/dev/null || { error "缺少 bun"; exit 1; }
success "本地依赖检查通过"
}

# 服务器连接检查
check_server_connection() {
section
info "检查服务器连接..."
ssh_cmd "echo connected >/dev/null"
success "服务器连接成功"
}

# 服务器依赖安装
install_server_dependencies() {
section
info "安装/检查服务器依赖..."
ssh_cmd '
set -e
sudo apt-get update
sudo apt-get install -y docker.io docker-compose-plugin rsync curl
sudo systemctl enable docker
sudo systemctl start docker
'
success "服务器依赖准备完成"
}

# 部署目录创建
setup_deploy_directory() {
section
info "创建部署目录..."
ssh_cmd "
mkdir -p ${SERVER_DIR}
mkdir -p ${SERVER_DIR}/data
mkdir -p ${SERVER_DIR}/logs
"
success "部署目录创建完成"
}

# 前端构建
build_frontend() {
section
info "本地构建前端..."
bun run build:inventory
success "构建完成"
}

# 打包上传
package_and_upload() {
section
info "上传部署产物..."
local temp_dir
temp_dir=$(mktemp -d)
cp -r dist/inventory "${temp_dir}/"
cp docker-compose.yml "${temp_dir}/"
cp -r scripts "${temp_dir}/"
sshpass -p "$SERVER_PASSWORD" scp -r -P "${SERVER_PORT}" \
"${temp_dir}/"* "${SERVER_USER}@${SERVER_HOST}:${SERVER_DIR}/"
rm -rf "${temp_dir}"
success "上传完成"
}

# 运行配置生成
setup_runtime_configs() {
section
info "生成远程运行配置..."
ssh_cmd "cat > ${SERVER_DIR}/docker-compose.prod.yml << 'EOF'
services:
app:
image: nginx:alpine
container_name: ${PROJECT_NAME}-nginx
ports:
- \"${FRONTEND_PORT}:80\"
volumes:
- ${SERVER_DIR}/dist/inventory:/usr/share/nginx/html:ro
restart: unless-stopped
EOF"
success "运行配置生成完成"
}

# 服务启动
start_services() {
section
info "启动服务..."
ssh_cmd "
cd ${SERVER_DIR}
docker compose -f docker-compose.prod.yml up -d
docker ps
"
success "服务启动完成"
}

# 服务停止
stop_services() {
section
info "停止服务..."
ssh_cmd "
cd ${SERVER_DIR}
docker compose -f docker-compose.prod.yml down
"
success "服务已停止"
}

# 服务重启
restart_services() {
stop_services
sleep 1
start_services
}

# 查看状态
check_status() {
section
info "查看状态..."
ssh_cmd "docker ps -a"
}

# 查看日志
view_logs() {
section
info "查看日志..."
ssh_cmd "cd ${SERVER_DIR} && docker compose -f docker-compose.prod.yml logs --tail=100"
}

# 健康检查
health_check() {
section
info "健康检查..."
ssh_cmd "curl -s -o /dev/null -w '%{http_code}' http://localhost:${FRONTEND_PORT}/" | \
grep -qE '200|304'
success "健康检查通过"
}

# 完整部署流程
full_deploy() {
section
info "开始完整部署..."
check_local_dependencies
check_server_connection
install_server_dependencies
setup_deploy_directory
build_frontend
package_and_upload
setup_runtime_configs
start_services
health_check
success "部署完成"
}

# 帮助信息
show_help() {
echo "用法:$0 <command>"
echo "command: deploy | start | stop | restart | status | logs | health | check"
}

# 主入口
main() {
local cmd="${1:-deploy}"
case "$cmd" in
deploy) full_deploy ;;
start) check_server_connection; start_services ;;
stop) check_server_connection; stop_services ;;
restart) check_server_connection; restart_services ;;
status) check_server_connection; check_status ;;
logs) check_server_connection; view_logs ;;
health) check_server_connection; health_check ;;
check) check_server_connection ;;
-h|--help) show_help ;;
*) error "未知命令:$cmd"; show_help; exit 1 ;;
esac
}

main "$@"

落地标准(团队规范)

  1. 命令入口:所有部署脚本必须有 main + case 子命令入口(deploy/start/stop/restart/status/logs/health)
  2. 敏感信息:所有敏感信息必须走环境变量,不允许硬编码(如 SERVER_PASSWORD="${SERVER_PASSWORD:-}"
  3. 完整流程:完整部署必须包含:依赖检查 → 连接检查 → 构建 → 上传 → 启动 → 健康检查
  4. 幂等设计:脚本必须幂等,重复执行不应破坏环境(mkdir -pdown || true 等)
  5. 日志清晰:每个阶段必须有清晰日志输出,失败要能定位(使用 info/success/warn/error + 分隔线)

CI/CD 部署流程

  • 标准流程:开发环境 → 测试环境 → 生产环境
  • 技术栈:GitHub Actions + Docker + Nginx + PM2
  • 部署闭环关键:环境分离、配置管理、验证流程、回滚方案