从Docker到K8S:新手避坑指南与实战入门
🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度
这类教程最值得先看的不是它覆盖了多少知识点,而是能不能帮你把 Docker 和 Kubernetes 从“知道名字”变成“能在自己机器上跑起来、能处理实际问题”。很多人学容器和 K8S 卡在第一步:环境装不上、概念太抽象、命令敲了没反应。这个教程的价值在于,它试图用一套连贯的流程,把安装、基础命令、核心概念和简单实战串起来,目标是让你看完能自己搭出一个可用的最小环境。
但这类“速通”教程也有个通病:容易讲成命令罗列,你跟着敲完了,还是不知道为什么要这么做,遇到自己项目里的配置文件、网络问题、存储挂载照样不会。所以,我更建议把学习过程拆成三步:先确保本地或虚拟机环境能稳定运行 Docker,再用 Docker 理解容器的基础操作和镜像构建,最后用 Minikube 或 K3s 这类轻量工具上手 K8S 的核心对象和调度。下面我会按这个实际落地的顺序,把每个环节的关键操作、参数含义和最容易踩的坑点拆解一遍。
1. 先别急着看 K8S,从 Docker 环境准备和最小验证开始
很多人一上来就被 Pod、Service、Deployment 这些概念绕晕了。其实 K8S 管理的是容器,而容器最直接的体验来自 Docker。所以第一步不是安装 K8S,而是先确保你的 Docker 能正常工作。
1.1 环境选择与基础安装:虚拟机还是云主机?
你可以在 Windows、macOS 或 Linux 上安装 Docker Desktop。但对于学习,尤其是后续要接触 K8S 网络和存储,我强烈建议使用一台 Linux 虚拟机。原因有两个:一是 Linux 是 Docker 和 K8S 的原生运行环境,兼容性问题最少;二是很多生产环境也是 Linux,提前熟悉命令行操作没坏处。
- 方案一(推荐):本地虚拟机。使用 VirtualBox 或 VMware,安装一个 Ubuntu 22.04 LTS 或 CentOS 7/8 Stream。分配至少 2 核 CPU、4GB 内存和 20GB 磁盘空间。这个配置足够同时运行 Docker 和一个轻量级 K8S(如 Minikube)。
- 方案二:云服务器。在主流云服务商购买一台最低配置的按量计费云服务器(通常被称为“ECS”或“CVM”),选择 Ubuntu 或 CentOS 镜像。好处是网络环境干净,且能模拟公网访问场景。
安装 Docker 本身很简单,以 Ubuntu 为例,官方的一键安装脚本通常可靠:
# 更新软件包索引 sudo apt-get update # 安装必要工具 sudo apt-get install ca-certificates curl # 添加 Docker 官方 GPG 密钥 sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc # 设置仓库 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update # 安装 Docker 引擎 sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin安装后,最关键的一步是将当前用户加入docker组,避免每次命令都要加sudo:
sudo usermod -aG docker $USER执行后,你需要退出当前终端并重新登录,这个改动才会生效。这是第一个常见坑点:很多人加了组就直接运行docker ps,发现还是权限错误。
1.2 验证安装与理解 Docker 守护进程
环境装好,不要马上拉镜像跑容器。先做几个基础验证,理解 Docker 的组件。
检查 Docker 服务状态:
sudo systemctl status docker你应该看到
active (running)。如果没启动,用sudo systemctl start docker启动它,并用sudo systemctl enable docker设置开机自启。运行经典测试容器:
docker run hello-world这个命令会做几件事:从 Docker Hub 拉取
hello-world镜像(如果本地没有),创建一个容器,执行容器内的程序(打印一段欢迎信息),然后容器退出。如果能看到成功输出的信息,说明 Docker 引擎、镜像拉取和容器运行都正常。理解
docker ps的输出:docker ps -a-a参数会显示所有容器,包括已退出的。你会看到刚才运行的hello-world容器,状态是Exited。这里要理解几个关键字段:CONTAINER ID: 容器的唯一标识。IMAGE: 创建容器所用的镜像。COMMAND: 容器启动时运行的命令。STATUS: 容器的状态(Up、Exited)。PORTS: 容器映射到主机的端口。NAMES: 容器的名称(可自定义)。
这个阶段的目标是:确保 Docker 服务在运行,能拉取镜像,能创建和运行容器,并且你能看懂基础命令的输出。如果hello-world都跑不起来,问题通常出在网络(拉取镜像失败)、权限(用户不在 docker 组)或服务状态上。
2. 用 Docker 理解镜像、容器和基础操作
能跑通hello-world只是开始。接下来要通过一个更实际的例子,理解镜像和容器的关系,以及如何管理它们。
2.1 从拉取镜像到运行一个持久化服务
我们用一个最常用的镜像nginx来演示。
拉取镜像:
docker pull nginx:latest这里
nginx是镜像名,latest是标签(Tag),代表最新稳定版。生产环境通常使用具体版本号,如nginx:1.24,以避免因镜像更新引入意外变更。以后台模式运行一个 Nginx 容器:
docker run -d --name my-nginx -p 8080:80 nginx-d: 后台运行(detached mode)。--name my-nginx: 给容器起个名字,方便后续管理。-p 8080:80: 端口映射,将主机的 8080 端口映射到容器的 80 端口(Nginx 默认监听端口)。nginx: 使用的镜像。
验证服务: 在主机上打开浏览器,访问
http://localhost:8080(如果主机是本地虚拟机)或http://<你的服务器IP>:8080(如果是云服务器)。你应该能看到 Nginx 的欢迎页面。 同时,用docker ps可以看到一个状态为Up的容器。查看容器日志:
docker logs my-nginx这会输出容器内 Nginx 服务的访问日志和错误日志。这是排查容器内应用问题的第一个入口。
2.2 进入容器、修改内容与理解容器隔离性
容器是隔离的环境。怎么查看和修改里面的东西?
进入运行中的容器:
docker exec -it my-nginx /bin/bashexec: 在已运行的容器中执行命令。-it: 分配一个交互式终端(-i -t)。/bin/bash: 要执行的命令,即启动一个 Bash shell。 进入后,你可以像操作一台独立 Linux 主机一样,使用ls,cat,apt-get update等命令。试试cat /etc/nginx/nginx.conf查看 Nginx 配置。
理解容器内修改的临时性: 在容器内,执行
echo "Hello from container" > /usr/share/nginx/html/test.txt,然后在主机浏览器访问http://localhost:8080/test.txt,能看到你写的文字。 但是,如果你现在停止并删除这个容器:docker stop my-nginx docker rm my-nginx然后重新用
docker run -d --name new-nginx -p 8080:80 nginx启动一个新容器,再去访问/test.txt,会发现文件不见了。这说明对容器内文件系统的修改,默认只存在于该容器的生命周期内,容器删除,修改即丢失。使用数据卷(Volume)持久化数据: 为了解决上述问题,需要把容器内需要持久化的目录(如 Nginx 的 HTML 目录
/usr/share/nginx/html)挂载到主机的一个目录上。# 先在主机创建一个目录 mkdir -p ~/nginx-html # 运行容器并挂载数据卷 docker run -d --name nginx-with-volume -p 8081:80 -v ~/nginx-html:/usr/share/nginx/html nginx-v ~/nginx-html:/usr/share/nginx/html: 将主机的~/nginx-html目录挂载到容器的/usr/share/nginx/html。 现在,你在主机~/nginx-html目录下放一个index.html文件,刷新浏览器就能看到变化。即使删除容器,主机上的文件依然存在,重新挂载即可。
这个阶段的目标是:理解docker pull/run/ps/logs/exec/stop/rm这一套基础命令链,明白镜像(只读模板)和容器(运行时实例)的区别,并初步接触端口映射 (-p) 和数据持久化 (-v) 这两个核心概念。这是后续理解 K8S 中 Service 和 PersistentVolume 的基础。
3. 构建自定义镜像与编写 Dockerfile
只会用现成镜像不够,你需要知道如何把自己的应用打包成镜像。这就要用到 Dockerfile。
3.1 编写第一个 Dockerfile
假设你有一个简单的 Python Web 应用,文件结构如下:
my-python-app/ ├── app.py ├── requirements.txt └── Dockerfileapp.py内容:from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello from my custom Docker image!" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)requirements.txt内容:flask==2.3.3Dockerfile内容:# 第一阶段:使用官方 Python 轻量级镜像作为基础 FROM python:3.11-slim # 设置工作目录,后续命令都在此目录下执行 WORKDIR /app # 将依赖文件复制到工作目录 COPY requirements.txt . # 安装 Python 依赖,使用清华镜像源加速(国内环境) RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt # 将当前目录所有文件复制到工作目录 COPY . . # 声明容器运行时监听的端口 EXPOSE 5000 # 定义容器启动时执行的命令 CMD ["python", "app.py"]
3.2 构建镜像并运行
在my-python-app目录下执行:
docker build -t my-python-app:1.0 .-t my-python-app:1.0: 为镜像打上标签(名称:版本)。.: 构建上下文路径,Docker 会把当前目录下的文件发送给 Docker 守护进程。
构建成功后,运行容器:
docker run -d --name my-app -p 5000:5000 my-python-app:1.0访问http://localhost:5000,你应该能看到自定义的问候语。
3.3 Dockerfile 关键指令与最佳实践
FROM: 必须且是第一条指令。选择合适的基础镜像(如alpine,slim版本可以减小镜像体积)。WORKDIR: 设置工作目录,代替RUN cd ... && ...这种复杂命令。COPYvsADD: 优先使用COPY,它更透明。ADD有自动解压等额外功能,但行为不够清晰。RUN: 执行命令并创建新的镜像层。合并多个RUN指令可以减少镜像层数,例如RUN apt-get update && apt-get install -y package1 package2 && rm -rf /var/lib/apt/lists/*。EXPOSE: 声明端口,是一种文档形式。实际映射端口仍需在docker run时用-p指定。CMD: 指定容器启动时的默认命令。一个 Dockerfile 只能有一个CMD。通常格式是CMD ["executable", "param1", "param2"](exec 格式)。
这个阶段的目标是:能将自己的简单应用通过 Dockerfile 打包成镜像,理解镜像分层构建的概念,并掌握编写高效 Dockerfile 的几个基本原则。这是实现 CI/CD 和部署到 K8S 的前提。
4. 从单机 Docker 到 Kubernetes 初体验
理解了 Docker 之后,K8S 就不再是空中楼阁。它要解决的核心问题是:当你有成百上千个容器需要跨多台机器部署、管理、扩缩容和保持高可用时,该怎么办?
4.1 选择本地 K8S 环境:Minikube 还是 K3s?
对于学习和开发,不建议直接在生产 K8S 集群上操作。本地轻量级方案是首选。
- Minikube: 官方维护的单节点 K8S 工具。它在你的机器上创建一个虚拟机,并在里面运行一个单节点的 K8S 集群。功能完整,最适合学习核心概念。
- K3s: Rancher 发布的轻量级 K8S,易于安装,资源占用更少,甚至可以在树莓派上运行。它更适合边缘计算或资源受限的环境。
对于初学者,我推荐Minikube,因为它最贴近标准 K8S 的体验,且文档和社区支持最好。
4.2 安装并启动 Minikube
在已经安装好 Docker 的 Linux 虚拟机或 macOS/Windows 上,安装 Minikube。
安装 Minikube 二进制文件(以 Linux 为例):
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube启动 Minikube 集群:
minikube start --driver=docker--driver=docker: 指定使用 Docker 作为底层容器运行时。Minikube 会在 Docker 内部再启动一个运行 K8S 组件的容器。 首次启动会下载基础镜像,需要一些时间。成功后,你会看到类似Done! kubectl is now configured to use "minikube" cluster的提示。
配置 kubectl:
kubectl是管理 K8S 集群的命令行工具。Minikube 会自动为你配置好。验证一下:kubectl cluster-info kubectl get nodes你应该能看到一个名为
minikube的节点,状态为Ready。
4.3 部署第一个应用:理解 Pod 和 Deployment
在 K8S 中,最小的部署单元不是容器,而是Pod。一个 Pod 可以包含一个或多个紧密关联的容器。但通常我们不会直接创建 Pod,而是通过Deployment来管理 Pod 的副本和生命周期。
创建一个 Deployment 配置文件
my-nginx-deployment.yaml:apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 2 # 指定 Pod 副本数为 2 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.24 ports: - containerPort: 80应用这个配置:
kubectl apply -f my-nginx-deployment.yaml查看部署状态:
kubectl get deployments kubectl get pods你会看到
nginx-deployment创建了 2 个 Pod。kubectl get pods的输出中,READY列显示1/1,STATUS为Running时,表示 Pod 已就绪。暴露服务:创建 Service。 Pod 的 IP 是临时的,且外部无法直接访问。需要通过Service来提供稳定的访问入口。 创建
my-nginx-service.yaml:apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx # 这个选择器必须匹配 Deployment 中 Pod 的标签 ports: - protocol: TCP port: 80 # Service 对外暴露的端口 targetPort: 80 # 容器内监听的端口 type: NodePort # 类型为 NodePort,会在集群每个节点上开放一个端口(范围 30000-32767)应用配置:
kubectl apply -f my-nginx-service.yaml。访问应用: 获取 Service 的 NodePort:
kubectl get service nginx-service在输出中找到
PORT(S)列,例如80:30678/TCP,其中30678就是 NodePort。 由于我们使用 Minikube,可以通过以下命令快速获取访问 URL:minikube service nginx-service --url它会返回一个类似
http://192.168.49.2:30678的地址,在浏览器中打开即可访问 Nginx。
这个阶段的目标是:在本地成功启动一个 K8S 集群(Minikube),使用kubectl命令与集群交互,并通过 YAML 文件定义并部署一个最简单的多副本应用(Deployment),最后通过 Service 将其暴露给外部访问。理解Deployment -> Pod -> Container的层次关系,以及Service通过标签选择器 (selector) 关联 Pod 的机制,是 K8S 入门的核心。
5. 深入 K8S 核心概念与日常操作
掌握了基本部署流程后,需要深入理解几个关键对象和它们的日常操作。
5.1 核心对象关系图(概念层面)
Deployment (定义Pod模板和副本数) | v Pod (一个或多个容器) <--- 被 Service 通过 Label Selector 选中 | v Container(s) (运行你的应用)- ConfigMap & Secret: 用于将配置信息和敏感数据(如密码)与容器镜像解耦,以环境变量或文件卷的形式注入到 Pod 中。
- PersistentVolume (PV) & PersistentVolumeClaim (PVC): 用于管理持久化存储。PVC 是 Pod 对存储的“申请”,PV 是集群中的存储资源。管理员创建 PV,用户通过 PVC 消费。
- Namespace: 用于在同一个物理集群中创建多个虚拟集群,实现资源隔离。
kube-system、default都是内置的命名空间。
5.2 常用 kubectl 命令与故障排查
kubectl是你与集群交互的主要工具。除了get和apply,以下命令至关重要:
查看详细信息:
kubectl describe pod <pod-name> # 查看 Pod 的详细状态、事件、配置 kubectl describe deployment <deployment-name> kubectl describe service <service-name>describe命令是排查 Pod 为什么处于Pending、CrashLoopBackOff等异常状态的第一选择。它会显示调度失败、镜像拉取失败、健康检查失败等具体原因。查看日志:
kubectl logs <pod-name> # 查看 Pod 内容器的标准输出日志 kubectl logs -f <pod-name> # 持续跟踪日志(类似 tail -f) kubectl logs <pod-name> -c <container-name> # 如果 Pod 有多个容器,指定容器名进入 Pod 内的容器:
kubectl exec -it <pod-name> -- /bin/bash类似于
docker exec,用于调试容器内部。删除资源:
kubectl delete -f my-nginx-deployment.yaml # 通过文件删除 kubectl delete deployment nginx-deployment # 通过资源类型和名称删除 kubectl delete pod <pod-name>排查 Pod 启动失败的常见原因:
- ImagePullBackOff: 镜像拉取失败。检查镜像名称、标签是否正确,网络是否通畅,是否有拉取私有镜像的凭证 (
imagePullSecrets)。 - CrashLoopBackOff: 容器启动后立即退出。检查应用本身是否有错误,查看
kubectl logs。 - Pending: Pod 无法被调度到节点上。检查节点资源是否充足(CPU、内存),是否有节点选择器 (
nodeSelector) 限制,或是否存在污点 (Taint)。 - ErrImagePull: 同 ImagePullBackOff。
- ImagePullBackOff: 镜像拉取失败。检查镜像名称、标签是否正确,网络是否通畅,是否有拉取私有镜像的凭证 (
5.3 应用更新、回滚与扩缩容
更新镜像版本(滚动更新):
kubectl set image deployment/nginx-deployment nginx=nginx:1.25K8S 的 Deployment 默认采用滚动更新策略,会逐步用新 Pod 替换旧 Pod,确保服务不中断。可以通过
kubectl rollout status deployment/nginx-deployment观察更新状态。回滚到上一版本:
kubectl rollout undo deployment/nginx-deployment查看更新历史:
kubectl rollout history deployment/nginx-deployment手动扩缩容:
kubectl scale deployment nginx-deployment --replicas=5
这个阶段的目标是:熟练使用kubectl describe和kubectl logs进行故障排查,理解 Pod 常见状态的含义,并掌握应用更新、回滚和扩缩容的基本操作。这已经覆盖了日常运维的大部分场景。
6. 向生产环境迈进:配置、存储与健康检查
要让应用在 K8S 上更健壮,需要关注配置管理、数据持久化和应用健康状态监控。
6.1 使用 ConfigMap 管理配置
将配置与镜像分离。例如,为 Nginx 创建一个自定义主页。
创建 ConfigMap:
kubectl create configmap nginx-index-html --from-file=index.html=./my-index.html假设
my-index.html文件内容为<h1>Hello from ConfigMap!</h1>。在 Deployment 中挂载 ConfigMap: 修改
my-nginx-deployment.yaml,在 Pod 模板的spec.containers下添加volumeMounts,并在spec下添加volumes:spec: containers: - name: nginx image: nginx:1.24 ports: - containerPort: 80 volumeMounts: - name: html-volume mountPath: /usr/share/nginx/html # 挂载到容器内的路径 volumes: - name: html-volume configMap: name: nginx-index-html # 引用刚才创建的 ConfigMap items: - key: index.html path: index.html应用更新后,访问 Nginx,主页内容将变为 ConfigMap 中定义的内容。
6.2 使用 PersistentVolumeClaim 挂载持久化存储
在 Minikube 中,可以方便地使用hostPath类型的 PV,但在生产环境通常会使用网络存储(如 NFS、Ceph、云盘)。
创建 PVC
my-pvc.yaml:apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-data-pvc spec: accessModes: - ReadWriteOnce # 访问模式:单节点读写 resources: requests: storage: 1Gi # 请求 1Gi 存储空间在 Deployment 中使用 PVC: 在 Pod 模板的
spec.containers中添加volumeMounts,并在spec下添加volumes,引用 PVC:spec: containers: - name: nginx ... volumeMounts: - name:>containers: - name: nginx image: nginx:1.24 livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 # 容器启动后等待 5 秒开始探测 periodSeconds: 10 # 每 10 秒探测一次 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 5这个阶段的目标是:了解如何将应用配置外置(ConfigMap),如何为有状态应用提供持久化存储(PVC),以及如何通过健康检查让 K8S 更好地管理你的应用生命周期。这是将简单部署转化为可运维、高可用服务的关键步骤。
7. 学习路径建议与常见避坑点
最后,结合我自己的经验,给几条学习和实践的建议。
7.1 学习路径规划
- 第一阶段(1-2周):夯实 Docker 基础。做到能熟练构建自定义镜像,理解 Dockerfile 每一行指令的作用,掌握容器网络(
--network)和数据卷(-v)的基本用法。 - 第二阶段(2-3周):上手 Minikube 和 kubectl。反复练习 Deployment、Service、Pod、ConfigMap、PVC 这几个核心对象的 YAML 编写和命令操作。在本地部署一个多副本的 Web 应用(如 WordPress + MySQL),并配置 Service 访问。
- 第三阶段(1-2个月):深入学习核心概念。理解 K8S 的架构(Master/Node)、调度原理、网络模型(CNI)、服务发现(CoreDNS)、Ingress 控制器。可以尝试在云服务器上使用
kubeadm手动搭建一个多节点集群,这个过程能极大加深理解。 - 第四阶段(长期):关注生态工具。学习 Helm(包管理)、Prometheus(监控)、Grafana(可视化)、EFK/ELK(日志)、GitOps(ArgoCD/Flux)等,这些是构建完整云原生技术栈的组成部分。
7.2 实践中的常见坑点
- 镜像拉取失败:确保镜像名称和标签正确。对于私有仓库,需要在 Deployment 中配置
imagePullSecrets。国内环境可能需要对 Docker Hub 配置镜像加速器。 - Pod 一直 Pending:运行
kubectl describe pod <pod-name>,查看Events部分。常见原因是节点资源不足(CPU、内存),或 PVC 无法绑定(没有可用的 PV)。 - Service 无法访问:
- 检查 Service 的
selector是否与 Pod 的labels完全匹配。 - 检查 Pod 的
containerPort是否与 Service 的targetPort一致。 - 对于
NodePort类型,检查防火墙是否放行了节点的对应端口(30000-32767)。 - 在集群内,可以通过
kubectl run -it --rm --image=busybox test-pod -- sh启动一个临时 Pod,用wget -O- <service-name>.<namespace>.svc.cluster.local:port测试服务发现。
- 检查 Service 的
- 配置文件格式错误:YAML 对缩进极其敏感,务必使用空格而非 Tab。可以使用在线 YAML 校验工具或
kubectl apply --dry-run=client -f your-file.yaml进行预检查。 - 忘记清理资源:学习过程中会创建大量临时资源。定期使用
kubectl get all --all-namespaces查看,并使用kubectl delete清理不再需要的 Deployment、Service、Pod、PVC 等,避免资源浪费。
我个人更建议把“速通”理解为快速建立核心概念和最小可运行环境,而不是追求一次性掌握所有高级特性。真正的熟练来自于反复的实践和踩坑。先从在 Minikube 上稳定运行一个你自己打包的应用开始,然后逐步加入配置、存储、健康检查,再尝试搭建多节点集群。每一步都确保自己理解了背后的原理和命令的作用,这样积累的经验才是扎实的。
🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度
- 第一阶段(1-2周):夯实 Docker 基础。做到能熟练构建自定义镜像,理解 Dockerfile 每一行指令的作用,掌握容器网络(
