一个实验搞懂 Docker 和 K8s 怎么配合
🗂️ 我的项目目录(12 个关键文件)
text
/root/message-board/
│
├── backend/ ← 【Docker 相关】打包后端用的
│ ├── Dockerfile ← 告诉 Docker 怎么打包后端
│ ├── package.json ← 后端依赖列表(供 Docker 构建时用)
│ └── server.js ← 后端代码(被 Docker 打包进镜像)
│
├── frontend/ ← 【Docker 相关】打包前端用的
│ ├── Dockerfile ← 告诉 Docker 怎么打包前端
│ ├── index.html ← 前端页面(被 Docker 打包进镜像)
│ ├── app.js ← 前端逻辑(被 Docker 打包进镜像)
│ └── config.js ← 前端配置(被 Docker 打包进镜像,但 K8s 会覆盖它)
│
└── k8s/ ← 【K8s 相关】告诉 K8s 怎么部署
├── namespace.yaml ← 告诉 K8s:创建一个叫 message-board 的文件夹
├── api-deployment.yaml ← 告诉 K8s:后端容器怎么跑
├── api-service.yaml ← 告诉 K8s:后端端口怎么对外暴露
├── frontend-configmap.yaml ← 告诉 K8s:前端配置内容是什么
├── frontend-deployment.yaml ← 告诉 K8s:前端容器怎么跑
└── frontend-service.yaml ← 告诉 K8s:前端端口怎么对外暴露
一、Docker 环节:哪些文件参与了?怎么参与的?
你执行的命令
bash
docker build -t message-api:v1 ./backend docker build -t message-frontend:v1 ./frontend
第一个命令:docker build -t message-api:v1 ./backend
| 文件 | 在这个命令中扮演的角色 |
|---|---|
backend/Dockerfile |
主文件。Docker 读取它,按里面的步骤一步步执行 |
backend/package.json |
被 Dockerfile 里的 COPY package.json ./ 复制进镜像,然后执行 npm install 装依赖 |
backend/server.js |
被 Dockerfile 里的 COPY server.js ./ 复制进镜像,成为容器的运行代码 |
Dockerfile 怎么说的:
dockerfile
FROM node:20-alpine # 基础环境:装好 Node.js 的 Linux COPY package.json ./ # 把依赖列表复制进去 RUN npm install # 在镜像里安装依赖 COPY server.js ./ # 把代码复制进去 CMD ["npm", "start"] # 容器启动时执行 node server.js
最终产出:message-api:v1 镜像。这个镜像 = Node.js 环境 + 你的代码 + 依赖。
第二个命令:docker build -t message-frontend:v1 ./frontend
| 文件 | 在这个命令中扮演的角色 |
|---|---|
frontend/Dockerfile |
主文件。Docker 读取它,按里面的步骤执行 |
frontend/index.html |
被复制进镜像,成为 Nginx 提供的页面 |
frontend/app.js |
被复制进镜像,页面加载后执行 |
frontend/config.js |
被复制进镜像,但 K8s 部署时会用 ConfigMap 覆盖它 |
Dockerfile 怎么说的:
dockerfile
FROM nginx:1.25-alpine # 基础环境:装好 Nginx 的 Linux COPY index.html /usr/share/nginx/html/ # 复制页面 COPY app.js /usr/share/nginx/html/ # 复制 JS COPY config.js /usr/share/nginx/html/ # 复制配置
最终产出:message-frontend:v1 镜像。这个镜像 = Nginx + 你的前端文件。
Docker 环节总结
| 你的文件 | 被谁用了 | 用来干什么 |
|---|---|---|
backend/Dockerfile |
Docker 读取 | 指导构建后端镜像 |
backend/package.json |
Docker 构建时复制进去 | 在镜像里装依赖 |
backend/server.js |
Docker 构建时复制进去 | 成为容器的运行代码 |
frontend/Dockerfile |
Docker 读取 | 指导构建前端镜像 |
frontend/index.html |
Docker 构建时复制进去 | 成为 Nginx 的页面 |
frontend/app.js |
Docker 构建时复制进去 | 成为页面逻辑 |
frontend/config.js |
Docker 构建时复制进去 | 作为默认配置,后续被 K8s ConfigMap 覆盖 |
二、K8s 环节:哪些文件参与了?怎么参与的?
你执行的命令
bash
kubectl apply -f k8s/namespace.yaml kubectl apply -f k8s/api-deployment.yaml kubectl apply -f k8s/api-service.yaml kubectl apply -f k8s/frontend-configmap.yaml kubectl apply -f k8s/frontend-deployment.yaml kubectl apply -f k8s/frontend-service.yaml
逐一拆解每个 YAML 文件的作用
① k8s/namespace.yaml
yaml
apiVersion: v1 kind: Namespace metadata: name: message-board
作用:告诉 K8s 创建一个叫 message-board 的“文件夹”,后面所有资源都放里面。
和 Docker/K8s 的关系:纯 K8s 概念。Docker 不参与。
② k8s/api-deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: message-api
namespace: message-board
spec:
replicas: 1
template:
spec:
containers:
- name: message-api
image: message-api:v1 # ← 关键!用的就是 Docker 构建的镜像
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3000
作用:告诉 K8s——“我要运行 1 个容器,用 message-api:v1 这个镜像(Docker 刚打好的),它监听 3000 端口”。
和 Docker 的关系:image: message-api:v1 直接引用 Docker 构建的镜像。
③ k8s/api-service.yaml
yaml
apiVersion: v1
kind: Service
metadata:
name: message-api
namespace: message-board
spec:
type: NodePort
selector:
app: message-api
ports:
- port: 3000
targetPort: 3000
nodePort: 30787
作用:告诉 K8s——“把后端 Pod 的 3000 端口映射到集群的 30787 端口,让外部能访问”。
和 Docker 的关系:引用的是 Pod(容器),通过 selector: app: message-api 找到 Deployment 创建的容器。
④ k8s/frontend-configmap.yaml
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: frontend-config
namespace: message-board
data:
config.js: |
window.APP_CONFIG = {
APP_TITLE: "K8s班级留言板",
API_BASE_URL: "http://192.168.116.168:30787"
};
作用:告诉 K8s——“这里有一份前端配置文件,内容如上”。
和 Docker 的关系:这个文件的内容会覆盖 Docker 构建时打包进去的 config.js。这就是“配置与镜像分离”。
⑤ k8s/frontend-deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: message-frontend
namespace: message-board
spec:
replicas: 1
template:
spec:
containers:
- name: message-frontend
image: message-frontend:v1 # ← 关键!用的就是 Docker 构建的镜像
ports:
- containerPort: 80
volumeMounts:
- name: frontend-config
mountPath: /usr/share/nginx/html/config.js
subPath: config.js # ← 用 ConfigMap 覆盖镜像里的 config.js
volumes:
- name: frontend-config
configMap:
name: frontend-config
作用:
-
告诉 K8s——“运行 1 个前端容器,用
message-frontend:v1镜像” -
同时告诉 K8s——“把 ConfigMap 里的配置挂进去,覆盖镜像里原来的 config.js”
和 Docker 的关系:
-
image: message-frontend:v1引用 Docker 构建的镜像 -
volumeMounts用 ConfigMap 覆盖镜像里的文件
⑥ k8s/frontend-service.yaml
yaml
apiVersion: v1
kind: Service
metadata:
name: message-frontend
namespace: message-board
spec:
type: NodePort
selector:
app: message-frontend
ports:
- port: 80
targetPort: 80
nodePort: 30082
作用:告诉 K8s——“把前端 Pod 的 80 端口映射到集群的 30082 端口,让用户浏览器能访问页面”。
和 Docker 的关系:引用的是 Pod(容器),通过 selector: app: message-frontend 找到 Deployment 创建的容器。
三、一张图:每个文件对应到 Docker/K8s 的哪个环节
text
┌─────────────────────────────────────────────────────────────────────┐
│ 【Docker 环节】 │
├─────────────────────────────────────────────────────────────────────┤
│ 输入文件 → 输出 │
│ ├── backend/Dockerfile → │
│ ├── backend/package.json → message-api:v1 镜像 │
│ └── backend/server.js → │
│ │
│ ├── frontend/Dockerfile → │
│ ├── frontend/index.html → message-frontend:v1 镜像 │
│ ├── frontend/app.js → │
│ └── frontend/config.js → (默认配置,会被覆盖) │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 【K8s 环节】 │
├─────────────────────────────────────────────────────────────────────┤
│ 输入文件 → 作用 │
│ ├── namespace.yaml → 创建“message-board”文件夹 │
│ ├── api-deployment.yaml → 用 message-api:v1 启动后端容器│
│ ├── api-service.yaml → 后端暴露 30787 端口 │
│ ├── frontend-configmap.yaml → 创建前端配置(API 地址) │
│ ├── frontend-deployment.yaml → 用 message-frontend:v1 + │
│ │ ConfigMap 覆盖 config.js │
│ └── frontend-service.yaml → 前端暴露 30082 端口 │
└─────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 【最终运行】 │
├─────────────────────────────────────────────────────────────────────┤
│ 浏览器访问 http://192.168.116.168:30082 → 看到留言板页面 ✅ │
└─────────────────────────────────────────────────────────────────────┘
四、我之前疑惑的几个点,现在用文件回答
| 你的疑惑 | 用文件回答 |
|---|---|
| Docker 怎么用的? | 用 backend/Dockerfile 和 frontend/Dockerfile,分别生成 message-api:v1 和 message-frontend:v1 两个镜像 |
| K8s 怎么用的? | 用 k8s/ 目录下的 6 个 YAML 文件,告诉 K8s 怎么运行、暴露、配置这两个镜像 |
| 配置文件怎么改? | frontend/config.js 本来在镜像里,但 K8s 部署时用 frontend-configmap.yaml 覆盖它 |
| 镜像和 YAML 什么关系? | api-deployment.yaml 里的 image: message-api:v1 引用 Docker 构建的镜像;frontend-deployment.yaml 里的 image: message-frontend:v1 同理 |
| Node2 收到什么? | Node2 没有收到 YAML 文件,收到的是 K8s 的指令:“用 message-api:v1 启动容器” |
五、一句话总结
Docker 读了
backend/Dockerfile和frontend/Dockerfile,生成了 2 个镜像(message-api:v1、message-frontend:v1)。
K8s 读了k8s/目录下的 6 个 YAML 文件,拿着这 2 个镜像在集群里启动容器、暴露端口、注入配置,最终让用户通过http://192.168.116.168:30082访问到留言板。
更多推荐




所有评论(0)