@zhengyizhao/deploy-helper 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/PUBLISHING.md +86 -0
- package/README.md +506 -59
- package/package.json +7 -1
- package/src/commands/backup.js +55 -16
- package/src/commands/env.js +25 -16
- package/src/commands/init.js +444 -67
- package/src/commands/rollback.js +82 -25
- package/src/commands/status.js +149 -47
- package/src/commands/update.js +72 -37
- package/src/utils/config.js +25 -1
- package/src/utils/detect.js +144 -12
- package/src/utils/setup.js +379 -31
- package/src/utils/ssh.js +32 -7
package/PUBLISHING.md
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# 发布流程
|
|
2
|
+
|
|
3
|
+
## 1. 版本号
|
|
4
|
+
|
|
5
|
+
`package.json` 和 `src/index.js` 中的版本号保持一致:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# package.json
|
|
9
|
+
"version": "x.y.z"
|
|
10
|
+
|
|
11
|
+
# src/index.js
|
|
12
|
+
console.log(chalk.cyan.bold('\n🚀 deploy-helper') + chalk.gray(' vx.y.z ...'))
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
版本规则(语义化版本):
|
|
16
|
+
- `patch`(0.2.**1**):bugfix
|
|
17
|
+
- `minor`(0.**3**.0):新功能,向下兼容
|
|
18
|
+
- `major`(**1**.0.0):破坏性变更
|
|
19
|
+
|
|
20
|
+
## 2. 发布前检查
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# 语法检查
|
|
24
|
+
node --check src/utils/ssh.js
|
|
25
|
+
node --check src/utils/setup.js
|
|
26
|
+
node --check src/utils/config.js
|
|
27
|
+
node --check src/utils/detect.js
|
|
28
|
+
node --check src/commands/init.js
|
|
29
|
+
node --check src/commands/update.js
|
|
30
|
+
node --check src/commands/status.js
|
|
31
|
+
node --check src/commands/rollback.js
|
|
32
|
+
node --check src/commands/backup.js
|
|
33
|
+
node --check src/commands/env.js
|
|
34
|
+
node --check src/index.js
|
|
35
|
+
|
|
36
|
+
# 加载验证
|
|
37
|
+
node --input-type=module -e "import('./src/index.js').then(()=>{})"
|
|
38
|
+
|
|
39
|
+
# 预览打包内容(确认无敏感文件)
|
|
40
|
+
npm pack --dry-run
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`.npmignore` 已配置排除 `.claude/`、`.git/` 等目录,无需手动处理。
|
|
44
|
+
|
|
45
|
+
## 3. 提交并推送
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
git add -A
|
|
49
|
+
git commit -m "Bump version to x.y.z"
|
|
50
|
+
git push
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 4. 登录 npm
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npm login
|
|
57
|
+
# 输入 npmjs.com 用户名、密码
|
|
58
|
+
# 如开启了 2FA,准备好 authenticator OTP
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 5. 发布
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# 带 OTP(推荐,避免二次提示)
|
|
65
|
+
npm publish --access public --otp=<6位OTP码>
|
|
66
|
+
|
|
67
|
+
# 不带 OTP(若账号未开启 2FA)
|
|
68
|
+
npm publish --access public
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
发布成功输出示例:
|
|
72
|
+
```
|
|
73
|
+
npm notice 📦 @zhengyizhao/deploy-helper@0.2.0
|
|
74
|
+
npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access
|
|
75
|
+
+ @zhengyizhao/deploy-helper@0.2.0
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 6. 验证
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# 查看 npm 上的最新版本
|
|
82
|
+
npm view @zhengyizhao/deploy-helper version
|
|
83
|
+
|
|
84
|
+
# 用 npx 测试(加 --yes 跳过确认)
|
|
85
|
+
npx --yes @zhengyizhao/deploy-helper@latest --version
|
|
86
|
+
```
|
package/README.md
CHANGED
|
@@ -1,73 +1,349 @@
|
|
|
1
|
-
#
|
|
1
|
+
# deploy-helper
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Deploy your project to any VPS by answering a few questions.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
No need to know Nginx, PM2, Certbot, or supervisor — deploy-helper handles server configuration, process management, HTTPS certificates, and code updates for you.
|
|
6
|
+
|
|
7
|
+
[中文文档](#中文文档)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @zhengyizhao/deploy-helper init
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or install globally:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g @zhengyizhao/deploy-helper
|
|
21
|
+
deploy-helper init
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## How It Works
|
|
27
|
+
|
|
28
|
+
**Web service** (5 steps):
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
[1/5] Server credentials → Enter IP, SSH key/password, connection tested immediately
|
|
32
|
+
[2/5] Project info → Auto-detect type, version, start command — confirm each
|
|
33
|
+
[3/5] Domain & HTTPS → Optional, auto-issue Let's Encrypt certificate
|
|
34
|
+
[4/5] Install server env → Install dependencies as needed, skip if already installed
|
|
35
|
+
[5/5] Upload & start → Upload → start process → configure Nginx → health check
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Background script / cron job** (4 steps, skips domain and Nginx):
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
[1/4] Server credentials
|
|
42
|
+
[2/4] Project info (including run mode selection)
|
|
43
|
+
[3/4] Install server env
|
|
44
|
+
[4/4] Upload & start
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
After deployment:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
🎉 Deployment successful!
|
|
51
|
+
|
|
52
|
+
# Web service
|
|
53
|
+
URL: https://example.com
|
|
54
|
+
|
|
55
|
+
# Cron job
|
|
56
|
+
Schedule: 0 2 * * *
|
|
57
|
+
Logs: tail -f /var/log/myapp.log
|
|
58
|
+
|
|
59
|
+
# Background script
|
|
60
|
+
Status: supervisorctl status myapp
|
|
61
|
+
Stdout: tail -f /var/log/myapp.out.log
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Commands
|
|
67
|
+
|
|
68
|
+
| Command | Description |
|
|
69
|
+
|---------|-------------|
|
|
70
|
+
| `deploy-helper init` | First-time deployment, fully guided |
|
|
71
|
+
| `deploy-helper update` | Push latest code and restart (supports multiple servers) |
|
|
72
|
+
| `deploy-helper status` | View process status, memory usage, recent logs |
|
|
73
|
+
| `deploy-helper rollback` | Roll back to a previous snapshot |
|
|
74
|
+
| `deploy-helper env` | Upload / pull / diff `.env` files |
|
|
75
|
+
| `deploy-helper backup` | Database backup (MySQL / PostgreSQL / MongoDB) |
|
|
76
|
+
| `deploy-helper servers` | Manage multiple servers |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Run Modes
|
|
81
|
+
|
|
82
|
+
Choose one during `init`. This determines process management and whether Nginx is configured:
|
|
83
|
+
|
|
84
|
+
| Mode | Use case | Process manager | Nginx |
|
|
85
|
+
|------|----------|----------------|-------|
|
|
86
|
+
| **Web service** | API, website, Next.js | PM2 / supervisor (auto-restart) | ✓ Reverse proxy |
|
|
87
|
+
| **Background script** | Crawler, queue consumer, long-running task | PM2 / supervisor (restart on crash only) | ✗ |
|
|
88
|
+
| **Cron job** | Scheduled sync, periodic cleanup | System crontab | ✗ |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Supported Project Types
|
|
93
|
+
|
|
94
|
+
### Node.js
|
|
95
|
+
|
|
96
|
+
Auto-detects: `.nvmrc` / `.node-version` / `package.json engines.node` → Node.js version; `package.json scripts.start` / common entry files → start command.
|
|
97
|
+
|
|
98
|
+
- Process manager: **PM2** (auto-restart, starts on boot)
|
|
99
|
+
- Works with `npm start`, `node server.js`, `next start`, and everything else
|
|
100
|
+
- **Script mode**: PM2 with `--no-autorestart` — won't restart after a clean exit
|
|
101
|
+
- **Cron mode**: writes to crontab, logs to `/var/log/<appname>.log`
|
|
102
|
+
|
|
103
|
+
### Python
|
|
104
|
+
|
|
105
|
+
Auto-detects: `.python-version` / `pyproject.toml` → Python version; `requirements.txt` → framework (FastAPI / Django / Flask) → recommended start command; `environment.yml` / `conda-lock.yml` → conda mode.
|
|
106
|
+
|
|
107
|
+
Process manager: **supervisor** (auto-restart, starts on boot, logs to `/var/log/<appname>.out.log` + `.err.log`)
|
|
108
|
+
|
|
109
|
+
**pip mode** (has `requirements.txt`)
|
|
110
|
+
- Installs Python automatically if missing (deadsnakes PPA, supports 3.8–3.13), skips if already installed
|
|
111
|
+
- Creates a virtualenv — all packages isolated inside `venv/`, nothing written to the system
|
|
112
|
+
- FastAPI → uvicorn; Django / Flask → gunicorn
|
|
113
|
+
- **Script mode**: supervisor `autorestart=unexpected` — only restarts on crash, not on clean exit
|
|
114
|
+
- **Cron mode**: writes to crontab, runs using the venv Python
|
|
115
|
+
|
|
116
|
+
**conda mode** (has `environment.yml`)
|
|
117
|
+
- Installs Miniconda to `/opt/miniconda3` automatically, skips if already present
|
|
118
|
+
- Creates the conda environment from `environment.yml` (`conda env create -n <appname>`); on re-deploy, runs `--prune` for incremental updates
|
|
119
|
+
- Start command runs via `conda run -n <appname> --no-capture-output` — no `conda activate` needed
|
|
120
|
+
|
|
121
|
+
**Generate environment.yml locally**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
conda activate <your-env-name>
|
|
125
|
+
conda env export > environment.yml
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
> If your environment includes CUDA / cudatoolkit or other system-level packages, use Docker instead (see below) to avoid GPU driver version mismatches.
|
|
129
|
+
|
|
130
|
+
### Docker
|
|
131
|
+
|
|
132
|
+
Works for **everything** deploy-helper doesn't natively support: Java, Go, Rust, C++, CUDA, multi-service orchestration… As long as you have a Dockerfile, the deployment is language-agnostic.
|
|
133
|
+
|
|
134
|
+
Auto-detects:
|
|
135
|
+
- `Dockerfile` — noted if present, guided if missing
|
|
136
|
+
- `docker-compose.yml` / `docker-compose.yaml` / `compose.yml` / `compose.yaml` — used automatically
|
|
137
|
+
- `EXPOSE` in Dockerfile or `ports` in compose file — reads the host port
|
|
138
|
+
|
|
139
|
+
Two deploy modes:
|
|
140
|
+
|
|
141
|
+
| Mode | Condition | Command |
|
|
142
|
+
|------|-----------|---------|
|
|
143
|
+
| Compose mode | compose file detected | `docker compose -f <file> up -d --build --remove-orphans` |
|
|
144
|
+
| Single-container mode | Dockerfile only | `docker build` + `docker run --restart unless-stopped` |
|
|
145
|
+
|
|
146
|
+
**Docker install**: the tool checks `command -v docker` first and skips installation if Docker is already present. Many cloud provider images ship with Docker pre-installed.
|
|
147
|
+
|
|
148
|
+
**.env files**: not uploaded by default (may contain secrets). If a local `.env` is detected, you'll be asked whether to upload it; if you decline, the tool shows the server path where you can create it manually.
|
|
149
|
+
|
|
150
|
+
### Static Sites
|
|
151
|
+
|
|
152
|
+
Plain HTML / CSS / JS, served directly by Nginx. Gzip and SPA fallback routing are configured automatically. Build output in `dist/` is uploaded normally (not skipped).
|
|
6
153
|
|
|
7
154
|
---
|
|
8
155
|
|
|
9
|
-
##
|
|
156
|
+
## Other Languages
|
|
10
157
|
|
|
11
|
-
|
|
158
|
+
> Java, C++, Go, Rust, CUDA, R…
|
|
12
159
|
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
160
|
+
Recommended path: write a Dockerfile to package your runtime environment, then choose the Docker type. deploy-helper doesn't need to know your language — it just runs the container. When you select `Other`, the tool prints these starter templates:
|
|
161
|
+
|
|
162
|
+
**Python + conda / CUDA**
|
|
163
|
+
```dockerfile
|
|
164
|
+
FROM continuumio/miniconda3
|
|
165
|
+
WORKDIR /app
|
|
166
|
+
COPY environment.yml .
|
|
167
|
+
RUN conda env create -f environment.yml -n myenv
|
|
168
|
+
COPY . .
|
|
169
|
+
CMD ["conda", "run", "-n", "myenv", "--no-capture-output", "python", "main.py"]
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Java (Maven + JDK 21)**
|
|
173
|
+
```dockerfile
|
|
174
|
+
FROM maven:3.9-eclipse-temurin-21-alpine AS build
|
|
175
|
+
WORKDIR /app
|
|
176
|
+
COPY pom.xml .
|
|
177
|
+
RUN mvn dependency:resolve -q
|
|
178
|
+
COPY src ./src
|
|
179
|
+
RUN mvn package -DskipTests -q
|
|
180
|
+
FROM eclipse-temurin:21-jre-alpine
|
|
181
|
+
COPY --from=build /app/target/*.jar app.jar
|
|
182
|
+
EXPOSE 8080
|
|
183
|
+
CMD ["java", "-jar", "app.jar"]
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Go**
|
|
187
|
+
```dockerfile
|
|
188
|
+
FROM golang:1.22-alpine AS build
|
|
189
|
+
WORKDIR /app
|
|
190
|
+
COPY go.mod go.sum ./
|
|
191
|
+
RUN go mod download
|
|
192
|
+
COPY . .
|
|
193
|
+
RUN go build -o main .
|
|
194
|
+
FROM alpine:latest
|
|
195
|
+
COPY --from=build /app/main .
|
|
196
|
+
EXPOSE 8080
|
|
197
|
+
CMD ["./main"]
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Dockerfile reference: https://docs.docker.com/get-started/
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## update
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
deploy-helper update
|
|
208
|
+
```
|
|
18
209
|
|
|
19
|
-
|
|
210
|
+
- Creates a code snapshot before deploying — rollback is always available
|
|
211
|
+
- Reuses init's startup logic: appMode / conda / composeFile all respected
|
|
212
|
+
- Health check after restart (PM2 online / supervisor RUNNING / container running)
|
|
213
|
+
- Multi-server support: parallel, serial, or rolling strategies
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## rollback
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
deploy-helper rollback
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Every `update` creates a snapshot automatically (last 5 kept). Rolling back:
|
|
224
|
+
|
|
225
|
+
1. Backs up the current version first (so you can undo the rollback)
|
|
226
|
+
2. Stops the service
|
|
227
|
+
3. Restores code via rsync (preserves `venv/` / `node_modules/`, only replaces code)
|
|
228
|
+
4. Restarts the service + health check
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## env
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
deploy-helper env
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
- **Push**: local `.env` → server (backs up the old one first, sets permissions to 600, restarts service)
|
|
239
|
+
- **Pull**: server `.env` → local
|
|
240
|
+
- **Diff**: shows key-level differences (added / missing / changed values)
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## backup
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
deploy-helper backup
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Supports MySQL, PostgreSQL, and MongoDB:
|
|
251
|
+
|
|
252
|
+
- Immediate backup (dump + gzip)
|
|
253
|
+
- List / download previous backups (last 10 kept)
|
|
254
|
+
- Scheduled automatic backups (crontab)
|
|
255
|
+
|
|
256
|
+
**Security**: database credentials for scheduled backups are stored in `/etc/deploy-helper/<appname>.creds` (chmod 600, owned by root). The backup script itself is chmod 700 — passwords are never exposed in world-readable locations.
|
|
257
|
+
|
|
258
|
+
---
|
|
259
|
+
|
|
260
|
+
## Requirements
|
|
261
|
+
|
|
262
|
+
**Local machine**
|
|
263
|
+
- Node.js 18+
|
|
264
|
+
|
|
265
|
+
**Server**
|
|
266
|
+
- Ubuntu 20.04 / 22.04 / 24.04
|
|
267
|
+
- Root access or sudo
|
|
268
|
+
- Ports open: 22 (SSH), 80 (HTTP), 443 (HTTPS if needed)
|
|
269
|
+
|
|
270
|
+
**Nothing needs to be pre-installed on the server** — Nginx, Node.js, Python, Docker, PM2, supervisor, and certbot are all installed on demand, and skipped if already present.
|
|
271
|
+
|
|
272
|
+
---
|
|
273
|
+
|
|
274
|
+
## Config File
|
|
275
|
+
|
|
276
|
+
After the first deployment, `.deploy-config.json` is written to your project root. It stores the server address, deploy path, start command, and more. The tool automatically adds it to `.gitignore` — it may contain passwords or keys and should never be committed.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## License
|
|
281
|
+
|
|
282
|
+
MIT
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
# 中文文档
|
|
287
|
+
|
|
288
|
+
> 把项目部署到任意 VPS,回答几个问题就够了。
|
|
289
|
+
|
|
290
|
+
不需要懂 Nginx、PM2、Certbot、supervisor——工具替你搞定服务器配置、进程管理、HTTPS 证书、代码更新。
|
|
291
|
+
|
|
292
|
+
[English Documentation](#deploy-helper)
|
|
20
293
|
|
|
21
294
|
---
|
|
22
295
|
|
|
23
296
|
## 快速开始
|
|
24
297
|
|
|
25
298
|
```bash
|
|
26
|
-
npx deploy-helper
|
|
299
|
+
npx @zhengyizhao/deploy-helper init
|
|
27
300
|
```
|
|
28
301
|
|
|
29
|
-
|
|
302
|
+
或全局安装后使用:
|
|
30
303
|
|
|
304
|
+
```bash
|
|
305
|
+
npm install -g @zhengyizhao/deploy-helper
|
|
306
|
+
deploy-helper init
|
|
31
307
|
```
|
|
32
|
-
🚀 deploy-helper — 把项目部署到服务器,就这么简单
|
|
33
308
|
|
|
34
|
-
|
|
35
|
-
? 服务器 IP 地址:123.456.78.9
|
|
36
|
-
? SSH 端口:22
|
|
37
|
-
? 登录用户名:root
|
|
38
|
-
? 登录方式:SSH 密钥(推荐)
|
|
39
|
-
? SSH 密钥路径:~/.ssh/id_rsa
|
|
40
|
-
✓ 服务器连接成功!
|
|
309
|
+
---
|
|
41
310
|
|
|
42
|
-
|
|
43
|
-
ℹ 自动检测到项目类型:Node.js 应用
|
|
44
|
-
? 应用名称:my-app
|
|
45
|
-
? 部署路径:/var/www/my-app
|
|
46
|
-
? 启动命令:node index.js
|
|
47
|
-
? 端口:3000
|
|
311
|
+
## 工作流程
|
|
48
312
|
|
|
49
|
-
|
|
50
|
-
? 是否配置域名?是
|
|
51
|
-
? 你的域名:example.com
|
|
52
|
-
? 自动申请 HTTPS 证书?是
|
|
313
|
+
**Web 服务**(5 步):
|
|
53
314
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
315
|
+
```
|
|
316
|
+
[1/5] 服务器连接信息 → 输入 IP、SSH 密钥/密码,立即测试连通性
|
|
317
|
+
[2/5] 项目信息 → 自动检测类型、版本、启动命令,逐一确认
|
|
318
|
+
[3/5] 域名 & HTTPS → 可选,自动申请 Let's Encrypt 免费证书
|
|
319
|
+
[4/5] 安装服务器环境 → 按需安装依赖,已安装的跳过
|
|
320
|
+
[5/5] 上传代码并启动服务 → 上传 → 启动进程 → 配置 Nginx → 健康检查
|
|
321
|
+
```
|
|
58
322
|
|
|
59
|
-
|
|
60
|
-
✓ 项目文件上传完成
|
|
61
|
-
✓ 安装依赖
|
|
62
|
-
✓ 启动应用(PM2)
|
|
63
|
-
✓ Nginx 配置完成
|
|
64
|
-
✓ HTTPS 证书申请成功
|
|
323
|
+
**后台脚本 / 定时任务**(4 步,跳过域名和 Nginx):
|
|
65
324
|
|
|
325
|
+
```
|
|
326
|
+
[1/4] 服务器连接信息
|
|
327
|
+
[2/4] 项目信息(含运行方式选择)
|
|
328
|
+
[3/4] 安装服务器环境
|
|
329
|
+
[4/4] 上传代码并启动
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
完成后:
|
|
333
|
+
|
|
334
|
+
```
|
|
66
335
|
🎉 部署成功!
|
|
67
336
|
|
|
337
|
+
# Web 服务
|
|
68
338
|
访问地址:https://example.com
|
|
69
|
-
|
|
70
|
-
|
|
339
|
+
|
|
340
|
+
# 定时任务
|
|
341
|
+
定时计划:0 2 * * *
|
|
342
|
+
日志查看:tail -f /var/log/myapp.log
|
|
343
|
+
|
|
344
|
+
# 后台脚本
|
|
345
|
+
进程状态:supervisorctl status myapp
|
|
346
|
+
输出日志:tail -f /var/log/myapp.out.log
|
|
71
347
|
```
|
|
72
348
|
|
|
73
349
|
---
|
|
@@ -76,42 +352,213 @@ npx deploy-helper
|
|
|
76
352
|
|
|
77
353
|
| 命令 | 说明 |
|
|
78
354
|
|------|------|
|
|
79
|
-
| `deploy-helper
|
|
80
|
-
| `deploy-helper update` |
|
|
81
|
-
| `deploy-helper status` |
|
|
355
|
+
| `deploy-helper init` | 首次部署,全程引导 |
|
|
356
|
+
| `deploy-helper update` | 推送最新代码并重启(支持多服务器) |
|
|
357
|
+
| `deploy-helper status` | 查看进程状态、内存、最近日志 |
|
|
358
|
+
| `deploy-helper rollback` | 从历史快照中选择一个版本回滚 |
|
|
359
|
+
| `deploy-helper env` | 上传 / 拉取 / 对比 .env 文件 |
|
|
360
|
+
| `deploy-helper backup` | 数据库备份(MySQL / PostgreSQL / MongoDB) |
|
|
361
|
+
| `deploy-helper servers` | 管理多台服务器 |
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## 应用运行方式
|
|
366
|
+
|
|
367
|
+
init 时选择三种模式之一,影响进程管理和是否配置 Nginx:
|
|
368
|
+
|
|
369
|
+
| 模式 | 适用场景 | 进程管理 | Nginx |
|
|
370
|
+
|------|---------|---------|-------|
|
|
371
|
+
| **Web 服务** | API、网站、Next.js | PM2 / supervisor(自动重启) | ✓ 反向代理 |
|
|
372
|
+
| **后台脚本** | 爬虫、消息消费、长任务 | PM2 / supervisor(崩溃才重启) | ✗ |
|
|
373
|
+
| **定时任务** | 数据同步、定期清理 | 系统 crontab | ✗ |
|
|
82
374
|
|
|
83
375
|
---
|
|
84
376
|
|
|
85
377
|
## 支持的项目类型
|
|
86
378
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
379
|
+
### Node.js
|
|
380
|
+
|
|
381
|
+
自动检测:`.nvmrc` / `.node-version` / `package.json engines.node` → Node.js 版本;`package.json scripts.start` / 常见入口文件 → 启动命令。
|
|
382
|
+
|
|
383
|
+
- 进程管理:**PM2**(自动重启、开机自启)
|
|
384
|
+
- 支持 `npm start`、`node server.js`、`next start` 等所有启动方式
|
|
385
|
+
- **后台脚本模式**:PM2 加 `--no-autorestart`,进程正常退出后不重启
|
|
386
|
+
- **定时任务模式**:写入 crontab,日志写入 `/var/log/<appname>.log`
|
|
387
|
+
|
|
388
|
+
### Python
|
|
389
|
+
|
|
390
|
+
自动检测:`.python-version` / `pyproject.toml` → Python 版本;`requirements.txt` → 框架(FastAPI / Django / Flask)→ 推荐启动命令;`environment.yml` / `conda-lock.yml` → conda 模式。
|
|
391
|
+
|
|
392
|
+
进程管理:**supervisor**(自动重启、开机自启、日志写入 `/var/log/<appname>.out.log` + `.err.log`)
|
|
393
|
+
|
|
394
|
+
**pip 模式**(有 `requirements.txt`)
|
|
395
|
+
- 服务器无 Python 时自动安装(deadsnakes PPA,支持 3.8–3.13),已有则跳过
|
|
396
|
+
- 自动创建 virtualenv,所有包装在 `venv/` 内,不污染系统环境
|
|
397
|
+
- FastAPI → uvicorn;Django / Flask → gunicorn
|
|
398
|
+
- **后台脚本模式**:supervisor `autorestart=unexpected`(只有崩溃才重启,正常退出不重启)
|
|
399
|
+
- **定时任务模式**:写入 crontab,用 venv 内的 Python 执行
|
|
400
|
+
|
|
401
|
+
**conda 模式**(有 `environment.yml`)
|
|
402
|
+
- 服务器自动安装 Miniconda 到 `/opt/miniconda3`,已有则跳过
|
|
403
|
+
- 从 `environment.yml` 创建 conda 环境(`conda env create -n <appname>`),二次部署时 `--prune` 增量更新
|
|
404
|
+
- 启动命令通过 `conda run -n <appname> --no-capture-output` 执行,无需 `conda activate`
|
|
405
|
+
|
|
406
|
+
**本地生成 environment.yml**
|
|
407
|
+
|
|
408
|
+
```bash
|
|
409
|
+
conda activate <你的环境名>
|
|
410
|
+
conda env export > environment.yml
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
> 如果环境包含 CUDA / cudatoolkit 等系统级包,建议改用 Docker 方案(见下文),避免服务器 GPU 驱动版本不一致。
|
|
414
|
+
|
|
415
|
+
### Docker
|
|
416
|
+
|
|
417
|
+
适合**所有** deploy-helper 原生不支持的场景:Java、Go、Rust、C++、CUDA、conda 环境、多服务编排……只要你有 Dockerfile,部署流程就与语言无关。
|
|
418
|
+
|
|
419
|
+
自动检测:
|
|
420
|
+
- `Dockerfile` — 存在则提示,不存在时给出引导
|
|
421
|
+
- `docker-compose.yml` / `docker-compose.yaml` / `compose.yml` / `compose.yaml` — 自动选用
|
|
422
|
+
- Dockerfile `EXPOSE` 或 compose `ports` — 读取宿主机端口
|
|
423
|
+
|
|
424
|
+
两种部署模式:
|
|
425
|
+
|
|
426
|
+
| 模式 | 条件 | 命令 |
|
|
427
|
+
|------|------|------|
|
|
428
|
+
| Compose 模式 | 检测到 compose 文件 | `docker compose -f <file> up -d --build --remove-orphans` |
|
|
429
|
+
| 单容器模式 | 仅有 Dockerfile | `docker build` + `docker run --restart unless-stopped` |
|
|
430
|
+
|
|
431
|
+
**Docker 是否需要安装**:工具先检查服务器是否已有 Docker(`command -v docker`),已有则跳过安装步骤。许多云服务商镜像预装了 Docker,无需重复安装。
|
|
432
|
+
|
|
433
|
+
**.env 文件**:默认不上传(含敏感信息)。检测到本地 `.env` 时会询问是否上传;选择不上传时,工具会告知在服务器手动创建的路径。
|
|
434
|
+
|
|
435
|
+
### 静态网站
|
|
436
|
+
|
|
437
|
+
纯 HTML / CSS / JS,直接由 Nginx 托管,自动配置 gzip 和 SPA 回退路由。`dist/` 等构建产物会正常上传(不会被跳过)。
|
|
93
438
|
|
|
94
439
|
---
|
|
95
440
|
|
|
96
|
-
##
|
|
441
|
+
## 对于不在列表里的语言
|
|
442
|
+
|
|
443
|
+
> Java、C++、Go、Rust、CUDA、R……
|
|
97
444
|
|
|
98
|
-
-
|
|
99
|
-
|
|
445
|
+
推荐路线:写 Dockerfile 把运行环境封装进镜像,然后选 Docker 类型。deploy-helper 不需要了解你的语言细节,只负责把容器跑起来。选择 `其他` 类型时,工具会在终端直接展示以下模板:
|
|
446
|
+
|
|
447
|
+
**Python + conda / CUDA**
|
|
448
|
+
```dockerfile
|
|
449
|
+
FROM continuumio/miniconda3
|
|
450
|
+
WORKDIR /app
|
|
451
|
+
COPY environment.yml .
|
|
452
|
+
RUN conda env create -f environment.yml -n myenv
|
|
453
|
+
COPY . .
|
|
454
|
+
CMD ["conda", "run", "-n", "myenv", "--no-capture-output", "python", "main.py"]
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**Java(Maven + JDK 21)**
|
|
458
|
+
```dockerfile
|
|
459
|
+
FROM maven:3.9-eclipse-temurin-21-alpine AS build
|
|
460
|
+
WORKDIR /app
|
|
461
|
+
COPY pom.xml .
|
|
462
|
+
RUN mvn dependency:resolve -q
|
|
463
|
+
COPY src ./src
|
|
464
|
+
RUN mvn package -DskipTests -q
|
|
465
|
+
FROM eclipse-temurin:21-jre-alpine
|
|
466
|
+
COPY --from=build /app/target/*.jar app.jar
|
|
467
|
+
EXPOSE 8080
|
|
468
|
+
CMD ["java", "-jar", "app.jar"]
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**Go**
|
|
472
|
+
```dockerfile
|
|
473
|
+
FROM golang:1.22-alpine AS build
|
|
474
|
+
WORKDIR /app
|
|
475
|
+
COPY go.mod go.sum ./
|
|
476
|
+
RUN go mod download
|
|
477
|
+
COPY . .
|
|
478
|
+
RUN go build -o main .
|
|
479
|
+
FROM alpine:latest
|
|
480
|
+
COPY --from=build /app/main .
|
|
481
|
+
EXPOSE 8080
|
|
482
|
+
CMD ["./main"]
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
Dockerfile 入门:https://docs.docker.com/get-started/
|
|
100
486
|
|
|
101
487
|
---
|
|
102
488
|
|
|
103
|
-
##
|
|
489
|
+
## update — 代码更新
|
|
104
490
|
|
|
105
491
|
```bash
|
|
106
|
-
|
|
107
|
-
|
|
492
|
+
deploy-helper update
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
- 部署前自动创建代码快照,失败可立即 rollback
|
|
496
|
+
- 复用 init 的启动逻辑,appMode / conda / composeFile 全部生效
|
|
497
|
+
- 重启后健康检查(PM2 online / supervisor RUNNING / 容器 running)
|
|
498
|
+
- 支持多台服务器:并行 / 串行 / 滚动三种策略
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
502
|
+
## rollback — 版本回滚
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
deploy-helper rollback
|
|
108
506
|
```
|
|
109
507
|
|
|
508
|
+
每次 `update` 前自动创建快照,保留最近 5 个版本。回滚时:
|
|
509
|
+
|
|
510
|
+
1. 备份当前版本(以便反悔)
|
|
511
|
+
2. 停止服务
|
|
512
|
+
3. 用 rsync 还原代码(保留 `venv/` / `node_modules/`,只换代码)
|
|
513
|
+
4. 重启服务 + 健康检查
|
|
514
|
+
|
|
515
|
+
---
|
|
516
|
+
|
|
517
|
+
## env — 环境变量管理
|
|
518
|
+
|
|
519
|
+
```bash
|
|
520
|
+
deploy-helper env
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
- **上传**:本地 `.env` → 服务器(先备份旧 `.env`,权限自动设为 600,上传后重启服务)
|
|
524
|
+
- **拉取**:服务器 `.env` → 本地
|
|
525
|
+
- **对比**:显示本地和服务器的 key 差异(新增 / 缺失 / 值不同)
|
|
526
|
+
|
|
527
|
+
---
|
|
528
|
+
|
|
529
|
+
## backup — 数据库备份
|
|
530
|
+
|
|
531
|
+
```bash
|
|
532
|
+
deploy-helper backup
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
支持 MySQL / PostgreSQL / MongoDB,功能:
|
|
536
|
+
|
|
537
|
+
- 立即备份(导出 + gzip 压缩)
|
|
538
|
+
- 查看 / 下载历史备份(保留最近 10 个)
|
|
539
|
+
- 配置定时自动备份(写入 crontab)
|
|
540
|
+
|
|
541
|
+
**安全设计**:定时脚本的数据库密码存放在 `/etc/deploy-helper/<appname>.creds`(chmod 600,root 所有),脚本本身 chmod 700,不在可读位置明文暴露密码。
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## 前提条件
|
|
546
|
+
|
|
547
|
+
**本地**
|
|
548
|
+
- Node.js 18+
|
|
549
|
+
|
|
550
|
+
**服务器**
|
|
551
|
+
- Ubuntu 20.04 / 22.04 / 24.04
|
|
552
|
+
- root 权限或可 sudo
|
|
553
|
+
- 开放 22(SSH)、80(HTTP)、443(HTTPS,如需 HTTPS)端口
|
|
554
|
+
|
|
555
|
+
**不需要**提前在服务器安装任何东西——Nginx、Node.js、Python、Docker、PM2、supervisor、certbot,工具按需安装,已装的跳过。
|
|
556
|
+
|
|
110
557
|
---
|
|
111
558
|
|
|
112
559
|
## 配置文件
|
|
113
560
|
|
|
114
|
-
|
|
561
|
+
首次部署后,项目根目录生成 `.deploy-config.json`,记录服务器地址、部署路径、启动命令等。工具会自动将其加入 `.gitignore`(文件中含服务器密码 / 密钥,请勿提交到 git)。
|
|
115
562
|
|
|
116
563
|
---
|
|
117
564
|
|