Procfile #
什么是 Procfile? #
Procfile 是一个文本文件,用于声明应用的进程类型和启动命令。Heroku 使用 Procfile 来确定如何启动和管理应用进程。
基本语法 #
text
<进程类型>: <命令>
示例 #
text
web: node index.js
worker: node worker.js
clock: node clock.js
release: node migrate.js
进程类型 #
Web 进程 #
Web 进程是唯一能接收外部 HTTP 流量的进程类型。
text
web: node index.js
bash
# Web Dyno 自动接收路由流量
heroku ps:scale web=3 # 启动 3 个 Web Dyno
Worker 进程 #
Worker 进程用于后台任务处理,不接收 HTTP 流量。
text
worker: node worker.js
bash
# 启动 Worker Dyno
heroku ps:scale worker=2
Clock 进程 #
Clock 进程用于定时任务调度。
text
clock: node clock.js
bash
# 启动 Clock Dyno
heroku ps:scale clock=1
Release 进程 #
Release 进程在每次发布时执行一次,用于数据库迁移等任务。
text
release: npm run migrate
进程类型详解 #
| 类型 | 说明 | 自动启动 | 接收流量 |
|---|---|---|---|
| web | Web 服务 | 是(至少 1 个) | 是 |
| worker | 后台任务 | 否 | 否 |
| clock | 定时任务 | 否 | 否 |
| release | 发布任务 | 发布时执行 | 否 |
创建 Procfile #
Node.js 应用 #
text
web: node index.js
worker: node worker.js
Python 应用 #
text
web: gunicorn app:app
worker: python worker.py
clock: python scheduler.py
release: python migrate.py
Ruby 应用 #
text
web: bundle exec puma -C config/puma.rb
worker: bundle exec sidekiq -e production -C config/sidekiq.yml
clock: bundle exec clockwork clock.rb
release: bundle exec rake db:migrate
Java 应用 #
text
web: java -jar target/myapp.jar
worker: java -jar target/worker.jar
Go 应用 #
text
web: bin/server
worker: bin/worker
多进程应用示例 #
完整 Procfile 示例 #
text
web: node server.js
worker: node worker.js
scheduler: node scheduler.js
release: npm run db:migrate
进程架构图 #
text
┌─────────────────────────────────────────┐
│ Heroku 应用 │
├─────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────┐ │
│ │ Web Dynos │ │
│ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │ web.1 │ │ web.2 │ │ │
│ │ │ HTTP │ │ HTTP │ │ │
│ │ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ Worker Dynos │ │
│ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │worker.1 │ │worker.2 │ │ │
│ │ │ Queue │ │ Queue │ │ │
│ │ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ Clock Dyno │ │
│ │ ┌─────────┐ │ │
│ │ │ clock.1 │ │ │
│ │ │ Cron │ │ │
│ │ └─────────┘ │ │
│ └─────────────────────────────────┘ │
│ │
└─────────────────────────────────────────┘
进程管理 #
查看进程状态 #
bash
# 查看所有进程
heroku ps
# 输出示例
# === web (Eco): node index.js (1)
# web.1: up 2024/01/15 10:30:00 (~ 2h ago)
#
# === worker (Eco): node worker.js (1)
# worker.1: up 2024/01/15 10:30:00 (~ 2h ago)
扩展进程 #
bash
# 扩展 Web Dyno
heroku ps:scale web=3
# 扩展 Worker Dyno
heroku ps:scale worker=5
# 同时扩展多个进程
heroku ps:scale web=2 worker=3
# 缩减到 0
heroku ps:scale worker=0
重启进程 #
bash
# 重启所有进程
heroku restart
# 重启特定进程类型
heroku restart web
# 重启特定 Dyno
heroku restart web.1
停止进程 #
bash
# 停止特定 Dyno
heroku ps:stop web.1
# 停止所有 Worker
heroku ps:stop worker
Release 进程 #
用途 #
Release 进程在每次部署时自动执行,常用于:
- 数据库迁移
- 资源编译
- 缓存预热
- 数据初始化
示例 #
text
release: npm run db:migrate && npm run seed
数据库迁移示例 #
json
// package.json
{
"scripts": {
"db:migrate": "node-pg-migrate up",
"db:rollback": "node-pg-migrate down",
"seed": "node scripts/seed.js"
}
}
text
# Procfile
release: npm run db:migrate
web: node index.js
Release 进程注意事项 #
bash
# Release 进程失败会导致部署失败
# 确保迁移脚本是幂等的
# 查看发布日志
heroku releases:info v10
# 如果 release 失败,回滚
heroku rollback
本地开发 #
Heroku Local #
bash
# 安装 Heroku Local(包含在 Heroku CLI 中)
# 使用 Procfile 本地运行
# 启动所有进程
heroku local
# 启动特定进程
heroku local web
heroku local worker
# 指定端口
heroku local --port 5000
# 指定环境文件
heroku local -f .env.local
.env 文件 #
bash
# .env 文件用于本地环境变量
DATABASE_URL=postgres://localhost:5432/myapp_dev
SECRET_KEY=dev-secret
PORT=3000
Foreman #
bash
# 也可以使用 foreman
gem install foreman
# 启动应用
foreman start
# 启动特定进程
foreman start web
高级配置 #
使用 Shell 脚本 #
text
web: ./scripts/start-web.sh
worker: ./scripts/start-worker.sh
bash
#!/bin/bash
# scripts/start-web.sh
echo "Starting web server..."
node index.js
环境变量配置 #
text
web: NODE_ENV=production node index.js
worker: QUEUE=high node worker.js
多命令组合 #
text
web: npm run build && node index.js
release: npm run db:migrate && npm run cache:warm
常见问题 #
Procfile 未找到 #
bash
# 确保 Procfile 在项目根目录
# 文件名必须是 Procfile(大写 P,无扩展名)
# 检查文件
ls -la Procfile
# 如果使用其他文件名
heroku buildpacks:set heroku/nodejs
# 并确保有 package.json 的 start 脚本
进程启动失败 #
bash
# 查看日志
heroku logs --tail
# 常见原因:
# 1. 命令不存在
# 2. 依赖未安装
# 3. 端口未正确绑定
# 4. 环境变量缺失
Web 进程绑定端口 #
javascript
// 正确:使用 PORT 环境变量
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});
// 错误:硬编码端口
app.listen(3000); // Heroku 会分配随机端口
进程超时 #
bash
# Web 进程必须在 60 秒内绑定端口
# Worker 进程没有此限制
# 长时间启动任务
# 1. 使用 release 进程预处理
# 2. 异步初始化
Procfile 最佳实践 #
1. 保持简单 #
text
# 好的做法
web: node index.js
# 避免
web: NODE_ENV=production DEBUG=* node --max-old-space-size=4096 index.js
2. 使用 npm 脚本 #
json
// package.json
{
"scripts": {
"start": "node index.js",
"worker": "node worker.js",
"migrate": "node-pg-migrate up"
}
}
text
# Procfile
web: npm start
worker: npm run worker
release: npm run migrate
3. 进程分离 #
text
# 分离关注点
web: node server.js # 处理 HTTP 请求
worker: node worker.js # 处理后台任务
scheduler: node cron.js # 定时任务
4. 健康检查 #
javascript
// 在进程中添加健康检查
process.on('SIGTERM', () => {
console.log('Received SIGTERM, shutting down gracefully...');
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
下一步 #
Procfile 掌握后,接下来学习 Dyno 管理 了解如何管理和扩展应用进程!
最后更新:2026-03-28