Docker与Kubernetes从零实战:环境搭建、镜像构建到集群部署全流程 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度大家好我是专注于分享云计算与容器化技术的博主。在当今云原生时代无论是开发、测试还是运维Docker和KubernetesK8S已成为必须掌握的核心技能。然而面对海量的教程和复杂的官方文档很多初学者感到无从下手环境搭建、概念理解、YAML编写每一步都可能成为拦路虎。本文旨在提供一份从零开始的实战指南不仅涵盖Docker和K8S的核心概念与基础操作更会通过一个完整的项目案例带你体验从镜像构建到服务上线的全流程。无论你是想转型运维的开发者还是希望提升部署效率的在校学生都能通过本文的步骤和代码搭建起自己的实验环境并运行起第一个容器化应用。1. 背景与核心概念为什么是Docker与K8S在深入动手之前我们需要理解这两个技术解决了什么问题以及它们之间的关系。Docker的核心是容器化技术。你可以把它想象成一个超级轻量级的虚拟机。但与虚拟机模拟整个操作系统不同容器直接运行在宿主机的内核上它只打包应用及其运行所需的库和环境。这就带来了几个革命性的优势环境一致性开发环境构建的镜像可以百分百复现在测试和生产环境彻底告别“在我机器上是好的”这类问题。资源高效容器启动秒级资源占用远低于虚拟机一台宿主机可以运行成百上千个容器。交付标准化应用以镜像Image的形式交付镜像本身不可变部署和回滚变得极其简单。Kubernetes (K8S)则是容器编排引擎。当你的应用从单个服务发展为由数十、数百个容器组成的微服务集群时你会面临一系列新挑战如何管理这么多容器的生命周期自动部署、重启、扩缩容如何让它们相互发现并通信如何将外部流量正确地分发到内部容器如何管理配置和密钥如何保证存储持久化K8S就是为解决这些问题而生的。它提供了一个平台用于自动化部署、扩展和管理容器化应用。你可以告诉K8S你想要的应用状态例如运行3个Nginx实例使用80端口K8S会持续工作确保实际状态与期望状态一致。简单比喻Docker是“集装箱”它标准化了货物的包装和运输。K8S是“超级货轮和自动化港口系统”它负责调度、管理成千上万个集装箱确保它们被运送到正确的位置并且在整个航程中保持稳定。2. 环境准备与版本说明我们的实战环境将基于Linux系统Ubuntu 20.04 LTS为例这是生产环境中最常见的选择。所有操作均通过命令行完成。核心组件与版本操作系统Ubuntu 20.04 LTS (内核版本 5.4 或以上)容器运行时Docker Engine 24.0容器编排Kubernetes (使用minikube搭建单节点集群) 1.28命令行工具docker: Docker客户端kubectl: K8S集群管理命令行工具minikube: 用于本地快速搭建单节点K8S集群的工具版本兼容性说明K8S与Docker的版本有对应关系。自K8S 1.24版本起默认移除了对Docker作为容器运行时的直接支持但Docker本身仍可生成符合标准的镜像。为了简化学习我们使用minikube它会自动集成一个兼容的容器运行时如containerd而我们本地安装的Docker主要用于构建镜像。这是一种业界通用的混合使用方式。安装概要详细命令见后续章节安装Docker Engine。安装kubectl命令行工具。安装minikube并启动一个本地K8S集群。3. 核心组件安装与配置3.1 安装Docker Engine首先更新系统包索引并安装必要的依赖。# 更新apt包索引 sudo apt-get update # 安装依赖包允许apt通过HTTPS使用仓库 sudo apt-get install -y \ ca-certificates \ curl \ gnupg \ lsb-release添加Docker官方GPG密钥和稳定版仓库。# 创建目录存放密钥环 sudo mkdir -p /etc/apt/keyrings # 下载并导入Docker官方GPG密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # 添加Docker稳定版仓库 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 # 安装Docker Engine、CLI、Containerd等 sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin验证安装并配置用户组避免每次使用sudo。# 启动Docker服务并设置开机自启 sudo systemctl start docker sudo systemctl enable docker # 将当前用户加入docker组以便非root用户运行docker命令 sudo usermod -aG docker $USER # 注意执行完上一步后需要**注销并重新登录**或重启系统组更改才会生效。 # 验证安装运行hello-world镜像 docker run hello-world如果看到Hello from Docker!等欢迎信息说明Docker安装成功。3.2 安装kubectlkubectl是操作K8S集群的“遥控器”。我们通过官方脚本安装最新稳定版。# 下载最新稳定版kubectl二进制文件 curl -LO https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl # 验证二进制文件可选但推荐 curl -LO https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256 echo $(cat kubectl.sha256) kubectl | sha256sum --check # 安装kubectl到系统路径 sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl # 验证安装 kubectl version --client --outputyaml3.3 安装Minikube并启动集群Minikube是在本地轻松创建单节点K8S集群的最佳工具。# 下载并安装Minikube二进制文件 curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube # 启动Minikube集群。这里使用docker作为驱动需要已安装Docker。 # --force 参数在root用户或某些环境下可能需要。 minikube start --driverdocker启动过程会下载基础镜像并配置集群需要几分钟时间。完成后可以查看集群状态。# 查看集群状态 minikube status # 查看集群节点信息现在应该有一个名为 minikube 的节点 kubectl get nodes至此一个完整的本地Docker Kubernetes学习环境就准备好了。4. Docker核心实战构建与运行自定义应用镜像理解了概念安装了环境现在我们从零开始创建一个简单的Web应用并将其容器化。4.1 创建应用代码我们创建一个用Python Flask编写的简单Web应用。# 创建一个项目目录 mkdir my-flask-app cd my-flask-app创建应用文件app.py# app.py from flask import Flask import os import socket app Flask(__name__) app.route(/) def hello(): hostname socket.gethostname() # 尝试读取一个通过环境变量设置的用户名 username os.getenv(USERNAME, Guest) return f h1Hello from Docker K8S!/h1 pHostname: b{hostname}/b/p pUsername: b{username}/b/p pThis is a simple Flask app running inside a container./p if __name__ __main__: # 监听所有网络接口的5000端口 app.run(host0.0.0.0, port5000, debugTrue)创建Python依赖文件requirements.txt# requirements.txt Flask2.3.34.2 编写DockerfileDockerfile是构建镜像的“食谱”它定义了镜像的每一层内容。# 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 # 设置维护者标签非必须 LABEL maintainerdevopsexample.com # 设置工作目录 WORKDIR /app # 从构建阶段复制已安装的Python依赖 COPY --frombuilder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages COPY --frombuilder /usr/local/bin /usr/local/bin # 复制应用源代码 COPY app.py . # 声明容器运行时监听的端口 EXPOSE 5000 # 定义环境变量可在运行容器时覆盖 ENV USERNAMECSDN_Reader # 定义容器启动时执行的命令 CMD [python, app.py]关键指令解析FROM指定基础镜像。我们使用了两阶段构建最终镜像更小。WORKDIR设置工作目录后续的COPY、RUN、CMD命令都在此目录下执行。COPY将宿主机文件复制到镜像内。RUN在构建镜像时执行命令如安装软件包。EXPOSE声明容器打算使用的端口这是一个元数据方便使用者理解。ENV设置环境变量。CMD指定容器启动时默认运行的命令一个Dockerfile只能有一个CMD。4.3 构建Docker镜像在my-flask-app目录下执行构建命令。-t参数用于给镜像打标签。docker build -t my-flask-app:1.0 .命令最后的.表示Dockerfile所在的当前目录。构建成功后可以使用docker images查看镜像。4.4 运行并测试容器基于刚构建的镜像运行一个容器。# -d: 后台运行 # -p 8080:5000: 将宿主机的8080端口映射到容器的5000端口 # --name: 给容器起个名字 docker run -d -p 8080:5000 --name flask-container my-flask-app:1.0现在打开浏览器访问http://localhost:8080你应该能看到Flask应用返回的页面显示主机名和用户名。常用容器管理命令# 查看正在运行的容器 docker ps # 查看所有容器包括已停止的 docker ps -a # 查看容器日志 docker logs flask-container # 停止容器 docker stop flask-container # 删除容器 docker rm flask-container # 进入容器内部调试用 docker exec -it flask-container /bin/bash5. Kubernetes核心实战部署应用到集群现在我们将这个容器化的应用部署到Minikube创建的K8S集群中。5.1 推送镜像到Minikube内部Minikube有自己的容器运行时环境。最简单的方式是让Minikube直接使用我们本地构建的镜像。# 告诉Docker客户端使用Minikube内部的Docker守护进程这样构建的镜像会直接存在于Minikube环境中 eval $(minikube docker-env) # 重新构建镜像这次镜像会直接保存在Minikube的镜像仓库里 docker build -t my-flask-app:1.0 . # 切换回本地Docker环境可选 eval $(minikube docker-env -u)5.2 编写Kubernetes部署清单DeploymentK8S通过YAML文件来定义资源。我们创建一个deployment.yaml。# deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: flask-app-deployment labels: app: flask-app spec: replicas: 3 # 我们希望运行3个相同的Pod副本 selector: matchLabels: app: flask-app template: # 这是Pod的模板 metadata: labels: app: flask-app spec: containers: - name: flask-app-container image: my-flask-app:1.0 # 使用我们构建的镜像 imagePullPolicy: Never # 因为镜像在本地不需要从远程仓库拉取 ports: - containerPort: 5000 # 容器监听的端口 env: - name: USERNAME # 覆盖Dockerfile中设置的环境变量 value: K8S_User resources: requests: memory: 64Mi cpu: 100m limits: memory: 128Mi cpu: 200m关键字段解析replicas: 3声明期望有3个Pod实例在运行。K8S会确保始终有3个健康的Pod。selector和template.metadata.labels必须匹配Deployment通过标签来管理它创建的Pod。imagePullPolicy: Never对于本地构建的镜像必须设置为Never或IfNotPresent否则K8S会尝试从公共仓库拉取而失败。resources为容器设置资源请求和限制这是生产环境最佳实践防止单个容器耗尽节点资源。5.3 编写Kubernetes服务清单ServicePod的IP地址是不固定的我们需要一个Service来提供稳定的访问入口并将流量负载均衡到后端的多个Pod。# service.yaml apiVersion: v1 kind: Service metadata: name: flask-app-service spec: selector: app: flask-app # 选择所有标签为 appflask-app 的Pod ports: - protocol: TCP port: 80 # Service对外的端口 targetPort: 5000 # 转发到Pod的哪个端口 type: NodePort # 使用NodePort类型便于从集群外访问5.4 部署应用到K8S集群使用kubectl apply命令创建资源。# 切换到包含YAML文件的目录 cd /path/to/my-flask-app # 创建Deployment kubectl apply -f deployment.yaml # 创建Service kubectl apply -f service.yaml查看部署状态# 查看Deployment状态 kubectl get deployments # 查看Pod状态应该能看到3个Running的Pod kubectl get pods # 查看Service状态 kubectl get svc查看flask-app-service的详细信息你会看到NodePort一行例如80:3xxxx/TCP其中3xxxx是随机分配的高位端口范围30000-32767。5.5 访问应用由于我们使用的是Minikube可以通过以下命令获取访问URL# 获取Service的访问URLMinikube会创建一个隧道方便访问NodePort服务 minikube service flask-app-service --url命令会返回一个类似http://192.168.49.2:3xxxx的URL在浏览器中打开它就能看到运行在K8S集群中的Flask应用了刷新页面可能会看到Hostname发生变化这证明Service正在将请求负载均衡到不同的Pod上。6. 核心操作与问题排查6.1 常用Kubectl命令速查操作命令说明查看资源kubectl get pods查看所有Podkubectl get deployments查看所有Deploymentkubectl get svc查看所有Servicekubectl get all查看所有常见资源查看详情kubectl describe pod pod-name查看Pod的详细事件和状态kubectl logs pod-name查看Pod日志kubectl logs -f pod-name实时跟踪Pod日志进入Podkubectl exec -it pod-name -- /bin/bash进入Pod的容器内部删除资源kubectl delete -f file.yaml根据YAML文件删除资源kubectl delete deployment name删除指定Deployment扩缩容kubectl scale deployment/name --replicas5将Pod副本数扩展到5个6.2 常见问题与排查思路问题现象可能原因排查步骤与解决方案ImagePullBackOff或ErrImagePull镜像拉取失败。1.kubectl describe pod pod-name查看事件详情。2. 确认镜像名和标签是否正确。3. 如果是本地镜像检查imagePullPolicy是否设置为Never或IfNotPresent。4. 如果是私有仓库检查Secret配置。CrashLoopBackOffPod内的容器启动后立即崩溃。1.kubectl logs pod-name查看崩溃前的日志通常是应用代码错误。2.kubectl describe pod检查资源限制是否过小。3. 检查应用启动命令Dockerfile中的CMD是否正确。Pod状态PendingPod无法被调度到节点上。1.kubectl describe pod查看事件常见原因是节点资源不足CPU/Memory。2. 检查节点状态kubectl get nodes确认节点是否Ready。3. 检查是否有污点Taint或亲和性Affinity规则限制。Service无法访问网络配置问题。1. 确认Service的selector与Pod的labels匹配。2.kubectl get endpoints service-name检查Endpoint列表是否为空。3. 在集群内另一个Pod中使用curl service-name测试内部DNS是否解析。4. 对于NodePort检查防火墙是否放行了对应端口。kubectl命令无响应无法连接到K8S API Server。1. 检查Minikube状态minikube status确保集群正在运行。2. 检查~/.kube/config配置文件是否正确。3. 重启Minikube集群minikube stop minikube start。7. 生产环境最佳实践与进阶建议将应用部署到开发环境只是第一步要用于生产还需考虑更多因素。7.1 镜像管理使用私有镜像仓库生产镜像不应放在公共仓库。搭建或使用Harbor、AWS ECR、阿里云ACR等私有仓库。镜像标签与版本化不要只用latest标签。使用语义化版本如v1.2.3或Git提交哈希如commit-abc123作为标签便于追踪和回滚。镜像扫描集成安全扫描工具如Trivy、Clair到CI/CD流程检查镜像中的漏洞。7.2 资源配置与限制必须设置资源请求和限制如示例中所示为每个容器设置requests和limits。这有助于调度器做出合理决策并防止“吵闹的邻居”问题。使用LimitRange和ResourceQuota在命名空间级别设置默认的资源限制和总配额实现多团队间的资源隔离和公平使用。7.3 应用部署策略使用Deployment而非裸PodDeployment提供了声明式更新、回滚和副本数维护是管理无状态应用的标准方式。配置健康检查在Deployment中定义livenessProbe存活探针和readinessProbe就绪探针让K8S能准确判断应用的健康状态实现自我修复。livenessProbe: httpGet: path: /health port: 5000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 5000 initialDelaySeconds: 5 periodSeconds: 5考虑多副本与反亲和性对于高可用应用至少运行2个副本并配置podAntiAffinity尝试将Pod调度到不同的节点上避免单点故障。7.4 配置与密钥管理切勿将配置硬编码在镜像中使用ConfigMap存储配置数据如环境变量、配置文件使用Secret存储敏感信息如密码、令牌。在Deployment中引用它们。env: - name: DB_HOST valueFrom: configMapKeyRef: name: app-config key: database.host - name: DB_PASSWORD valueFrom: secretKeyRef: name: app-secret key: db-password7.5 日志与监控标准输出日志确保应用日志输出到标准输出stdout和标准错误stderrK8S会自动捕获并可通过kubectl logs查看。集中式日志生产环境需使用EFKElasticsearch, Fluentd, Kibana或Loki等方案收集所有Pod的日志进行集中存储和分析。监控部署Prometheus监控K8S集群和应用的各项指标CPU、内存、网络、业务指标使用Grafana进行可视化。7.6 持续集成与持续部署CI/CD将Docker镜像构建和K8S部署YAML的更新自动化。常见的模式是代码推送到Git仓库后CI工具如Jenkins、GitLab CI、GitHub Actions自动执行测试、构建镜像、推送镜像到仓库并更新K8S集群中的Deployment镜像版本可通过kubectl set image或GitOps工具如ArgoCD、Flux实现。8. 学习路线与资源推荐通过本文的实战你已经完成了从零到一的跨越掌握了Docker和K8S最核心的搭建、构建、部署流程。但要真正掌握云原生技术栈建议按以下路径深入巩固基础反复练习本文的实战案例理解每个命令和YAML字段的含义。尝试修改应用代码、环境变量、副本数观察变化。深入学习K8S核心概念Pod理解Pod是调度的最小单位以及Pod的生命周期。Service Ingress深入理解ClusterIP, NodePort, LoadBalancer类型的区别学习Ingress实现七层路由和HTTPS。Volume PersistentVolume学习如何在Pod中挂载存储实现数据持久化。ConfigMap Secret掌握如何将配置与镜像解耦。尝试有状态应用部署一个带数据库如MySQL的应用学习使用StatefulSet和PersistentVolumeClaim。学习HelmHelm是K8S的包管理器用于管理复杂的多资源应用部署Charts是生产部署的利器。探索服务网格当微服务数量增多时了解Istio或Linkerd如何管理服务间通信、安全、可观测性。关注云原生生态了解CNCF云原生计算基金会的其他项目如Prometheus监控、Fluentd日志、gRPCRPC框架等。官方文档是你最好的朋友遇到问题时优先查阅Docker官方文档https://docs.docker.com/Kubernetes官方文档https://kubernetes.io/docs/home/动手实验是学习运维技术的唯一捷径。建议在个人云服务器或利用Minikube/Kind搭建的本地集群中将你的个人项目容器化并部署在实践中遇到并解决问题你的技能树才会真正牢固。 30款热门AI模型一站整合DeepSeek/GLM/Qwen 随心用限时 5 折。 点击领海量免费额度