前后端并行开发时,接口文档定了但后端还没实现,前端只能干等着,这是很多团队都遇到过的问题。与其每次都用抓包工具改返回值,不如自己动手搭一个Mock服务,一次搭建全组共用。本文就用Node.js最主流的Express框架实现一个灵活的Mock服务,再把它打包成Docker镜像,部署到Kubernetes集群里,让团队随时随地都能访问。

一、用Express实现可配置的Mock服务
先说服务本身的设计。最简单的Mock无非是监听所有路径,根据URL返回预设数据,但这种写法不够灵活。比较优雅的做法是把Mock规则抽离成配置文件,每个接口一条规则,包含请求方法、路径、返回数据、延迟时间等字段,服务启动时统一加载。这样后续加接口只需要改配置,不用动框架代码。
下面是一个完整的实现示例。核心思路是用app.all兜底接收所有请求,然后在路由配置里查找匹配项,命中后按配置返回,支持通配符匹配和模拟网络延迟:
const express = require('express');
const fs = require('fs');
const path = require('path');
const app = express();
app.use(express.json());
// 读取mock配置文件
const mockConfig = JSON.parse(
fs.readFileSync(path.join(__dirname, 'mock-routes.json'), 'utf-8')
);
// 将路径配置转为正则,支持 :id 之类的参数占位
function compilePattern(pattern) {
const regexStr = pattern
.replace(/:[^/]+/g, '([^/]+)')
.replace(/\*/g, '(.*)');
return new RegExp('^' + regexStr + '$');
}
app.all('*', (req, res) => {
const matched = mockConfig.find(item => {
const re = compilePattern(item.path);
return re.test(req.path) && item.method.toUpperCase() === req.method;
});
if (!matched) {
return res.status(404).json({ code: 404, message: '未匹配到Mock规则: ' + req.path });
}
// 模拟网络延迟,方便前端测试loading态
const delay = matched.delay || 0;
setTimeout(() => {
if (matched.response instanceof Function) {
// 支持函数类型的动态响应
return res.json(matched.response(req));
}
res.json(matched.response);
}, delay);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log('Mock服务已启动,端口: ' + PORT));对应的mock-routes.json配置大概长这样,一目了然,非开发同学也能看懂:
[
{
"path": "/api/users",
"method": "GET",
"delay": 300,
"response": {
"code": 0,
"data": [
{ "id": 1, "name": "张三" },
{ "id": 2, "name": "李四" }
]
}
},
{
"path": "/api/users/:id",
"method": "GET",
"response": { "code": 0, "data": { "id": 1, "name": "张三" } }
},
{
"path": "/api/login",
"method": "POST",
"response": { "code": 0, "token": "mock-token-abc123" }
}
]这套方案的好处是规则和数据分离,你甚至可以按环境维护多份配置文件,通过环境变量切换。如果需要更智能的假数据,可以引入faker.js之类的库,把固定值换成随机生成的姓名、手机号、日期,让前端联调时更接近真实场景。
二、编写Dockerfile打包镜像
服务写好了,本地node app.js就能跑,但要部署到K8s,第一步是做成镜像。Node.js应用容器化有几个容易踩的坑:一是没用多阶段构建导致镜像里带着大量构建缓存;二是没处理优雅退出,Pod被杀时请求直接断掉;三是以root用户运行容器存在安全隐患。
下面这份Dockerfile针对这三点都做了处理:
FROM node:18-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install --production COPY . . FROM node:18-alpine WORKDIR /app # 使用非root用户运行 USER node COPY --from=builder --chown=node:node /app /app ENV NODE_ENV=production EXPOSE 3000 CMD ["node", "server.js"]
选alpine版本的基础镜像可以把体积从一G级别压到一百多MB,拉取和启动都快很多。--production参数确保不装devDependencies。构建和推送镜像的命令如下,注意镜像名要带上你的镜像仓库地址:
docker build -t registry.ippipp.com/mock2image/express-mock:v1.0.0 . docker push registry.ippipp.com/mock2image/express-mock:v1.0.0
如果公司没有私有仓库,也可以直接用Docker Hub或者本地构建后用kind load、minikube image load把镜像塞进本地集群,学习阶段足够用了。
三、编写K8s部署清单发布服务
镜像就绪后,接下来写部署清单。最少需要两个资源:Deployment管理Pod副本,Service提供稳定的访问入口。对于Mock服务这种无状态应用,配置并不复杂,但有几个字段值得说明。
apiVersion: apps/v1
kind: Deployment
metadata:
name: express-mock
labels:
app: express-mock
spec:
replicas: 2
selector:
matchLabels:
app: express-mock
template:
metadata:
labels:
app: express-mock
spec:
containers:
- name: express-mock
image: registry.ippipp.com/mock2image/express-mock:v1.0.0
ports:
- containerPort: 3000
readinessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 15
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: express-mock-svc
spec:
selector:
app: express-mock
ports:
- port: 80
targetPort: 3000
type: ClusterIP探针配置很重要。readinessProbe保证容器真正就绪后才接流量,避免启动瞬间就被打挂;livenessProbe则在进程假死时自动重启Pod。为此需要在Express里加一个健康检查接口,一行代码的事:app.get('/healthz', (req, res) => res.status(200).send('ok'));。
资源限额不是必须的,但强烈建议写上。Node.js的V8引擎默认堆内存可能超过容器限额,被OOMKilled杀掉是常见问题,可以在启动命令里加--max-old-space-size=256来限制堆大小,让它和容器的memory limit匹配。
四、更新策略与日常维护
部署完成只是开始,后续改了Mock规则要更新服务怎么办?最直接的流程是改代码、打新tag、推镜像,然后执行kubectl set image deployment/express-mock express-mock=registry.ippipp.com/mock2image/express-mock:v1.0.1。K8s默认的RollingUpdate策略会先起新Pod,健康检查通过后再逐个杀旧Pod,全程不断服务。
更省心的做法是把Mock规则挂到ConfigMap上,容器启动时读取配置。这样只改规则时不用重新构建镜像,执行kubectl rollout restart deployment express-mock让Pod重新加载即可。配置示例如下:
apiVersion: v1
kind: ConfigMap
metadata:
name: mock-routes
data:
mock-routes.json: |
[
{ "path": "/api/hello", "method": "GET", "response": { "code": 0, "msg": "hello" } }
]然后在Deployment的volumes和volumeMounts里把ConfigMap挂载到/app/mock-routes.json,代码里加一段文件监听或者直接依赖重启加载,就能实现配置与镜像解耦。这套Express加K8s的方案整体下来不到两百行代码和配置,就能给团队提供一个稳定可用的Mock环境,无论是日常联调还是自动化测试都能派上用场。
Express MockNode.js镜像部署K8s部署修改时间:2026-09-10 00:04:43