2026云原生实战:Docker+K8S+Jenkins构建完整CI/CD流水线
这次我们来看一套面向2026年的容器化与云原生实战教程。这套内容不是零散的知识点堆砌,而是将 Docker、Kubernetes (K8S)、Jenkins 和 Linux 运维串联成一个完整的 CI/CD 实战项目。对于刚接触容器技术、想从零搭建一套自动化部署流水线的开发者或运维人员来说,这套教程的核心价值在于“学完就能用”——它清晰地展示了如何从单机 Docker 环境,一步步构建出具备自动构建、测试、部署能力的 K8S 集群。
如果你关心的是:如何在 Windows/macOS/Linux 上快速安装 Docker Desktop、如何编写高效的 Dockerfile、如何搭建一个最小可用的 K8S 集群(即使是单节点学习环境)、如何配置 Jenkins 实现代码提交即自动部署,以及如何解决过程中最常见的网络、存储、镜像拉取问题,那么这篇文章可以直接收藏。我们将避开庞杂的理论,聚焦于可执行的操作、可验证的结果和可复现的排错步骤。
1. 核心能力速览
本教程涵盖的技术栈和关键实践点如下表所示,这不仅是学习路径,也是一个最小可用的云原生交付流水线清单。
| 能力项 | 说明与目标 |
|---|---|
| 技术栈覆盖 | Docker 容器化 -> Kubernetes 编排 -> Jenkins 自动化 -> Linux 基础运维 |
| 学习门槛 | 面向零基础或有一定 Linux 命令基础的开发者,无需预先精通所有组件。 |
| 环境要求 | 支持 Windows 10/11 (WSL2)、macOS 及主流 Linux 发行版。内存建议 8GB+,CPU 支持虚拟化。 |
| 核心产出 | 1. 一个可运行的 Docker 环境。 2. 一个单节点或多节点 K8S 集群。 3. 一套 Jenkins CI/CD 流水线,能自动构建 Docker 镜像并部署到 K8S。 |
| 关键技能点 | Dockerfile 编写、Docker Compose、K8S Pod/Deployment/Service 配置、Jenkins Pipeline (Declarative), Helm Chart 基础。 |
| 排错重点 | 镜像拉取失败、网络策略冲突、持久化存储配置、Jenkins 插件依赖、K8S 资源权限。 |
2. 适用场景与使用边界
这套教程和实战项目主要适合以下几类读者:
- 转型 DevOps 的传统开发/运维人员:需要快速掌握容器化和自动化部署的核心技能链。
- 计算机相关专业的学生:希望通过一个完整的项目理解云原生技术的实际工作流,丰富简历项目经验。
- 中小团队技术负责人:计划引入容器化和自动化部署,需要一套经过验证的、可落地的入门方案进行技术预研。
- 个人项目开发者:希望为自己的应用搭建一套专业的、可扩展的部署环境。
需要明确的使用边界:
- 学习与预研环境:教程中搭建的 K8S 集群(如使用 Minikube、K3s 或单 Master 集群)适用于开发、测试和学习,不能直接等同于生产级的高可用集群。生产环境需要考虑多 Master、etcd 集群、网络插件选型、监控日志体系等。
- 资源消耗:在本地同时运行 Docker、K8S 集群和 Jenkins,对电脑内存和 CPU 有一定要求。如果资源紧张,建议按模块分步实践,或使用云服务器进行。
- 安全边界:教程以保证功能跑通为首要目标,涉及的网络策略、镜像仓库认证、K8S RBAC 权限控制等安全最佳实践仅作引导性介绍。在生产部署前,必须系统性地加强安全配置。
3. 环境准备与前置条件
在开始动手之前,请确保你的实验环境满足以下基本要求。这是后续所有步骤能够顺利进行的基础。
3.1 硬件与操作系统
- 操作系统:Windows 10/11 (版本 2004 及以上,需启用 WSL2)、macOS 10.15+ 或任意主流 Linux 发行版(如 Ubuntu 20.04/22.04 LTS, CentOS 7/8)。
- 内存:建议 8 GB 或以上。运行 K8S 单节点集群至少需要 2-3 GB 空闲内存,加上 Jenkins 和 Docker,8GB 是流畅体验的起点。
- CPU:现代双核以上处理器,并确保在 BIOS/UEFI 中已开启虚拟化技术(如 Intel VT-x 或 AMD-V)。这对于在 Windows/macOS 上运行 Docker Desktop 和 K8S 至关重要。
- 磁盘空间:至少预留 20 GB 可用空间,用于安装软件、拉取基础镜像和存储项目文件。
3.2 关键软件检查清单
在安装 Docker 之前,请先完成这些检查:
- Windows 用户:确认已安装并启用WSL 2。在 PowerShell(管理员)中运行
wsl --list --verbose查看。若未安装,请参考微软官方文档安装。 - 虚拟化检查:
- Windows:打开任务管理器 -> “性能”选项卡 -> “CPU”,查看“虚拟化”是否已启用。
- Linux/macOS:通常在终端运行
egrep -c ‘(vmx|svm)’ /proc/cpuinfo(Linux) 或sysctl -a | grep machdep.cpu.features(macOS),输出非0则支持。
- 网络准备:确保主机可以正常访问互联网,用于下载安装包和拉取 Docker 镜像。了解公司或家庭网络是否有特殊的代理或防火墙规则。
4. Docker 安装与基础实战
Docker 是整个技术栈的基石。我们采用最通用的安装方式,并立即通过一个实战项目来巩固。
4.1 Docker 安装(以 Ubuntu 22.04 为例)
以下脚本完成了仓库配置、依赖安装和 Docker Engine 的安装。
# 1. 卸载旧版本(如有) sudo apt-get remove docker docker-engine docker.io containerd runc # 2. 安装依赖包,允许 apt 通过 HTTPS 使用仓库 sudo apt-get update sudo apt-get install -y \ ca-certificates \ curl \ gnupg \ lsb-release # 3. 添加 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 # 4. 设置稳定版仓库 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 # 5. 安装 Docker Engine sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 6. 验证安装 sudo docker run hello-world如果看到 “Hello from Docker!” 的输出,说明安装成功。对于 Windows/macOS 用户,强烈建议直接下载并安装 Docker Desktop,它集成了 Docker Engine、CLI 和图形化管理界面,并内置了 K8S 支持选项。
4.2 第一个 Docker 实战:容器化一个 Python Web 应用
我们创建一个简单的 Flask 应用并将其容器化。
- 创建项目目录及文件:
mkdir my-flask-app && cd my-flask-app - 编写应用代码
app.py:from flask import Flask app = Flask(__name__) @app.route(‘/‘) def hello(): return ‘<h1>Hello, Docker & K8S!</h1><p>This is my first containerized app.</p>‘ if __name__ == ‘__main__‘: app.run(host=‘0.0.0.0‘, port=5000) - 编写依赖文件
requirements.txt:Flask==2.3.2 - 编写 Dockerfile:这是构建镜像的“食谱”。
# 使用官方 Python 轻量级镜像作为基础 FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 复制依赖文件 COPY requirements.txt . # 安装依赖,使用国内镜像源加速(可选) RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 复制应用代码 COPY . . # 声明容器运行时暴露的端口 EXPOSE 5000 # 定义容器启动命令 CMD [“python”, “app.py”] - 构建 Docker 镜像:
使用# -t 为镜像打标签,格式为 name:tag docker build -t my-flask-app:1.0 .docker images查看构建成功的镜像。 - 运行容器:
# -d 后台运行,-p 将主机8080端口映射到容器5000端口 docker run -d -p 8080:5000 --name my-flask-container my-flask-app:1.0 - 验证:打开浏览器访问
http://localhost:8080,应该能看到 Flask 应用的欢迎页面。使用docker ps查看运行中的容器,docker logs my-flask-container查看容器日志。
5. Kubernetes (K8S) 单机集群搭建与部署
在生产中,K8S 集群由多台机器组成。为了学习和开发,我们使用轻量级工具在单机上快速搭建一个集群。
5.1 使用 Minikube 搭建本地 K8S 集群
Minikube 是最流行的本地单节点 K8S 方案。
# 1. 安装 Minikube(Linux 示例) curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube # 2. 启动集群(需要提前安装好 Docker) minikube start --driver=docker # 3. 验证集群状态 minikube status kubectl get nodes # 如果 kubectl 未安装,minikube 会提示安装命令kubectl是操作 K8S 的命令行工具。Minikube 启动后,会自动配置kubectl的上下文。
5.2 将 Flask 应用部署到 K8S
现在,我们把之前容器化的 Flask 应用部署到 Minikube 集群中。
- 创建 Deployment:Deployment 管理 Pod(容器组)的副本和更新策略。
# flask-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: flask-app-deployment spec: replicas: 2 # 运行2个副本(Pod) selector: matchLabels: app: flask-app template: metadata: labels: app: flask-app spec: containers: - name: flask-app image: my-flask-app:1.0 # 使用本地构建的镜像 ports: - containerPort: 5000 resources: requests: memory: “64Mi” cpu: “250m” limits: memory: “128Mi” cpu: “500m” - 应用配置:
kubectl apply -f flask-deployment.yaml - 创建 Service:Service 为 Pod 提供一个稳定的网络访问入口。
# flask-service.yaml apiVersion: v1 kind: Service metadata: name: flask-app-service spec: selector: app: flask-app # 选择标签为 app: flask-app 的 Pod ports: - protocol: TCP port: 80 # Service 对外的端口 targetPort: 5000 # 容器内部的端口 type: NodePort # 类型为 NodePort,会在每个节点上开放一个端口(30000-32767)kubectl apply -f flask-service.yaml - 访问应用:
你应该能看到和之前 Docker 运行时一样的页面。通过# 获取 Service 的 NodePort 端口 kubectl get svc flask-app-service # 输出中会有一行类似:80:3xxxx/TCP,其中 3xxxx 就是节点端口 # 获取 Minikube 节点的 IP minikube ip # 在浏览器中访问:http://<minikube-ip>:<node-port>kubectl get pods可以看到两个 Pod 正在运行。
6. Jenkins 安装与 CI/CD 流水线配置
Jenkins 是整个自动化流程的“大脑”。我们将它安装在 Docker 中,并配置一个 Pipeline 任务,实现代码提交 -> 自动构建镜像 -> 更新 K8S 部署。
6.1 使用 Docker 运行 Jenkins
# 创建 Jenkins 数据卷,防止数据丢失 mkdir -p ~/jenkins_home chmod 777 ~/jenkins_home # 注意权限问题,生产环境需细化权限 # 运行 Jenkins 容器 docker run -d \ --name jenkins \ -p 8080:8080 \ -p 50000:50000 \ -v ~/jenkins_home:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v $(which docker):/usr/bin/docker \ jenkins/jenkins:lts-jdk17-v /var/run/docker.sock:/var/run/docker.sock:这是 Docker in Docker (DinD) 的一种简便方式,让 Jenkins 容器能使用宿主机的 Docker 引擎。- 访问
http://localhost:8080,根据提示从容器日志 (docker logs jenkins) 中获取初始管理员密码完成安装。
6.2 安装必要插件
首次登录后,在“系统管理” -> “插件管理” -> “可选插件”中,搜索并安装以下关键插件:
- Pipeline:支持声明式流水线。
- Docker Pipeline:在流水线中执行 Docker 命令。
- Kubernetes CLI:在流水线中执行
kubectl命令。 - Git:从 Git 仓库拉取代码。
6.3 配置 Jenkins 凭据与工具
- 配置 Docker Hub 凭据(如果你有公共/私有仓库):在“凭据” -> “系统” -> “全局凭据”中,添加用户名密码类型的凭据,用于推送镜像。
- 配置 kubeconfig:为了让 Jenkins 能访问 Minikube 集群,需要将宿主机的
~/.kube/config文件内容复制到 Jenkins 的一个“Secret file”类型凭据中,或在 Jenkins 容器内安装kubectl并配置。
6.4 创建第一个 Pipeline 任务
- 在 Jenkins 首页点击“新建任务”,输入任务名(如
flask-app-pipeline),选择“流水线”,点击确定。 - 在流水线配置页面的“Pipeline”区域,选择“Pipeline script”,并填入以下脚本:
pipeline { agent any // 使用任意可用的代理执行器 environment { // 定义环境变量 DOCKER_IMAGE = ‘your-dockerhub-username/my-flask-app:${BUILD_NUMBER}‘ KUBE_CONFIG = credentials(‘minikube-kubeconfig‘) // 引用凭据ID } stages { stage(‘Checkout‘) { steps { // 从 Git 仓库拉取代码(此处需替换为你的仓库地址) git ‘https://github.com/your-username/my-flask-app.git‘ } } stage(‘Build Docker Image‘) { steps { script { // 使用宿主机 Docker 构建镜像 docker.build(DOCKER_IMAGE) } } } stage(‘Push to Registry‘) { steps { script { // 登录 Docker Hub 并推送镜像(需配置凭据) docker.withRegistry(‘https://registry.hub.docker.com‘, ‘docker-hub-credential‘) { docker.image(DOCKER_IMAGE).push() } } } } stage(‘Deploy to K8S‘) { steps { script { // 将 kubeconfig 写入文件 writeFile file: ‘${WORKSPACE}/kubeconfig‘, text: KUBE_CONFIG // 使用 kubectl 设置上下文并更新部署的镜像 sh “““ kubectl --kubeconfig=${WORKSPACE}/kubeconfig set image deployment/flask-app-deployment flask-app=${DOCKER_IMAGE} --record ”““ } } } } post { always { // 清理工作空间 cleanWs() } } } - 点击保存。点击“立即构建”来触发流水线。在“阶段视图”中,你可以实时看到每个步骤的执行状态和日志。
7. 资源占用与性能观察
在本地运行这一整套环境,了解其资源消耗对于规划生产环境至关重要。
- Docker Daemon:作为后台服务,常驻内存约 200-500 MB,CPU 占用很低。
- Minikube 集群:启动一个单节点集群(包含 API Server、etcd、Scheduler 等核心组件),会占用约 2-3 GB 内存和 1-2 个 CPU 核心。使用
minikube dashboard命令打开仪表板可以直观查看资源使用情况。 - Jenkins 容器:Jenkins 本身(Java 应用)内存占用在 500 MB 到 1 GB 之间,具体取决于安装的插件数量和并发任务数。可以通过
docker stats jenkins命令监控。 - 应用 Pod:我们的 Flask 应用 Pod,每个副本请求 64Mi 内存,实际占用可能更低。使用
kubectl top pods命令查看实际资源使用。 - 磁盘空间:Docker 镜像和容器、K8S 的 etcd 数据、Jenkins 的工作空间和构建历史会持续占用磁盘。定期清理无用镜像 (
docker image prune) 和 Jenkins 旧构建记录是必要的。
性能优化小贴士:
- 限制资源:始终在 K8S 的 Deployment 中为容器设置
resources.requests和resources.limits,防止单个应用异常消耗所有资源。 - 使用轻量级基础镜像:如
python:3.9-slim比python:3.9体积小很多。Alpine Linux 镜像更小,但可能遇到兼容性问题。 - Jenkins 代理:对于大型项目,不要将所有构建任务都放在 Master 节点。可以配置 Kubernetes 插件,让 Jenkins 在 K8S 集群中动态创建 Pod 作为构建代理,任务完成后销毁,节省资源。
8. 常见问题与排查方法
在实践过程中,你几乎一定会遇到下面这些问题。这里提供快速的排查思路。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
docker run报错:端口被占用 | 主机端口已被其他进程使用。 | `netstat -tulpn | grep :8080(Linux) 或lsof -i :8080` (macOS)。 |
| Minikube 启动失败 | 1. 虚拟化未开启。 2. 驱动不匹配。 3. 网络问题。 | 1. 检查 BIOS 虚拟化设置。 2. 查看 minikube start --driver=docker的详细日志 (--alsologtostderr)。3. 检查防火墙或代理。 | 1. 开启 BIOS 虚拟化。 2. 尝试其他驱动,如 --driver=hyperkit(macOS)。3. 配置正确的 HTTP/HTTPS 代理。 |
kubectl get pods显示 ImagePullBackOff | 1. 镜像名称错误或不存在。 2. 私有仓库无权限。 | kubectl describe pod <pod-name>查看 Events 详情。 | 1. 检查 Deployment YAML 中的image字段。2. 为私有仓库创建 imagePullSecrets。 |
| Jenkins Pipeline 中 Docker 命令失败 | Jenkins 容器内无法访问 Docker 守护进程。 | 在 Pipeline 的sh步骤中运行docker version测试。 | 确保启动 Jenkins 容器时正确挂载了 Docker Socket (-v /var/run/docker.sock:/var/run/docker.sock)。 |
Jenkins 无法执行kubectl | kubectl未安装或kubeconfig配置错误。 | 在 Jenkins 的“脚本命令行”中尝试执行kubectl get nodes。 | 1. 在 Jenkins 容器内安装kubectl。2. 确保提供的 kubeconfig文件内容正确且上下文指向目标集群。 |
| Pipeline 推送镜像到 Docker Hub 失败 | 认证失败。 | 检查 Jenkins 中 Docker Hub 凭据的 ID 是否与 Pipeline 脚本中引用的docker-hub-credential一致。 | 在 Jenkins 凭据管理页面检查或重新配置凭据。 |
| 应用更新后,浏览器访问仍是旧版本 | 浏览器缓存或 K8S Service 负载均衡到旧 Pod。 | 1. 使用浏览器无痕模式访问。 2. kubectl get pods查看新 Pod 是否已就绪 (Running)。3. kubectl describe svc查看 Endpoints 是否指向新 Pod IP。 | 1. 清理浏览器缓存。 2. 等待 K8S 滚动更新完成。 Deployment 的 strategy可控制更新速度。 |
9. 最佳实践与进阶方向
当你成功跑通整个流程后,以下实践能让你的项目更健壮、更接近生产标准。
- 基础设施即代码 (IaC):不要手动点击 Jenkins 界面创建任务。将 Jenkins Pipeline 脚本(Jenkinsfile)存放在项目代码库根目录,在 Jenkins 中创建“流水线任务来自 SCM”的任务,实现流水线配置的版本化管理。
- 使用 Helm 管理 K8S 应用:将 Deployment、Service、ConfigMap 等 YAML 文件打包成 Helm Chart。只需一个
helm install命令即可部署整个应用,并通过values.yaml轻松配置不同环境(开发、测试、生产)的参数。 - 引入镜像仓库:在生产中,不应直接使用 Docker Hub 的公共仓库。搭建私有镜像仓库(如 Harbor)或使用云服务商提供的仓库,并配置镜像扫描和安全策略。
- 完善的监控与日志:为 K8S 集群部署 Prometheus 和 Grafana 来监控资源指标和应用性能。使用 EFK(Elasticsearch, Fluentd, Kibana)或 Loki 栈来集中收集和查询容器日志。
- GitOps 工作流:考虑使用 Argo CD 或 Flux 等 GitOps 工具。将应用所需的 K8S 清单文件存储在 Git 仓库中,Argo CD 会自动同步仓库与集群的状态,实现声明式、自动化的持续部署。
- 安全加固:
- 容器安全:使用非 root 用户运行容器,定期扫描镜像漏洞。
- K8S RBAC:为 Jenkins 等服务账户配置最小必要权限,而非使用
cluster-admin。 - 网络策略:使用 Calico 等网络插件定义 Pod 间的网络隔离策略。
这套从 Docker 到 K8S 再到 Jenkins CI/CD 的实战链路,清晰地展示了一个现代化应用从代码到上线的核心自动化流程。最大的价值不在于一次性记住所有命令,而在于理解了每个环节的职责和衔接方式。当你再次遇到“如何自动部署”这类问题时,你的思路会非常清晰:容器化 -> 编排定义 -> 自动化触发。
最先应该验证的是 Docker 部分,确保你能成功构建和运行一个自定义镜像。最容易踩的坑集中在网络和权限上,比如 Jenkins 与 Docker/K8S 的通信问题。后续的进阶,可以从优化 Pipeline 效率(并行阶段)、增加测试环节、集成代码质量扫描、实现蓝绿部署等方面深入。建议将本教程中的每个 YAML 文件和脚本都保存下来,它们是你构建更复杂流水线的最佳起点。