从Docker到Kubernetes:容器化与编排实战入门指南
🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度
在实际的云计算和容器化部署场景中,Docker 和 Kubernetes 已经成为构建、交付和运行现代应用的标准技术栈。对于希望从零开始掌握 Linux 云计算运维核心技术的开发者或运维工程师而言,理解从容器化到容器编排的完整链路,是提升工程效率和系统稳定性的关键。本文旨在提供一个结构化的学习路径和实战指南,帮助你从基础概念入手,逐步搭建环境、运行容器、部署集群,最终理解生产环境中常见的配置、排错和优化实践。无论你是刚接触容器技术的新手,还是希望系统化巩固知识的实践者,都可以跟随本文的步骤,构建一个可运行、可验证的本地实验环境。
1. 理解 Docker 与 Kubernetes 的核心价值与关系
在深入命令行操作之前,必须先厘清 Docker 和 Kubernetes 各自解决的问题以及它们如何协同工作。这有助于避免后续学习中将两者概念混淆,或在错误场景下使用错误工具。
1.1 Docker:标准化应用交付的基石
Docker 的核心是容器化技术。它通过镜像(Image)和容器(Container)的概念,解决了“在我的机器上能运行,在你的机器上不能运行”这一经典难题。
- 镜像:一个只读的模板,包含了运行应用所需的代码、运行时、系统工具、库和设置。你可以把它理解为一个轻量级、可移植的软件包。
- 容器:镜像的运行实例。它是一个隔离的进程,拥有自己的文件系统、网络和进程空间,但共享宿主机的内核。
Docker 的价值在于将应用及其所有依赖打包成一个标准单元,实现了开发、测试、生产环境的一致性。例如,一个基于 Spring Boot 的 Java 应用,在 Docker 化后,无论是在 Ubuntu 还是 CentOS 的宿主机上,都能以完全相同的方式启动和运行。
1.2 Kubernetes:自动化容器编排的大脑
当你的应用从单个容器扩展到由数十、数百个容器组成的微服务集群时,手动管理这些容器的生命周期、网络、存储和伸缩就变得不可能。Kubernetes 应运而生,它是一个开源的容器编排平台。
- 编排:意味着自动化容器的部署、管理、扩展和网络互联。Kubernetes 负责调度容器到集群中的节点上,并确保它们按照用户声明的期望状态运行。
- 核心概念:包括 Pod(Kubernetes 的最小调度单元,通常包含一个或多个紧密关联的容器)、Service(为 Pod 提供稳定的网络访问端点)、Deployment(声明 Pod 的副本数和更新策略)等。
简单来说,Docker 负责“造砖”(创建容器),而 Kubernetes 负责“盖房子”(用这些砖搭建和管理复杂的应用架构)。两者是互补关系,而非替代关系。
1.3 典型技术栈演进路径
一个典型的技术演进路径是:开发者先在本地使用 Docker 构建和测试单个服务镜像。当服务需要上线时,通过 Kubernetes 的配置文件(如 YAML)定义这个服务应该如何被部署和暴露。Kubernetes 集群则会拉取 Docker 镜像,创建 Pod,并管理其整个生命周期。理解这个协作流程,是后续所有实践的基础。
2. 环境准备:搭建本地实验环境
为了进行安全、可反复的实验,我们将在本地计算机上搭建一个最小化的实验环境。生产环境的 Kubernetes 集群通常由多台物理机或云服务器组成,但本地环境足以让我们学习核心概念和操作。
2.1 系统与工具要求
建议使用 Linux 或 macOS 系统进行学习,其命令行环境与生产服务器更为接近。Windows 用户可以使用 WSL2。以下是所需的核心工具及其作用:
| 工具 | 作用 | 备注 |
|---|---|---|
| Docker Desktop或Docker Engine | 提供 Docker 守护进程和客户端,用于构建和运行容器。 | Docker Desktop 集成了 Kubernetes,是快速搭建本地集群的便捷选择。 |
| kubectl | Kubernetes 命令行工具,用于与集群交互。 | 这是操作 Kubernetes 的“遥控器”,必须安装。 |
| Minikube或Kind | 用于在本地快速创建单节点 Kubernetes 集群的工具。 | 生产集群复杂,本地学习首选这些轻量级工具。 |
| 代码编辑器(如 VSCode) | 用于编写 Dockerfile 和 Kubernetes YAML 配置文件。 | 推荐安装 Kubernetes 和 YAML 语法高亮插件。 |
注意:不同工具的版本兼容性非常重要。建议在安装时,查阅官方文档,选择经过验证的稳定版本组合,以避免因版本冲突导致无法预料的问题。
2.2 安装与验证 Docker
我们以 Ubuntu 22.04 为例,演示 Docker Engine 的安装。其他系统请参考 Docker 官方文档。
卸载旧版本(如有):
sudo apt-get remove docker docker-engine docker.io containerd runc设置仓库并安装:
# 更新 apt 包索引并安装依赖 sudo apt-get update sudo apt-get install ca-certificates curl gnupg lsb-release # 添加 Docker 官方 GPG 密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 设置稳定版仓库 echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 安装 Docker Engine sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin验证安装:
# 启动 Docker 服务 sudo systemctl start docker sudo systemctl enable docker # 运行 hello-world 镜像测试 sudo docker run hello-world如果看到 “Hello from Docker!” 等欢迎信息,说明 Docker 已正确安装并可以运行容器。
(可选)免 sudo 运行 Docker(为方便实验):
sudo usermod -aG docker $USER执行此命令后,需要退出当前终端并重新登录才能生效。
2.3 安装 kubectl 和 Minikube
安装 kubectl:
# 下载最新稳定版 curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" # 安装到系统路径 sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl # 验证版本 kubectl version --client --output=yaml安装 Minikube:
# 下载并安装 curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube # 启动集群(这里使用 Docker 驱动,要求已安装 Docker) minikube start --driver=docker # 检查集群状态 minikube status kubectl cluster-info kubectl get nodes如果
kubectl get nodes显示一个状态为Ready的节点,说明你的本地单节点 Kubernetes 集群已经就绪。
至此,你已经拥有了一个完整的本地实验环境:Docker 用于构建容器,Minikube 提供了一个 Kubernetes 集群,kubectl 用于操控这个集群。
3. Docker 实战:从镜像构建到容器运行
我们将通过一个简单的 Web 应用,完成 Docker 的核心工作流:编写 Dockerfile -> 构建镜像 -> 运行容器 -> 验证服务。
3.1 创建示例应用
首先,创建一个项目目录并编写一个最简单的 Python Flask 应用。
mkdir docker-k8s-demo && cd docker-k8s-demo创建app.py文件:
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello, Docker & Kubernetes!' if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)创建requirements.txt文件,声明依赖:
Flask==2.3.23.2 编写 Dockerfile
Dockerfile 是构建镜像的蓝图。在项目根目录创建Dockerfile(无后缀):
# 第一阶段:使用官方 Python 轻量级镜像作为构建环境 FROM python:3.9-slim as builder WORKDIR /app # 复制依赖文件并安装 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 第二阶段:创建最终运行镜像 FROM python:3.9-slim WORKDIR /app # 从构建阶段复制已安装的 Python 依赖 COPY --from=builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages COPY --from=builder /usr/local/bin /usr/local/bin # 复制应用代码 COPY app.py . # 声明容器运行时暴露的端口 EXPOSE 5000 # 定义容器启动时执行的命令 CMD ["python", "app.py"]这个 Dockerfile 采用了多阶段构建,这能有效减小最终镜像的体积,因为它只包含运行应用所必需的依赖,而不包含构建过程中的中间文件和工具。
3.3 构建镜像并运行容器
构建镜像:
# -t 参数为镜像打标签,格式通常为 `仓库名/镜像名:标签` docker build -t my-web-app:1.0 .构建成功后,使用
docker images命令可以看到名为my-web-app,标签为1.0的镜像。运行容器:
# -d 后台运行,-p 将宿主机的 8080 端口映射到容器的 5000 端口 docker run -d -p 8080:5000 --name web-container my-web-app:1.0验证服务:
- 打开浏览器,访问
http://localhost:8080,应该看到 “Hello, Docker & Kubernetes!”。 - 查看容器日志:
docker logs web-container。 - 查看运行中的容器:
docker ps。 - 进入容器内部(用于调试):
docker exec -it web-container /bin/bash。
- 打开浏览器,访问
3.4 Docker 常用命令与核心操作
掌握以下命令是日常工作的基础:
| 操作类别 | 命令示例 | 说明 |
|---|---|---|
| 镜像管理 | docker images | 列出本地镜像 |
docker rmi <image_id> | 删除本地镜像 | |
docker pull nginx:latest | 从仓库拉取镜像 | |
| 容器生命周期 | docker ps -a | 列出所有容器(包括已停止的) |
docker stop <container_id> | 停止运行中的容器 | |
docker start <container_id> | 启动已停止的容器 | |
docker rm <container_id> | 删除容器 | |
| 容器交互 | docker logs -f <container_id> | 查看并跟随容器日志 |
docker exec -it <container_id> /bin/sh | 进入容器终端 | |
docker cp <container_id>:/path/to/file . | 从容器复制文件到宿主机 |
4. Kubernetes 实战:部署应用到集群
现在,我们将上面构建的my-web-app镜像部署到 Minikube 创建的 Kubernetes 集群中。Kubernetes 通过 YAML 文件来声明期望的应用状态。
4.1 准备镜像
Minikube 集群默认使用其内部的 Docker 守护进程。为了使用我们本地构建的镜像,有两种方式:
- 使用 Minikube 的 Docker 环境重新构建(推荐用于实验):
# 将当前 shell 切换到 Minikube 的 Docker 环境 eval $(minikube docker-env) # 此时再执行 docker build,镜像将直接构建在 Minikube 内部 docker build -t my-web-app:1.0 . # 完成后,可以切换回本地环境 eval $(minikube docker-env -u) - 将镜像推送到公共或私有镜像仓库(如 Docker Hub),然后在 Kubernetes 配置中指定仓库地址。这是生产环境的标准做法。
4.2 编写 Kubernetes 部署文件
创建deployment.yaml文件,定义一个 Deployment 和一个 Service。
# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: web-app-deployment spec: replicas: 2 # 指定 Pod 副本数为 2,实现高可用 selector: matchLabels: app: web-app template: metadata: labels: app: web-app spec: containers: - name: web-app-container image: my-web-app:1.0 # 使用我们构建的镜像 imagePullPolicy: Never # 告诉 K8s 从本地拉取镜像,而不是去仓库 ports: - containerPort: 5000 --- apiVersion: v1 kind: Service metadata: name: web-app-service spec: selector: app: web-app # 选择器,匹配 Deployment 中 Pod 的标签 ports: - protocol: TCP port: 80 # Service 对集群内暴露的端口 targetPort: 5000 # 转发到 Pod 容器的端口 type: NodePort # 类型为 NodePort,会在每个节点上开放一个端口(30000-32767)供外部访问这个文件定义了两部分资源:
- Deployment:声明需要运行 2 个 Pod 副本,每个 Pod 里运行一个
my-web-app:1.0的容器。 - Service:为这些 Pod 提供一个统一的访问入口。
NodePort类型使得我们可以通过集群任意节点的 IP 和分配的端口来访问服务。
4.3 部署应用到集群并验证
应用配置:
kubectl apply -f deployment.yaml这条命令会告知 Kubernetes 集群,使其实际状态符合 YAML 文件中声明的期望状态。
查看资源状态:
# 查看 Deployment 状态 kubectl get deployments # 查看 Pod 状态,应看到两个 Running 的 Pod kubectl get pods # 查看 Service 状态,并获取 NodePort kubectl get svc在
kubectl get svc的输出中,web-app-service的PORT(S)列会显示类似80:3xxxx/TCP的信息,其中3xxxx就是分配的 NodePort。访问应用:
# 获取 Minikube 节点的 IP 地址 minikube ip # 假设 minikube ip 输出 192.168.49.2,Service NodePort 是 30080 # 则在浏览器访问:http://192.168.49.2:30080你应该能看到和 Docker 运行时一样的 “Hello, Docker & Kubernetes!” 信息。
模拟故障与自愈: Kubernetes 的核心能力之一是自愈。我们可以手动删除一个 Pod 来观察:
# 获取一个 Pod 的名称 kubectl get pods # 删除该 Pod kubectl delete pod <pod-name> # 立即再次查看 Pod kubectl get pods -w # -w 参数用于持续观察你会看到被删除的 Pod 状态变为
Terminating,随后 Kubernetes 的控制器(Deployment)会立刻创建一个新的 Pod 来满足replicas: 2的声明,最终恢复两个 Running 的 Pod。
4.4 kubectl 核心命令速查
| 操作类别 | 命令示例 | 说明 |
|---|---|---|
| 基础查询 | kubectl get pods | 查看 Pod |
kubectl get svc | 查看 Service | |
kubectl get deployments | 查看 Deployment | |
kubectl describe pod <pod-name> | 查看 Pod 详细信息(事件、状态等) | |
| 应用管理 | kubectl apply -f <file.yaml> | 创建或更新资源 |
kubectl delete -f <file.yaml> | 删除资源 | |
kubectl scale deployment/<name> --replicas=3 | 伸缩 Pod 副本数 | |
| 交互与调试 | kubectl logs <pod-name> | 查看 Pod 日志 |
kubectl exec -it <pod-name> -- /bin/sh | 进入 Pod 容器 | |
kubectl port-forward svc/<svc-name> 8080:80 | 将本地端口转发到 Service,方便本地调试 |
5. 生产环境考量与常见问题排查
将应用从本地实验环境迁移到生产环境,需要考虑更多因素。以下是关键实践和常见问题的排查思路。
5.1 镜像管理与安全
- 使用特定版本标签:永远不要在生产环境使用
latest标签。应使用语义化版本或构建编号,如my-app:v1.2.3或my-app:git-abc123。 - 镜像仓库:使用私有镜像仓库(如 Harbor, AWS ECR, Google Container Registry)存储生产镜像,并配置镜像拉取密钥。
- 镜像安全扫描:集成安全扫描工具(如 Trivy, Clair)到 CI/CD 流水线,在构建和部署前检查镜像漏洞。
- 非 root 用户运行:在 Dockerfile 中创建并使用非 root 用户运行应用,以遵循最小权限原则。
FROM python:3.9-slim RUN groupadd -r appuser && useradd -r -g appuser appuser USER appuser # ... 后续 COPY 和 CMD
5.2 Kubernetes 配置优化
- 资源请求与限制:为 Pod 中的容器定义资源请求和限制,防止单个应用耗尽节点资源。
resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" - 就绪和存活探针:配置健康检查,让 Kubernetes 能感知应用内部状态。
livenessProbe: httpGet: path: /health port: 5000 initialDelaySeconds: 3 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 5000 initialDelaySeconds: 5 periodSeconds: 5 - 配置分离:使用 ConfigMap 和 Secret 管理配置信息和敏感数据,而不是硬编码在镜像或 YAML 中。
5.3 常见问题排查路径
当部署出现问题时,遵循从外到内、从宏观到微观的排查顺序。
| 问题现象 | 排查步骤与命令 | 可能原因与解决方案 |
|---|---|---|
| Pod 状态不是 Running | 1.kubectl get pods查看状态(Pending, CrashLoopBackOff, ImagePullBackOff)。2. kubectl describe pod <pod-name>查看 Events 部分。3. kubectl logs <pod-name>查看容器日志。 | ImagePullBackOff:镜像拉取失败,检查镜像名、标签、仓库权限。 CrashLoopBackOff:容器启动后立即退出,检查应用启动逻辑、依赖、命令。 Pending:资源不足或节点选择问题,检查节点资源、污点容忍。 |
| Service 无法访问 | 1.kubectl get svc确认 Service 类型和端口。2. kubectl get endpoints <svc-name>检查 Endpoints 是否关联了 Pod IP。3. kubectl exec进入 Pod 内,尝试curl localhost:<containerPort>检查应用本身。 | Endpoints 为空:Service 的selector与 Pod 的labels不匹配。应用内部错误:Pod 内应用未在指定端口监听或报错,检查 Pod 日志。 |
| 应用性能差或频繁重启 | 1.kubectl describe pod查看是否被 OOMKilled。2. kubectl top pod查看资源使用情况。3. 检查应用日志和监控指标。 | 资源不足:未设置资源限制或限制过小,调整resources.limits。探针配置不当:存活探针过于敏感或路径错误,调整探针参数和端点。 |
| 配置变更未生效 | 1. 确认 YAML 文件已正确kubectl apply。2. kubectl rollout status deployment/<name>查看滚动更新状态。3. kubectl get pods查看新 Pod 是否已创建。 | 镜像未更新:Deployment 使用的镜像标签未改变,K8s 认为无需更新。更改标签或使用kubectl rollout restart deployment。更新策略:检查 strategy配置,可能是分批更新导致观察延迟。 |
5.4 日志与监控
生产环境必须建立可观测性体系。
- 集中式日志:部署 EFK(Elasticsearch, Fluentd, Kibana)或 Loki 栈,收集所有容器和节点的日志。
- 监控与告警:部署 Prometheus 收集指标(CPU、内存、网络、自定义业务指标),使用 Grafana 可视化,并配置 Alertmanager 进行告警。
- 使用
kubectl调试:掌握kubectl logs,kubectl describe,kubectl exec是在问题初期进行快速诊断的必备技能。
从 Docker 镜像构建到 Kubernetes 集群部署,这条链路是现代应用运维的基石。本地实验环境让你可以安全地练习所有核心操作,但务必记住,生产环境的复杂性远不止于此,它涉及网络策略、存储编排、安全上下文、多集群管理等多个维度。建议在掌握本文基础后,进一步深入学习 Ingress 控制器、持久卷、Helm 包管理、Operator 模式以及服务网格等进阶主题。真正的精通源于在稳定可控的实验环境中反复练习,并对生产部署中每一个配置项背后的设计意图保持追问。
🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Claude 随心用,限时 5 折。 👉 点击领海量免费额度