部署上线 #
一、部署概述 #
本章将介绍Fastify应用的生产环境部署方法。
1.1 部署方式 #
| 方式 | 适用场景 | 优点 |
|---|---|---|
| PM2 | VPS/云服务器 | 简单易用、自动重启 |
| Docker | 容器化部署 | 环境一致、易于扩展 |
| Serverless | 无服务器架构 | 按需付费、自动扩展 |
| Kubernetes | 大规模部署 | 高可用、自动扩展 |
1.2 部署清单 #
- [ ] 环境变量配置
- [ ] 日志配置
- [ ] 错误处理
- [ ] 健康检查
- [ ] 安全配置
- [ ] 性能优化
- [ ] 监控告警
二、生产环境配置 #
2.1 环境变量 #
.env.production:
env
NODE_ENV=production
PORT=3000
HOST=0.0.0.0
LOG_LEVEL=info
DATABASE_URL=mongodb://production-server:27017/myapp
REDIS_URL=redis://production-server:6379
JWT_SECRET=your-production-secret-key
JWT_EXPIRES_IN=15m
2.2 生产配置 #
src/config/production.js:
javascript
export default {
logger: {
level: 'info',
redact: ['req.headers.authorization', 'req.headers.cookie'],
serializers: {
req(req) {
return {
method: req.method,
url: req.url,
headers: {
'user-agent': req.headers['user-agent']
}
}
}
}
},
trustProxy: true,
ignoreTrailingSlash: true,
bodyLimit: 1048576
}
2.3 优雅关闭 #
src/server.js:
javascript
import Fastify from 'fastify'
import config from './config/index.js'
import app from './app.js'
const fastify = Fastify(config)
fastify.register(app)
const signals = ['SIGINT', 'SIGTERM']
for (const signal of signals) {
process.on(signal, async () => {
fastify.log.info(`Received ${signal}, shutting down...`)
await fastify.close()
fastify.log.info('Server closed')
process.exit(0)
})
}
const start = async () => {
try {
await fastify.listen({
port: config.port,
host: config.host
})
fastify.log.info(`Server running on ${config.host}:${config.port}`)
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start()
三、PM2部署 #
3.1 安装PM2 #
bash
npm install -g pm2
3.2 PM2配置 #
ecosystem.config.js:
javascript
module.exports = {
apps: [{
name: 'fastify-app',
script: './src/server.js',
instances: 'max',
exec_mode: 'cluster',
autorestart: true,
watch: false,
max_memory_restart: '1G',
env_production: {
NODE_ENV: 'production',
PORT: 3000
},
env_staging: {
NODE_ENV: 'staging',
PORT: 3000
},
log_date_format: 'YYYY-MM-DD HH:mm:ss',
error_file: './logs/error.log',
out_file: './logs/out.log',
merge_logs: true
}]
}
3.3 PM2命令 #
bash
pm2 start ecosystem.config.js --env production
pm2 stop fastify-app
pm2 restart fastify-app
pm2 delete fastify-app
pm2 logs fastify-app
pm2 monit
pm2 list
pm2 save
pm2 startup
3.4 PM2监控 #
bash
pm2 install pm2-logrotate
pm2 set pm2-logrotate:max_size 10M
pm2 set pm2-logrotate:retain 7
四、Docker部署 #
4.1 Dockerfile #
Dockerfile:
dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine
WORKDIR /app
RUN addgroup -g 1001 -S nodejs
RUN adduser -S fastify -u 1001
COPY --from=builder --chown=fastify:nodejs /app/node_modules ./node_modules
COPY --chown=fastify:nodejs . .
USER fastify
EXPOSE 3000
ENV NODE_ENV=production
ENV PORT=3000
CMD ["node", "src/server.js"]
4.2 Docker Compose #
docker-compose.yml:
yaml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=mongodb://mongo:27017/myapp
- REDIS_URL=redis://redis:6379
depends_on:
- mongo
- redis
restart: always
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
mongo:
image: mongo:7
volumes:
- mongo_data:/data/db
restart: always
redis:
image: redis:7-alpine
volumes:
- redis_data:/data
restart: always
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
restart: always
volumes:
mongo_data:
redis_data:
4.3 Nginx配置 #
nginx.conf:
nginx
events {
worker_connections 1024;
}
http {
upstream fastify_app {
server app:3000;
keepalive 64;
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://fastify_app;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
location /health {
proxy_pass http://fastify_app/health;
access_log off;
}
}
}
4.4 Docker命令 #
bash
docker build -t fastify-app .
docker run -p 3000:3000 fastify-app
docker-compose up -d
docker-compose logs -f app
docker-compose down
五、健康检查 #
5.1 健康检查端点 #
javascript
fastify.get('/health', async (request, reply) => {
return {
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime()
}
})
fastify.get('/ready', async (request, reply) => {
const checks = {
database: await checkDatabase(),
redis: await checkRedis()
}
const healthy = Object.values(checks).every(v => v)
reply.code(healthy ? 200 : 503)
return { checks, healthy }
})
async function checkDatabase() {
try {
await fastify.mongo.db.admin().ping()
return true
} catch {
return false
}
}
async function checkRedis() {
try {
await fastify.redis.ping()
return true
} catch {
return false
}
}
六、日志管理 #
6.1 日志配置 #
javascript
const fastify = require('fastify')({
logger: {
level: 'info',
file: './logs/app.log',
redact: ['req.headers.authorization'],
formatters: {
level: (label) => {
return { level: label.toUpperCase() }
}
}
}
})
6.2 日志轮转 #
使用pm2-logrotate或logrotate:
/etc/logrotate.d/fastify-app:
text
/var/log/fastify-app/*.log {
daily
rotate 14
compress
delaycompress
notifempty
create 0640 www-data www-data
sharedscripts
postrotate
pm2 reloadLogs
endscript
}
七、监控告警 #
7.1 Prometheus监控 #
javascript
fastify.register(require('@fastify/under-pressure'), {
maxEventLoopDelay: 1000,
maxHeapUsedBytes: 100000000,
maxRssBytes: 100000000
})
fastify.get('/metrics', async (request, reply) => {
return {
memory: fastify.memoryUsage(),
eventLoopDelay: fastify.eventLoopDelay(),
cpuUsage: process.cpuUsage()
}
})
7.2 APM集成 #
使用Elastic APM:
javascript
require('elastic-apm-node').start({
serviceName: 'fastify-app',
serverUrl: process.env.APM_SERVER_URL
})
八、安全加固 #
8.1 安全配置 #
javascript
import helmet from '@fastify/helmet'
import rateLimit from '@fastify/rate-limit'
await fastify.register(helmet, {
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"]
}
}
})
await fastify.register(rateLimit, {
max: 100,
timeWindow: '1 minute'
})
8.2 HTTPS配置 #
javascript
import fs from 'fs'
const fastify = require('fastify')({
https: {
key: fs.readFileSync('./ssl/key.pem'),
cert: fs.readFileSync('./ssl/cert.pem')
}
})
九、CI/CD配置 #
9.1 GitHub Actions #
.github/workflows/deploy.yml:
yaml
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build Docker image
run: docker build -t fastify-app .
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /app
docker-compose pull
docker-compose up -d
docker image prune -f
十、云平台部署 #
10.1 AWS部署 #
使用Elastic Beanstalk或ECS:
Dockerrun.aws.json:
json
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "fastify-app",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "3000"
}
],
"Environment": [
{
"Name": "NODE_ENV",
"Value": "production"
}
]
}
10.2 Heroku部署 #
Procfile:
text
web: node src/server.js
bash
heroku create fastify-app
heroku config:set NODE_ENV=production
git push heroku main
10.3 Vercel Serverless #
api/index.js:
javascript
import Fastify from 'fastify'
import app from '../src/app.js'
const fastify = Fastify()
fastify.register(app)
export default async function handler(req, res) {
await fastify.ready()
fastify.server.emit('request', req, res)
}
十一、总结 #
本章我们学习了:
- 生产配置:环境变量、优雅关闭
- PM2部署:配置、命令、监控
- Docker部署:Dockerfile、Docker Compose、Nginx
- 健康检查:健康端点、依赖检查
- 日志管理:配置、轮转
- 监控告警:Prometheus、APM
- 安全加固:Helmet、HTTPS
- CI/CD:GitHub Actions
- 云平台:AWS、Heroku、Vercel
恭喜你完成了Fastify完全指南的学习!
最后更新:2026-03-28