在前后端分离的开发流程里,Mock服务几乎是必不可少的环节。前端同学需要在后端接口尚未就绪时模拟数据返回,测试同学也需要一份可控的假数据源来验证边界场景。当团队把服务整体迁移到Azure AKS(Azure Kubernetes Service)之后,一个很现实的问题就出现了:原本跑在本地的Mock服务如何变成一份可分发、可部署的容器镜像,并且能被AKS集群正确拉取?这就是所谓的Mock2Image过程。本文将以Node.js技术栈为例,从Dockerfile编写、Azure容器仓库推送,到AKS部署验证,完整走一遍这条链路。

一、准备Mock服务与容器化基础
首先需要有一个可以独立运行的Mock服务。这里用Express搭建一个最简单的例子,它根据请求路径返回不同的Mock数据,并通过环境变量MOCK_SCENE切换不同的数据场景,方便部署到AKS后不重新构建镜像就能切换数据。
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
const scenes = {
normal: { code: 0, msg: 'ok', data: { list: [1, 2, 3] } },
empty: { code: 0, msg: 'ok', data: { list: [] } },
error: { code: 500, msg: 'mock internal error', data: null }
};
app.get('/api/items', (req, res) => {
const scene = process.env.MOCK_SCENE || 'normal';
res.json(scenes[scene] || scenes.normal);
});
app.listen(PORT, () => console.log('mock server on ' + PORT));容器化的核心是Dockerfile。对于Node.js项目,推荐使用多阶段构建:第一阶段安装依赖并编译,第二阶段只拷贝运行所需的文件,这样可以显著减小镜像体积。很多人直接用node:20全量镜像,结果一个简单Mock服务打包出来接近1GB,拉取和调度都很慢。改用alpine基础镜像加上多阶段构建后,镜像通常能控制在200MB以内。
# 构建阶段 FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci --production COPY . . # 运行阶段 FROM node:20-alpine WORKDIR /app ENV NODE_ENV=production COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app . EXPOSE 3000 CMD ["node", "server.js"]
需要注意.dockerignore文件别忘了写,把node_modules、.git这类目录排除掉,否则本地安装过的依赖会被整个拷进构建上下文,既拖慢构建又可能在linux容器里混入不兼容的二进制文件。
二、构建镜像并推送到Azure Container Registry
AKS本身不存储镜像,它从镜像仓库拉取。Azure体系的标配是ACR(Azure Container Registry)。先在本地完成登录,然后构建并打上规范化的tag。tag里包含完整仓库地址是关键,否则docker push不知道要推到哪里。
# 登录ACR az acr login --name mymockregistry # 构建镜像并打tag,注意地址格式:仓库名.azurecr.io/镜像名:标签 docker build -t mymockregistry.azurecr.io/mock-server:v1.0.0 . # 推送镜像 docker push mymockregistry.azurecr.io/mock-server:v1.0.0
如果不想在本地装Docker,也可以直接用ACR的云端构建能力,通过az acr build把源码提交给Azure在云端构建镜像,本地只需要Azure CLI即可,对CI环境特别友好:
az acr build --registry mymockregistry \ --image mock-server:v1.0.1 \ https://github.com/your-org/mock-server.git#main
还有一个容易被忽略的权限问题:AKS集群要有权限从ACR拉镜像。最省事的做法是创建集群时附加--attach-acr参数,如果集群已经存在,也可以事后执行az aks update --name myAKS --attach-acr mymockregistry --resource-group myRG完成绑定。没做这一步,部署时Pod会一直报ImagePullBackOff错误,排查起来很浪费时间的。
三、编写部署清单并发布到AKS集群
镜像就位后,接下来写一份Deployment清单。Mock服务通常不需要持久化存储,也不需要多副本,重点是声明好环境变量和端口,让前面设计的MOCK_SCENE发挥作用。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mock-server
spec:
replicas: 1
selector:
matchLabels:
app: mock-server
template:
metadata:
labels:
app: mock-server
spec:
containers:
- name: mock-server
image: mymockregistry.azurecr.io/mock-server:v1.0.0
ports:
- containerPort: 3000
env:
- name: MOCK_SCENE
value: "normal"
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 250m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: mock-server-svc
spec:
selector:
app: mock-server
ports:
- port: 80
targetPort: 3000执行kubectl apply -f mock-deploy.yaml之后,用kubectl get pods -w观察Pod状态,从Pending到ContainerCreating再到Running,说明镜像拉取和启动都正常。如果需要从集群外部访问,可以再加一个Ingress规则,或者临时用kubectl port-forward svc/mock-server-svc 8080:80转发到本地验证接口返回。切换Mock场景时只需修改Deployment中的环境变量并重新apply,Pod滚动重启后即刻生效,完全不用重新构建镜像,这正是把场景配置外置带来的灵活性。
四、常见问题与优化建议
实际操作中有几个坑值得提前规避。第一是ImagePullBackOff,除了前面提到的ACR授权问题,还要检查镜像tag是否拼写正确,以及docker push是否真的成功。第二是Pod启动后立刻CrashLoopBackOff,多半是容器内进程启动报错,用kubectl logs看日志,常见原因是端口被配置覆盖或依赖没有正确拷贝。第三是镜像更新后集群里跑的还是旧版本,这是因为Deployment的镜像tag没变化时Kubernetes不会重新拉取,要么每次用新tag,要么设置imagePullPolicy: Always。
从工程化角度,建议把整套流程固化成脚本或CI流水线:代码提交后自动执行az acr build构建镜像,再用kubectl set image触发滚动更新。同时可以给Mock服务加一个/healthz健康检查端点,在Deployment里配置livenessProbe,避免进程假死时集群毫无感知。这套Mock2Image的工作流一旦搭建好,联调环境的Mock数据就从个人电脑上的临时脚本,升级成了团队共享、版本可控、随取随用的标准服务,对提升协作效率的帮助非常直接。
Node.jsAzure AKSMock2Image修改时间:2026-09-03 18:27:01