Docker与Kubernetes实战:从零搭建云原生应用部署环境 📅 2026/7/4 17:19:01 30款热门AI模型一站整合DeepSeek/GLM/Claude 随心用限时 5 折。 点击领海量免费额度最近在帮团队做容器化改造时发现很多刚接触云原生的小伙伴对 Docker 和 Kubernetes 的学习路径感到迷茫。网上的资料要么过于零散要么版本老旧跟着操作总遇到各种环境问题。本文将整合一套从零开始的实战教程基于当前主流稳定版本手把手带你搭建环境、理解核心概念、完成项目部署。无论你是想转行运维、提升后端技能还是单纯想掌握容器化技术这篇长文都能提供一条清晰的路径。学完后你将能独立完成一个微服务应用的 Docker 镜像构建、推送并在 K8s 集群中部署和发布。1. 背景与核心概念为什么是 Docker 和 Kubernetes在深入动手之前我们需要先理解这两个技术解决了什么问题以及它们之间的关系。这能帮助你在后续操作中不仅知道“怎么做”更明白“为什么这么做”。1.1 容器化与 Docker从“它在我这能跑”到“在哪都能跑”在传统开发中最令人头疼的问题之一就是环境不一致。开发人员在自己的电脑上可能安装了特定版本的 Node.js、Python 包测试通过的程序到了测试或生产服务器上却因为库版本、系统配置不同而无法运行。我们常戏称此为“玄学问题”。Docker的出现就是为了解决这个痛点。你可以把它理解为一个轻量级的标准化集装箱。这个集装箱里不仅装着你的应用程序还装着它运行所需的所有依赖如运行时环境、系统工具、库文件、配置文件。一旦在开发环境把这个集装箱即 Docker 镜像打包好它就可以被运送到任何安装了 Docker 引擎的服务器上并且保证以完全相同的方式运行。核心优势环境一致性镜像即环境彻底杜绝“在我机器上好好的”这类问题。快速部署与扩展秒级启动容器非常适合微服务架构和弹性伸缩。资源高效与传统虚拟机相比容器共享主机操作系统内核无需为每个应用加载完整的操作系统因此更轻量、启动更快、资源利用率更高。版本控制与回滚镜像本身有版本标签可以轻松回滚到之前的版本。1.2 容器编排与 Kubernetes从管理一个集装箱到调度整个船队当你只有一个或几个容器时手动管理或许还行。但当你的应用由数十甚至上百个微服务组成每个服务都需要多个副本以保证高可用并且还要处理服务发现、负载均衡、滚动更新、故障自愈、配置管理、存储挂载等一系列复杂问题时手动操作就变得不可能了。Kubernetes (常简称为 K8s)就是一个容器编排平台它好比一个智能的港口调度系统。你只需要告诉 K8s 你的应用最终应该是什么样子例如需要运行 3 个副本的 Web 服务每个副本需要 1G 内存并且需要挂载一个配置文件K8s 就会自动在集群中找到合适的服务器节点去创建并运行这些容器并持续监控它们的状态。如果某个容器挂了K8s 会自动重启它如果某个节点宕机K8s 会在其他节点上重新调度运行这些容器。核心价值自动化运维声明式配置让系统自动达到并维持你期望的状态。服务发现与负载均衡自动为容器组分配 IP 地址和 DNS 名称并实现流量负载均衡。存储编排自动挂载你选择的存储系统本地、云存储等。密钥与配置管理安全地存储和管理敏感信息如密码、密钥。自我修复重启失败容器、替换不可用节点、杀死不健康的容器。水平伸缩根据 CPU 使用率或其他自定义指标自动扩缩容应用副本数。简单来说Docker 负责“造”和“装”集装箱而 Kubernetes 负责“调度”和“管理”整个由集装箱组成的船队。两者结合构成了现代云原生应用的基石。2. 环境准备与版本说明工欲善其事必先利其器。为了避免版本兼容性问题我们统一使用当前2024-2025年的主流稳定版本进行演示。请注意软件生态更新很快以下版本在未来可能会变化但核心操作逻辑是相通的。2.1 基础环境要求操作系统本文以Ubuntu 22.04 LTS作为演示环境。CentOS 7/8、其他 Linux 发行版或 macOS 在安装命令上略有不同但 Docker 和 K8s 的核心概念与使用完全一致。Windows 用户建议使用 WSL2。硬件建议至少 2核 CPU4GB 内存20GB 磁盘空间。如果要搭建多节点的 K8s 集群需要更多资源。网络需要稳定的网络连接以下载镜像和软件包。2.2 软件版本清单以下是本文实战部分将用到的核心软件及其版本。请务必记录这是后续所有操作的基础。组件版本说明Docker Engine24.0社区稳定版。负责运行容器。Docker Composev2.20用于定义和运行多容器 Docker 应用的工具。Kubernetes (k8s)1.28我们使用kubeadm工具搭建一个单控制平面的集群。容器运行时containerd1.7K8s 默认的容器运行时Docker 本身也使用它。kubectl1.28命令行工具用于操作 K8s 集群。示例应用-一个简单的 Python Flask Web 应用。重要提示生产环境请务必查阅官方文档选择经过充分测试的版本组合。对于学习而言使用较新的稳定版可以接触到更多现代特性。3. Docker 核心实战从安装到镜像发布让我们从 Docker 开始这是所有容器化操作的第一步。3.1 安装 Docker Engine在 Ubuntu 22.04 上官方推荐使用 apt 仓库安装。# 1. 更新 apt 包索引并安装必要的依赖 sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg lsb-release # 2. 添加 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 # 3. 设置稳定版仓库 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 # 4. 更新 apt 包索引并安装最新版本的 Docker Engine sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 5. 验证安装是否成功 sudo docker run hello-world如果看到 “Hello from Docker!” 等信息说明安装成功。默认情况下运行 Docker 命令需要sudo权限。为了方便可以将当前用户加入docker组。sudo usermod -aG docker $USER # 执行后需要退出当前终端并重新登录或者执行 newgrp docker 使组更改生效3.2 理解 Docker 核心三要素镜像、容器、仓库镜像 (Image)一个只读的模板包含了运行应用所需的文件系统结构和内容。例如一个 Ubuntu 镜像、一个 Nginx 镜像。你可以基于一个镜像创建多个容器。容器 (Container)镜像的一个运行实例。你可以启动、停止、移动或删除容器。容器是隔离的拥有自己的进程、网络和文件系统。仓库 (Registry)存放镜像的地方。最著名的是 Docker Hub (https://hub.docker.com)你可以从中拉取公共镜像也可以推送自己的镜像需要注册账号。它们的关系是从仓库拉取镜像用镜像创建并运行容器。3.3 编写你的第一个 DockerfileDockerfile 是一个文本文件里面包含了一系列指令用于告诉 Docker 如何构建你的自定义镜像。我们来为一个简单的 Python Flask 应用创建镜像。首先创建项目目录和文件mkdir my-flask-app cd my-flask-app创建应用文件app.py# app.py from flask import Flask app Flask(__name__) app.route(/) def hello(): return Hello, Docker Kubernetes from CSDN! if __name__ __main__: app.run(host0.0.0.0, port5000)创建依赖文件requirements.txtFlask2.3.3现在创建最重要的Dockerfile# Dockerfile # 1. 指定基础镜像。我们使用官方的 Python 轻量级镜像。 FROM python:3.11-slim # 2. 设置工作目录。后续命令都会在这个目录下执行。 WORKDIR /app # 3. 将依赖文件复制到工作目录。 COPY requirements.txt . # 4. 安装 Python 依赖。使用清华镜像源加速国内环境。 RUN pip install --no-cache-dir -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt # 5. 将当前目录下的所有文件复制到容器的 /app 目录。 COPY . . # 6. 声明容器运行时监听的端口。这只是元数据实际映射需要在运行容器时指定。 EXPOSE 5000 # 7. 定义容器启动时执行的命令。 CMD [python, app.py]3.4 构建镜像并运行容器在Dockerfile所在目录执行构建命令# -t 参数给镜像打标签格式为 name:tag docker build -t my-flask-app:1.0 .构建过程会逐行执行 Dockerfile 中的指令。完成后可以用docker images查看本地镜像。运行一个容器# -d 后台运行-p 将宿主机的8080端口映射到容器的5000端口 docker run -d -p 8080:5000 --name my-flask-container my-flask-app:1.0现在打开浏览器访问http://localhost:8080你应该能看到 “Hello, Docker Kubernetes from CSDN!”。常用容器管理命令# 查看运行中的容器 docker ps # 查看所有容器包括已停止的 docker ps -a # 查看容器日志 docker logs my-flask-container # 停止容器 docker stop my-flask-container # 启动已停止的容器 docker start my-flask-container # 进入容器内部调试用 docker exec -it my-flask-container /bin/bash # 删除容器 docker rm my-flask-container # 删除镜像 docker rmi my-flask-app:1.03.5 使用 Docker Compose 编排多容器应用当你的应用需要多个服务如 Web 应用 数据库时使用 Docker Compose 可以简化管理。创建一个docker-compose.yml文件# docker-compose.yml version: 3.8 services: web: build: . # 使用当前目录的 Dockerfile 构建 ports: - 8080:5000 depends_on: - redis environment: - REDIS_HOSTredis redis: image: redis:alpine # 使用官方 Redis 镜像然后只需一条命令即可启动整个应用栈docker-compose up -d使用docker-compose down停止并移除所有相关容器。4. Kubernetes 核心实战搭建集群与部署应用掌握了 Docker我们就可以进入更强大的 Kubernetes 世界了。为了学习我们将在单台机器上搭建一个简易的 K8s 集群。4.1 使用 kubeadm 搭建单节点集群kubeadm是官方提供的用于快速搭建合规 K8s 集群的工具。以下步骤在 Ubuntu 22.04 上执行。步骤一前置配置# 1. 关闭交换分区K8s 认为交换会影响性能和稳定性 sudo swapoff -a # 永久关闭编辑 /etc/fstab注释掉包含 swap 的行 sudo sed -i / swap / s/^\(.*\)$/#\1/g /etc/fstab # 2. 配置网络转发和桥接流量 cat EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF sudo modprobe overlay sudo modprobe br_netfilter cat EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables 1 net.bridge.bridge-nf-call-iptables 1 net.ipv4.ip_forward 1 EOF sudo sysctl --system # 3. 安装容器运行时 containerdDocker 已安装但 K8s 默认用 containerd # 我们这里使用 Docker 的 containerd所以只需配置 sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml # 修改配置使用 systemd 作为 cgroup 驱动 sudo sed -i s/SystemdCgroup false/SystemdCgroup true/ /etc/containerd/config.toml sudo systemctl restart containerd sudo systemctl enable containerd步骤二安装 kubeadm, kubelet, kubectl# 添加 Kubernetes apt 仓库 sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg echo deb [signed-by/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ / | sudo tee /etc/apt/sources.list.d/kubernetes.list # 安装 sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl # 防止被自动升级步骤三初始化集群# 初始化控制平面节点。注意替换 your-master-ip 为你机器的内网IP。 sudo kubeadm init --apiserver-advertise-addressyour-master-ip --pod-network-cidr10.244.0.0/16初始化成功后会输出类似下面的信息其中包含加入集群的命令和配置kubectl的指令务必保存好。Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run kubectl apply -f [podnetwork].yaml with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join control-plane-host:control-plane-port --token token --discovery-token-ca-cert-hash sha256:hash按照提示配置kubectlmkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config步骤四安装 Pod 网络插件Pod 之间需要网络才能通信。我们安装最常用的 Flannel。kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml等待几分钟使用kubectl get pods -n kube-system查看所有系统 Pod 是否都处于Running状态。步骤五解除控制平面节点的调度限制单节点集群必需默认情况下控制平面节点不运行用户 Pod。kubectl taint nodes --all node-role.kubernetes.io/control-plane-现在一个单节点的 K8s 学习集群就搭建好了使用kubectl get nodes查看节点状态应为Ready。4.2 理解 Kubernetes 核心对象在部署应用前需要理解几个最核心的 K8s 对象资源PodK8s 中最小的可部署单元。一个 Pod 包含一个或多个容器通常是一个共享存储、网络和命名空间。Deployment用于管理 Pod 副本的声明式对象。你定义“期望状态”如需要3个副本Deployment 控制器会确保实际状态与之匹配。它处理滚动更新和回滚。Service定义了一组 Pod 的访问策略。为 Pod 提供一个稳定的 IP 地址和 DNS 名称并实现负载均衡。Namespace虚拟集群用于在物理集群中划分资源实现多租户隔离。4.3 编写 YAML 清单文件部署应用K8s 使用 YAML 文件来声明资源的状态。我们将之前构建的 Flask 应用部署到 K8s。首先需要将本地镜像推送到一个镜像仓库如 Docker Hub或者让 K8s 使用本地镜像需配置。为了简化我们先学习如何从公共仓库拉取镜像。假设我们已经将my-flask-app:1.0推送到了 Docker Hub 的yourusername/my-flask-app:1.0。创建部署文件flask-deployment.yaml# flask-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 image: yourusername/my-flask-app:1.0 # 替换为你的镜像 ports: - containerPort: 5000 resources: requests: memory: 128Mi cpu: 100m limits: memory: 256Mi cpu: 200m应用这个部署kubectl apply -f flask-deployment.yaml使用kubectl get pods查看 Pod 状态等待所有 Pod 变为Running。Pod 已经运行但外部还无法访问。我们需要创建一个 Service 来暴露它。创建flask-service.yaml# flask-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 # 容器内监听的端口 type: NodePort # 使用 NodePort 类型便于从集群外访问应用 Servicekubectl apply -f flask-service.yaml查看 Servicekubectl get svc flask-app-service输出中会有一个PORT(S)列例如80:3xxxx/TCP。后面的3xxxx就是随机分配的 NodePort。现在你可以通过http://你的服务器IP:3xxxx访问到 Flask 应用了4.4 基本运维操作# 查看资源 kubectl get deployments kubectl get pods -o wide kubectl get svc kubectl describe pod pod-name # 查看Pod详情常用于排错 # 查看日志 kubectl logs pod-name kubectl logs -f pod-name # 实时查看日志流 # 进入Pod类似 docker exec kubectl exec -it pod-name -- /bin/bash # 扩缩容 kubectl scale deployment flask-app-deployment --replicas5 # 更新镜像触发滚动更新 kubectl set image deployment/flask-app-deployment flask-appyourusername/my-flask-app:2.0 # 查看更新状态和回滚 kubectl rollout status deployment/flask-app-deployment kubectl rollout history deployment/flask-app-deployment kubectl rollout undo deployment/flask-app-deployment --to-revision1 # 删除资源 kubectl delete -f flask-deployment.yaml kubectl delete deployment flask-app-deployment5. 常见问题与排查思路在学习和使用 Docker 和 K8s 的过程中你一定会遇到各种问题。下面是一些高频问题的排查思路。问题现象可能原因排查思路与解决方案docker run报错端口被占用宿主机上该端口已被其他进程使用。sudo netstat -tulpn | grep :端口号查找占用进程并停止或更改-p参数映射到其他端口。docker build速度极慢或失败网络问题或 Dockerfile 中某些指令如apt-get update因网络超时失败。1. 为RUN指令设置国内镜像源如阿里云、中科大。2. 使用--networkhost模式构建。3. 使用 Docker 的构建缓存分层构建。kubectl get pods显示PendingPod 无法被调度到节点上。kubectl describe pod pod-name查看Events部分。常见原因资源不足、节点有污点taint、未满足节点选择器。kubectl get pods显示ImagePullBackOff无法拉取镜像。1. 检查镜像名称和标签是否正确。2. 检查镜像仓库是否需认证需创建 Secret。3. 节点网络是否通畅。kubectl describe pod查看详情。kubectl get pods显示CrashLoopBackOffPod 内的容器启动后立即退出。1.kubectl logs pod-name查看应用日志通常是应用自身错误如代码bug、依赖缺失。2. 检查容器启动命令CMD是否正确。3. 检查资源限制是否过小。Service 创建后无法访问1. Pod 的标签与 Service 的selector不匹配。2.NodePort范围不在默认范围30000-32767。3. 云服务器安全组/防火墙未放行端口。1.kubectl get pods --show-labels和kubectl describe svc svc-name核对标签。2. 检查kubectl get svc输出的端口。3. 检查宿主机防火墙和云平台安全组规则。kubeadm init失败多种可能端口冲突、swap 未关闭、镜像拉取失败、容器运行时未就绪。1. 根据错误信息搜索错误信息通常很明确。2. 执行kubeadm reset后按本文“前置配置”步骤仔细检查。3. 使用kubeadm init --v5获取更详细日志。Pod 内无法解析外部域名CoreDNS Pod 未正常运行或配置错误。1.kubectl get pods -n kube-system | grep coredns检查状态。2.kubectl logs -n kube-system coredns-pod-name查看日志。3. 检查 Pod 的/etc/resolv.conf配置。通用排错命令链kubectl get 资源类型查看资源状态。kubectl describe 资源类型 资源名查看详细事件和配置。kubectl logs pod-name查看应用日志。kubectl exec -it pod-name -- command进入容器内部检查。6. 最佳实践与工程建议掌握了基础操作后将这些最佳实践应用到项目中能极大提升稳定性、安全性和可维护性。6.1 Docker 最佳实践使用多阶段构建对于编译型语言如 Go, Java在第一个阶段编译在第二个仅包含运行时的轻量级阶段复制编译结果可以极大减小最终镜像体积。# 示例Go 多阶段构建 FROM golang:1.20 AS builder WORKDIR /app COPY . . RUN CGO_ENABLED0 GOOSlinux go build -o myapp . FROM alpine:latest WORKDIR /root/ COPY --frombuilder /app/myapp . CMD [./myapp]合理利用构建缓存Dockerfile 中每条指令都会生成一层镜像。将变化频率低的指令如安装基础工具放在前面变化频率高的指令如复制源代码放在后面可以充分利用缓存加速构建。使用.dockerignore文件类似于.gitignore避免将不必要的文件如node_modules,.git, 日志文件复制到镜像中减小镜像体积。以非 root 用户运行容器在 Dockerfile 中创建并使用非 root 用户增强安全性。RUN groupadd -r appuser useradd -r -g appuser appuser USER appuser明确指定镜像标签避免使用latest标签应在 CI/CD 或构建命令中明确指定版本号或构建号如myapp:v1.2.3或myapp:git-${COMMIT_SHA}。6.2 Kubernetes 最佳实践资源请求与限制务必为 Pod 设置resources.requests和resources.limits。这有助于调度器做出合理决策并防止单个 Pod 耗尽节点资源。resources: requests: memory: 64Mi cpu: 250m limits: memory: 128Mi cpu: 500m使用 Readiness 和 Liveness 探针它们告诉 K8s 你的应用是否已准备好接收流量Readiness以及是否健康运行Liveness。这是实现零停机部署和自我修复的关键。livenessProbe: httpGet: path: /healthz port: 8080 initialDelaySeconds: 3 periodSeconds: 3 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5将配置与镜像分离使用ConfigMap存储配置使用Secret经过 Base64 编码存储敏感信息通过环境变量或卷挂载的方式注入到 Pod 中。切勿将配置硬编码在镜像里。使用 Namespace 进行逻辑隔离将不同项目、不同环境dev/staging/prod的资源划分到不同的命名空间中便于管理和权限控制。为生产环境配置 HPA使用 Horizontal Pod Autoscaler 根据 CPU/内存等指标自动扩缩容 Deployment以应对流量波动。做好日志与监控确保应用日志输出到标准输出stdout和标准错误stderrK8s 会自动捕获。集成监控系统如 Prometheus Grafana来监控集群和应用状态。6.3 学习与项目进阶路线巩固基础反复练习本文的实操步骤直到能熟练完成从 Docker 镜像构建到 K8s 服务暴露的全流程。学习核心概念深入理解 K8s 的StatefulSet有状态应用、DaemonSet每个节点运行一个 Pod、Job/CronJob批处理任务、Ingress七层流量入口、PersistentVolume/PersistentVolumeClaim持久化存储。尝试 Helm学习使用 Helm 作为 K8s 的包管理工具用 Chart 来打包、分享和部署复杂的应用。搭建多节点集群在云服务器或本地虚拟机中搭建一个真正的多节点集群理解 Master 和 Worker 节点的角色。集成 CI/CD将整个流程自动化。例如使用 GitHub Actions 或 Jenkins代码推送 → 自动构建 Docker 镜像 → 推送至镜像仓库 → 自动更新 K8s 部署。探索云服务尝试使用阿里云 ACK、腾讯云 TKE、亚马逊 EKS 等托管 K8s 服务了解它们如何简化集群管理。容器化和 Kubernetes 是现代软件开发和运维的必备技能其学习曲线虽然有些陡峭但一旦掌握你将拥有应对复杂系统部署和管理的强大能力。从今天开始动手将你的一个简单项目容器化并部署到 K8s 中这是最好的学习方式。过程中遇到问题善用官方文档、社区和搜索引擎大部分坑都有前人踩过并提供了解决方案。记住实践出真知祝你学习顺利 30款热门AI模型一站整合DeepSeek/GLM/Claude 随心用限时 5 折。 点击领海量免费额度