Docker 与 Kubernetes 学习笔记
——从容器基础到集群编排的系统梳理
整理范围:K8s 与 Docker 的区别、Docker 三件套、docker-compose
多容器编排、K8s 核心对象与进阶四件套(ConfigMap / Secret / Ingress /
Volume),并附命令对照表与学习路线。
目录
一、先搞懂:K8s 是什么,和 Docker 什么关系
1.1 一句话定义
K8s 就是
Kubernetes,一个开源的容器编排系统——它是帮你自动部署、扩缩容和管理大量容器化应用的”自动驾驶管家”。
名字由来:Kubernetes 源自希腊语,意为”舵手、飞行员”;K 和 s 之间正好 8
个字母,故简称 K8s。它 2014 年由 Google
开源,基于其十几年大规模生产运维经验。
1.2 它解决什么问题
用 Docker
能把应用打包成容器,但线上往往是几十上百个容器一起跑:半夜某个容器挂了谁去重启?流量暴涨怎么从
3 个扩到 30 个?发版怎么做到用户无感?K8s 就是来自动干这些脏活累活的。
1.3 核心思想:声明式 + 自愈
你不用一步步下命令(命令式),而是只描述”我想要什么状态”,K8s
自己想办法达成并一直维持。比如你说”这个应用永远保持 3
个副本在线”,真掉到 2 个它会立刻拉起第 3 个——这叫自愈,是 K8s
最迷人的能力。
1.4 必懂的三个概念
| 概念 | 一句话 | 比喻 |
|---|---|---|
| Pod | 最小调度单位,包着一个或几个容器 | 豌豆荚(豆子=容器) |
| Deployment | 声明副本数,自动维持、滚动更新、回滚 | staffing 经理,有人请假就补人 |
| Service | 给会变的 Pod 一个固定入口 + 负载均衡 | 公司总机号,员工换了号码不变 |
1.5 整体架构:大脑 + 工人
控制平面(大脑):API
Server(统一入口)、etcd(存状态的数据库)、Scheduler(决定 Pod
放哪台机器)、Controller Manager(监工,不停对比”期望 vs 现实”)。
工作节点(工人):真正跑容器的地方,上面有
kubelet(听指挥、照看本机容器)、kube-proxy(网络转发)、容器运行时(containerd
/ CRI-O)。
1.6 一句话总结
你负责描述目标(写 YAML),K8s 负责让现实一直等于目标。
二、K8s 和 Docker 有什么区别
2.1 核心区别对照
| 维度 | Docker | Kubernetes |
|---|---|---|
| 定位 | 容器引擎(造容器、跑容器) | 容器编排系统(管一群容器) |
| 关注点 | 单个容器的构建与运行 | 多个容器的部署、调度、自愈、扩缩容 |
| 规模 | 适合单机、几到几十个容器 | 设计目标就是集群,几十到上万节点 |
| 高可用 | 容器挂了得你自己重启 | 自动重启、自动迁移、自动补齐副本 |
| 典型工具 | docker build / run / ps | kubectl apply / get / logs |
2.2 比喻与配合关系
Docker 是造集装箱的工厂 +
货轮上的工人,负责把货装进箱、运到指定位置;K8s
是港口调度中心,决定哪个箱子放哪条船、船超载了要不要加船、船沉了货怎么转到别的船上。
典型误解”K8s 要取代 Docker?”——没有。准确说是 K8s 在 2020 年移除了对
Docker 作为容器运行时的直接支持(去掉了 dockershim),改用兼容 CRI
标准的 containerd。你用 Docker 构建的镜像,K8s
照常能跑,镜像格式完全通用。
2.3 实际开发里怎么配合
写 Dockerfile → docker build 出镜像 → 推到镜像仓库 → kubectl apply -f
deploy.yaml → K8s 从仓库拉镜像,调度到节点跑起来。Docker
是你的开发/打包工具,K8s 是线上的运行平台。
2.4 到底学哪个
只跑一两个小项目、单机部署 → Docker + Docker Compose
就够了,轻量好上手。
团队协作、要上线、要高可用、要弹性扩缩 → 上 K8s。
初学者路线:先 Docker 入门(1-2 天)→ 再 K8s(概念多,慢慢啃)。
三、Docker 三件套:镜像 / 容器 / 仓库
3.1 镜像(Image)= 模板 / 安装盘
只读的模板,里面打包了代码、运行环境、系统库、配置文件。同一份镜像可以启动出
N 个一模一样的容器。
Dockerfile 示例:
FROM node:18-alpine # 基础镜像
WORKDIR /app
COPY package*.json ./
RUN npm install # 构建时安装依赖
COPY . .
EXPOSE 3000
CMD \”node\”, \”server.js\” # 容器启动命令
关键理解:RUN 是在构建镜像时执行;CMD 是在启动容器时执行。
3.2 容器(Container)= 镜像的运行实例
就像”类 vs 对象”的关系。容器是可写、有生命周期的(运行 / 停止 / 删除)。
docker build -t myapp:1.0 . # 用 Dockerfile 造镜像
docker run -d -p 8080:3000 myapp:1.0 # 启动容器,端口映射
docker ps # 看正在跑的容器
docker logs <容器id> # 看日志
docker exec -it <容器id> sh # 进容器里看看
3.3 仓库(Registry)= 镜像的”应用商店”
本地 build 好的镜像推上去,别人(和 K8s)就能拉下来用。公共仓库有 Docker
Hub(默认)、阿里云容器镜像服务(国内快);公司内网可用 Harbor。
docker tag myapp:1.0 registry.cn-chengdu.aliyuncs.com/myteam/myapp:1.0
docker push registry.cn-chengdu.aliyuncs.com/myteam/myapp:1.0
3.4 主线口诀
写 Dockerfile → build 出镜像 → run 成容器 → push 到仓库。Docker
的活就干完了,剩下的交给 K8s。
四、docker-compose:一条命令拉起一整套服务
4.1 为什么需要它
docker run 手动起容器,遇到”Web + 数据库 + 缓存 +
消息队列”就得敲四五条命令、记一堆参数。docker-compose
就是把它们写进一个文件,一条命令全起来。
4.2 典型场景:Node.js + MySQL + Redis
docker-compose.yml
version: “3.9”
services:
web:
build: . # 用当前目录 Dockerfile 构建
ports:
– “8080:3000”
environment:
– DB_HOST=mysql
– REDIS_HOST=redis
depends_on:
– mysql
– redis
restart: unless-stopped
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: myapp
volumes:
– mysql-data:/var/lib/mysql # 数据持久化
ports:
– “3306:3306”
redis:
image: redis:7-alpine
command: redis-server –requirepass redis123
volumes:
mysql-data: # 声明命名卷
4.3 四条救命命令
docker-compose up -d # 后台启动全部服务
docker-compose ps # 看状态
docker-compose logs -f web # 跟某个服务的日志
docker-compose down -v # 全停掉 + 顺带清掉卷
4.4 新手必踩的三个坑
depends_on 只管启动顺序,不管”就绪”。MySQL
容器起来了但数据库还没初始化完,Web
就连不上——解决:应用里加重试逻辑,或用 healthcheck。
容器之间用服务名当域名:mysql、redis 就是主机名,不用 IP。
数据一定要挂卷,否则 down 一次数据全没。
适用场景:docker-compose 适合开发环境、单机部署、CI
测试;一旦要多机、高可用、弹性伸缩,就该上 K8s。
五、K8s 部署一个真实项目(全流程)
假设要把一个 Node.js 服务部署成 3 个副本 + 对外可访问。
5.1 用 Deployment 声明”我要什么”
deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3 # 要 3 个副本
selector:
matchLabels:
app: myapp
template: # Pod 模板
metadata:
labels:
app: myapp
spec:
containers:
– name: web
image: myapp:1.0
ports:
– containerPort: 3000
resources:
requests: {cpu: “100m”, memory: “128Mi”}
limits: {cpu: “500m”, memory: “512Mi”}
5.2 用 Service 给 Pod 一个固定入口
svc.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
selector:
app: myapp # 自动找到带这个标签的 Pod
ports:
– port: 80 # 服务对外端口
targetPort: 3000 # 转发到 Pod 的端口
type: NodePort # 简单起见用 NodePort
5.3 三条命令搞定上线
kubectl apply -f deploy.yaml # 创建/更新部署
kubectl apply -f svc.yaml
kubectl get pods -l app=myapp # 看 3 个 Pod 是不是都 Running
kubectl get svc myapp-svc # 拿到端口,比如 8080
5.4 滚动更新 & 回滚
改了代码,build 出新镜像 myapp:2.0
kubectl set image deployment/myapp web=myapp:2.0
默认一个一个替换,用户全程无感知
kubectl rollout status deployment/myapp # 看更新进度
kubectl rollout undo deployment/myapp # 翻车了?一秒回滚
提示:标签(label)是 K8s 的粘合剂——Deployment 靠标签找 Pod
模板,Service 靠标签找后端 Pod,你靠标签筛选查看。搞懂 label,K8s
就通了一半。
六、K8s 进阶四件套
6.1 ConfigMap / Secret:把配置和镜像解耦
核心思想:镜像一份跑遍所有环境,变的是配置。开发 / 测试 /
生产用同一个镜像,只是数据库地址、日志级别不同。
ConfigMap 存非敏感配置(如环境变量、配置文件);Secret
存密码、token——注意它只是 Base64 编码,不是加密,kubectl get secret
-o yaml 就能看到明文。生产环境一定要开 RBAC
限制访问、加密静态存储,或对接外部密钥管理(如腾讯云 KMS、HashiCorp
Vault)。
6.2 Ingress:给 K8s 装个”智能路由器”
之前用 NodePort 访问,问题很多:端口随机、每个服务一个端口、没
HTTPS、没域名。Ingress 是集群入口的 7 层负载均衡 + 反向代理(相当于
Nginx)。
架构:用户浏览器 → 域名 → Ingress Controller(通常是 Nginx Pod)→
Ingress 规则(路由表)→ Service → Pod。前提:集群里得先装好 Ingress
Controller。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
ingressClassName: nginx
tls:
– hosts: myapp.com
secretName: myapp-tls # TLS 证书存在 Secret 里
rules:
– host: myapp.com
http:
paths:
– path: /api
pathType: Prefix
backend:
service: {name: api-svc, port: {number: 80}}
– path: /
pathType: Prefix
backend:
service: {name: web-svc, port: {number: 80}}
6.3 Volume:容器的”硬盘”
容器本身是临时的——重启、重建就没了。数据库、日志、上传文件必须挂外部存储。
| 类型 | 用途 | 特点 |
|---|---|---|
| emptyDir | Pod 内多容器共享临时数据 | Pod 删就没,纯临时 |
| hostPath | 挂宿主机目录 | 单机能用,不跨节点,不推荐生产 |
| PersistentVolumeClaim | 生产标准做法 | 用云盘/NAS,跟节点解耦 |
说明:PV 是”供给”,PVC 是”申请”,Pod 用 PVC。云环境里你只需要写
PVC,云厂商的 CSI 驱动会自动帮你把云盘接上。
七、kubectl vs docker 命令对照表
| 想做什么 | Docker | K8s(kubectl) |
|---|---|---|
| 启动 | docker run -d nginx | kubectl run nginx –image=nginx |
| 查看列表 | docker ps | kubectl get pods |
| 看详情 | docker inspect <id> | kubectl describe pod <名> |
| 看日志 | docker logs <id> | kubectl logs <pod名> |
| 进容器 | docker exec -it <id> sh | kubectl exec -it <pod名> — sh |
| 删掉 | docker rm -f <id> | kubectl delete pod <名> |
| 构建 | docker build -t app . | (K8s 不负责构建,用 Docker) |
| 状态监控 | docker stats | kubectl top pod |
本质区别:Docker 命令操作的是”一个容器”,K8s
命令操作的是”一个期望状态”——你删掉一个 Pod,K8s
会立刻再建一个补上,因为 Deployment 说要 3 个。
八、学习路线与知识地图
8.1 完整知识地图
Docker:镜像 / 容器 / 仓库 → Dockerfile → docker-compose 多容器编排。
K8s 核心:Pod / Deployment / Service → ConfigMap / Secret → Ingress →
Volume / PVC → 下一步安全 / 运维 / 上云。
进阶(按需):RBAC 权限控制、HPA
自动伸缩、三种探针(liveness/readiness/startup)、资源配额、上云(腾讯云
TKE / 阿里云 ACK)。
8.2 推荐练习环境
本地:kind(Kubernetes IN Docker,轻量、起得快)或
minikube(单节点,官方 Basics 教程就用它)。
在线:Killercoda(浏览器里的交互式 K8s 场景)、Play with
Kubernetes(免费临时集群,无需安装)。
官方教程:Kubernetes Basics
六个浏览器模块,覆盖部署、探索、暴露、扩缩、更新,边学边敲真实 kubectl
命令。
8.3 学习建议
先跑通”镜像→容器→compose”,再上 K8s 核心对象,最后用真实项目走一遍
deploy + service + ingress + PVC 全流程。
命令别死记,重点是理解”期望状态 + 调和循环”这一设计思想,它解释了 K8s
大部分行为。