从零搭建Docker与Kubernetes实战环境:手把手教程与排错指南

📅 2026/7/9 18:10:25 👁️ 阅读次数 📝 编程学习
从零搭建Docker与Kubernetes实战环境:手把手教程与排错指南

🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度

最近在帮团队搭建新的微服务环境,发现很多刚接触容器化和云原生的同学,对 Docker 和 Kubernetes (K8S) 的理解还停留在“听说过”的阶段。从安装配置到实际部署应用,中间踩的坑一个接一个,网上资料要么太旧,要么太散,不成体系。

如果你也正面临类似困境——想系统学习容器技术却不知从何下手,或者项目急需落地但被复杂的配置和网络问题卡住——那么这篇文章就是为你准备的。本文将带你从零开始,手把手搭建一套完整的 Docker + K8S 学习与实践环境。内容涵盖从 Linux 基础操作、Docker 核心概念与实战,到 K8S 集群搭建、应用部署与管理,最后还会探讨其在云计算运维中的核心价值。文末提供了完整的实战项目配置文件和常见问题排查清单,无论是学生练手还是企业开发,都能直接复用。

1. 背景与核心概念:为什么是 Docker 和 K8S?

在深入动手之前,我们需要先理解这两个技术解决了什么问题,以及它们之间的关系。

Docker的核心是容器化。你可以把它想象成一个超级轻量级的“虚拟机”。但与虚拟机需要模拟完整的操作系统(Guest OS)不同,容器直接共享宿主机的操作系统内核,只打包应用及其运行所需的库和依赖。这使得容器具有启动快、资源消耗小、部署一致性好等巨大优势。Docker 提供了构建、分发和运行容器的完整工具链。

Kubernetes (K8S)的核心是容器编排。当你的应用从单体服务拆分成数十甚至上百个微服务,每个服务都用容器封装后,如何管理这些容器的生命周期?如何实现自动扩缩容、负载均衡、服务发现、滚动更新和故障自愈?手动操作 Docker 命令会变得极其困难。K8S 就是一个生产级的容器编排平台,它负责自动化管理成百上千的容器,让开发者可以专注于应用本身。

它们的关系:Docker 是“集装箱”,负责把货物(应用)标准化打包;Kubernetes 是“超级货轮和港口调度系统”,负责管理成千上万个集装箱的运输、存放和调度。通常,我们使用 Docker 来创建容器镜像,然后在 K8S 集群中运行这些镜像。

应用场景

  • 开发环境一致性:用 Docker 镜像固化环境,“一次构建,处处运行”,彻底解决“在我机器上是好的”问题。
  • CI/CD 流水线:容器作为构建和测试的标准单元,实现快速、可靠的持续集成与部署。
  • 微服务架构:K8S 是微服务架构的理想运行平台,提供服务治理、弹性伸缩等能力。
  • 混合云与多云部署:K8S 提供了抽象层,让应用可以无缝运行在不同的云平台或数据中心。

2. 环境准备与版本说明

本文将在一个纯净的 Linux 环境下进行所有操作。为了保证教程的通用性和可复现性,我们选择Ubuntu 22.04 LTS作为演示系统。其他 Linux 发行版(如 CentOS、Debian)的命令会有细微差别,文中会适当说明。

核心软件版本

  • 操作系统:Ubuntu 22.04.4 LTS (Jammy Jellyfish)
  • Docker Engine:24.0.7
  • Kubernetes (kubeadm, kubelet, kubectl):1.28.2
  • 容器运行时:containerd 1.7.6 (由 Docker 安装时默认集成,K8S 也使用它)

硬件与网络要求

  • 至少2核 CPU4GB 内存(运行 K8S 单节点集群的最低要求,生产环境需更高)。
  • 稳定的网络连接,用于下载软件包和容器镜像。
  • 禁用交换分区(Swap),K8S 默认要求。sudo swapoff -a并编辑/etc/fstab注释掉 swap 行。

重要提示:容器和云原生生态迭代迅速,版本兼容性至关重要。本文提供的安装命令和配置基于上述版本验证。如果你的环境是其他版本(尤其是较新的版本),部分命令或参数可能需要调整。建议先通读全文理解原理,再根据官方文档进行微调。

3. Linux 基础与 Docker 核心实战

在搭建 K8S 之前,我们必须先掌握 Docker,而 Docker 又运行在 Linux 之上。因此,我们从必要的 Linux 操作开始。

3.1 必备 Linux 命令速查

即使你是 Windows 或 macOS 用户,在服务器领域,Linux 是绝对的主流。以下是容器运维中最常用的命令:

# 1. 系统与权限 sudo -i # 切换到 root 用户(谨慎使用) whoami # 查看当前用户 cat /etc/os-release # 查看系统版本 df -h # 查看磁盘使用情况 free -h # 查看内存使用情况 # 2. 文件操作 ls -la /path/ # 详细列出目录内容 cp -r source dest # 递归复制 mv old new # 移动或重命名 rm -rf dir # 强制递归删除(危险!) chmod +x script.sh # 给脚本添加执行权限 chown user:group file # 修改文件属主和属组 # 3. 网络与进程 ip addr show # 查看 IP 地址(替代老旧的 ifconfig) netstat -tulnp # 查看端口监听情况(需安装 net-tools) ss -tulnp # 查看端口监听情况(更现代的 ss 命令) ps aux | grep nginx # 查找 nginx 进程 systemctl status docker # 查看 Docker 服务状态 journalctl -u docker -f # 实时查看 Docker 服务日志 # 4. 包管理 (Ubuntu/Debian) sudo apt update # 更新软件包列表 sudo apt upgrade -y # 升级所有已安装的包 sudo apt install -y vim curl wget git # 安装常用工具

3.2 Docker 安装与配置

在 Ubuntu 上安装 Docker 官方版本是最佳实践。

# 1. 卸载旧版本(如果是全新系统可跳过) sudo apt remove docker docker-engine docker.io containerd runc # 2. 安装依赖工具 sudo apt update sudo apt 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 update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin # 6. 启动 Docker 并设置开机自启 sudo systemctl start docker sudo systemctl enable docker # 7. 验证安装 sudo docker run hello-world

如果看到 “Hello from Docker!” 的输出,说明安装成功。

配置镜像加速器:从 Docker Hub 拉取镜像在国内可能很慢。我们需要配置国内镜像源。

# 编辑 Docker 守护进程配置文件 sudo vim /etc/docker/daemon.json

将以下内容写入(如果文件不存在则创建),这里使用阿里云和网易的镜像加速器。

{ "registry-mirrors": [ "https://<你的ID>.mirror.aliyuncs.com", "https://hub-mirror.c.163.com" ], "exec-opts": ["native.cgroupdriver=systemd"], "log-driver": "json-file", "log-opts": { "max-size": "100m" }, "storage-driver": "overlay2" }

保存后,重启 Docker 使配置生效:

sudo systemctl daemon-reload sudo systemctl restart docker

3.3 Docker 核心概念与实战

理解三个核心概念:镜像(Image)容器(Container)仓库(Registry)

1. 镜像操作镜像是容器的模板,是一个只读的文件层集合。

# 搜索镜像 docker search nginx # 拉取镜像(从 Docker Hub) docker pull nginx:alpine # 拉取轻量版 nginx 镜像 docker pull mysql:8.0 # 查看本地镜像 docker images # 或使用更强大的格式 docker image ls --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}" # 删除镜像 docker rmi <镜像ID或名称> docker image prune -a # 删除所有未被容器使用的镜像(悬空镜像)

2. 容器操作容器是镜像的运行实例。

# 运行一个容器 # -d: 后台运行 # -p 80:80: 将宿主机的80端口映射到容器的80端口 # --name mynginx: 给容器命名 docker run -d -p 80:80 --name mynginx nginx:alpine # 查看运行中的容器 docker ps # 查看所有容器(包括已停止的) docker ps -a # 进入容器内部(就像 SSH 到一台服务器) docker exec -it mynginx /bin/sh # alpine 镜像用 /bin/sh # 对于 Ubuntu/CentOS 镜像,通常用 /bin/bash # docker exec -it myubuntu /bin/bash # 查看容器日志 docker logs mynginx docker logs -f mynginx # 实时跟踪日志 # 停止、启动、重启容器 docker stop mynginx docker start mynginx docker restart mynginx # 删除容器(必须先停止) docker rm mynginx docker rm -f mynginx # 强制删除运行中的容器(危险!) # 拷贝文件 docker cp /host/path/file.txt mynginx:/container/path/ # 宿主机 -> 容器 docker cp mynginx:/container/path/log.txt /host/path/ # 容器 -> 宿主机

3. 使用 Dockerfile 构建自定义镜像这是 Docker 的核心技能。假设我们有一个简单的 Python Web 应用。

# 创建项目目录 mkdir mypythonapp && cd mypythonapp # 创建应用文件 app.py cat > app.py << 'EOF' from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return "Hello, Docker & K8S from Python Flask!\n" if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) EOF # 创建依赖文件 requirements.txt cat > requirements.txt << 'EOF' Flask==2.3.3 EOF # 创建 Dockerfile cat > Dockerfile << 'EOF' # 使用官方 Python 轻量级镜像作为基础 FROM python:3.11-alpine # 设置工作目录 WORKDIR /app # 复制依赖文件并安装 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY . . # 声明容器运行时暴露的端口 EXPOSE 5000 # 定义容器启动命令 CMD ["python", "app.py"] EOF # 构建镜像 docker build -t my-python-app:1.0 . # 运行自定义镜像的容器 docker run -d -p 5000:5000 --name myapp my-python-app:1.0 # 访问应用 curl http://localhost:5000 # 应输出:Hello, Docker & K8S from Python Flask!

4. 使用 docker-compose 编排多容器应用对于需要多个容器协作的应用(如 Web + 数据库),使用 docker-compose 更方便。

# docker-compose.yml version: '3.8' services: web: build: . # 使用当前目录的 Dockerfile 构建 ports: - "5000:5000" depends_on: - db environment: - DATABASE_URL=postgresql://user:password@db:5432/mydb networks: - app-network db: image: postgres:15-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: password POSTGRES_DB: mydb volumes: - postgres-data:/var/lib/postgresql/data networks: - app-network volumes: postgres-data: networks: app-network: driver: bridge

运行:docker-compose up -d;停止:docker-compose down

4. Kubernetes (K8S) 单节点集群搭建与核心概念

掌握了 Docker,我们就可以进军 K8S 了。生产环境通常是多节点集群,但对于学习和开发测试,一个单节点集群(All-in-One)完全足够。我们将使用kubeadm这个官方工具来搭建。

4.1 安装前系统配置

这些步骤至关重要,很多安装失败都源于此。

# 1. 关闭交换分区(K8S 1.8+ 要求) sudo swapoff -a # 永久关闭:编辑 /etc/fstab,注释掉所有包含 swap 的行,然后重启。 # 2. 设置主机名(可选,但有助于识别) sudo hostnamectl set-hostname k8s-master # 修改 /etc/hosts,确保主机名能解析到本机IP # 例如:192.168.1.100 k8s-master # 3. 允许 iptables 检查桥接流量 cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf br_netfilter EOF cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 EOF sudo sysctl --system

4.2 安装容器运行时和 K8S 组件

K8S 本身不直接运行容器,它通过 CRI (Container Runtime Interface) 调用容器运行时。我们将使用 Docker 安装时已经集成的containerd

# 1. 安装 containerd 的配置工具(如果尚未安装) sudo apt install -y containerd # 2. 生成 containerd 的默认配置文件 sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml # 3. 修改配置文件,使用 systemd 作为 cgroup 驱动(与 K8S 保持一致) sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml # 4. 重启 containerd sudo systemctl restart containerd sudo systemctl enable containerd # 5. 安装 kubeadm, kubelet, kubectl # 添加 Kubernetes 阿里云镜像源 sudo apt install -y apt-transport-https ca-certificates curl curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list # 安装指定版本(避免使用最新版可能带来的兼容性问题) sudo apt update sudo apt install -y kubelet=1.28.2-00 kubeadm=1.28.2-00 kubectl=1.28.2-00 sudo apt-mark hold kubelet kubeadm kubectl # 阻止自动更新 # 6. 初始化 Master 节点(单节点集群) # 注意:将 <MASTER_IP> 替换为你本机的实际 IP 地址 sudo kubeadm init \ --apiserver-advertise-address=<MASTER_IP> \ --image-repository registry.aliyuncs.com/google_containers \ --kubernetes-version v1.28.2 \ --service-cidr=10.96.0.0/12 \ --pod-network-cidr=10.244.0.0/16 # 初始化成功后会输出类似以下信息,请务必保存好最后的 kubeadm join 命令(虽然单节点用不上): # kubeadm join 192.168.1.100:6443 --token xxxxxx.xxxxxxxxxxxxxx \ # --discovery-token-ca-cert-hash sha256:xxxxxxxx... # 7. 配置 kubectl(普通用户) mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config # 8. 安装 Pod 网络插件(CNI) # 这是 K8S 集群的“神经系统”,负责 Pod 间的通信。这里安装最常用的 Flannel。 kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml # 等待所有 Pod 变为 Running 状态 kubectl get pods --all-namespaces -w # 看到 kube-flannel-* 和 coredns-* 都 Running 即可。

4.3 K8S 核心概念与对象

在 K8S 中,一切皆对象。通过 YAML 文件定义对象的期望状态,K8S 会努力让实际状态与之匹配。

  1. Pod:K8S 的最小调度单元。一个 Pod 可以包含一个或多个紧密关联的容器(如主容器和 Sidecar 容器),它们共享网络和存储空间。
  2. Deployment:用于部署无状态应用。它管理一组相同的 Pod(称为 ReplicaSet),并提供滚动更新、回滚等功能。
  3. Service:定义一组 Pod 的访问策略。为 Pod 提供一个稳定的 IP 地址和 DNS 名称,并实现负载均衡。
  4. Namespace:虚拟集群,用于在物理集群中划分多个虚拟环境,实现资源隔离(如 dev, test, prod)。
  5. ConfigMap & Secret:用于将配置信息和敏感数据(如密码)与容器镜像解耦。

4.4 第一个 K8S 应用:部署 Nginx

让我们用 kubectl 命令和 YAML 文件两种方式部署一个 Nginx。

方式一:使用kubectl run命令(快速测试)

# 创建一个名为 my-nginx 的 Deployment,使用 nginx 镜像 kubectl create deployment my-nginx --image=nginx:alpine # 将 Deployment 暴露为一个 Service(NodePort 类型,便于从集群外访问) kubectl expose deployment my-nginx --type=NodePort --port=80 # 查看资源状态 kubectl get deployments kubectl get pods kubectl get services # 获取 NodePort 端口号 kubectl get svc my-nginx -o jsonpath='{.spec.ports[0].nodePort}' # 假设输出是 31876,则在浏览器访问 http://<你的服务器IP>:31876

方式二:使用 YAML 文件(推荐,可版本控制)

# nginx-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 2 # 运行 2 个 Pod 副本 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:alpine ports: - containerPort: 80 --- # nginx-service.yaml (也可以和上面写在一个文件里,用 --- 分隔) apiVersion: v1 kind: Service metadata: name: nginx-service spec: selector: app: nginx # 选择标签为 app: nginx 的 Pod ports: - protocol: TCP port: 80 # Service 对内的端口 targetPort: 80 # Pod 容器的端口 nodePort: 30080 # 集群外访问的端口 (范围 30000-32767) type: NodePort

应用配置:

kubectl apply -f nginx-deployment.yaml kubectl apply -f nginx-service.yaml # 或合并执行:kubectl apply -f .

5. 深入实战:在 K8S 中部署有状态应用(MySQL)

无状态应用(如 Nginx)的 Pod 可以随意创建和销毁。有状态应用(如数据库)则需要持久化存储和稳定的网络标识。我们使用StatefulSetPersistentVolume (PV)/PersistentVolumeClaim (PVC)来部署 MySQL。

5.1 创建持久化存储

首先,我们创建一个本地目录作为存储(生产环境请使用网络存储如 NFS、Ceph、云盘等)。

# 在宿主机上创建存储目录 sudo mkdir -p /data/mysql sudo chmod 777 /data/mysql # 简化权限,生产环境需严格设置

然后,创建 PV 和 PVC 的 YAML 文件。

# mysql-pv-pvc.yaml apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce # 单节点读写 hostPath: path: /data/mysql --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi

应用:kubectl apply -f mysql-pv-pvc.yaml

5.2 创建 ConfigMap 存储配置

将 MySQL 的配置文件从镜像中分离。

# mysql-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: mysql-config data: my.cnf: | [mysqld] character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci default-authentication-plugin=mysql_native_password max_connections=1000

5.3 创建 Secret 存储密码

敏感信息必须用 Secret。

# 使用 kubectl 命令创建 Secret(密码会经过 base64 编码) kubectl create secret generic mysql-secret \ --from-literal=root-password=MyStrongPassword123!

5.4 创建 MySQL StatefulSet 和 Service

# mysql-statefulset.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: mysql-service # 必须有,用于提供稳定的 DNS replicas: 1 # 单实例 MySQL,生产环境可考虑主从 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:8.0 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: root-password ports: - containerPort: 3306 name: mysql volumeMounts: - name: mysql-data mountPath: /var/lib/mysql - name: mysql-config mountPath: /etc/mysql/conf.d volumes: - name: mysql-config configMap: name: mysql-config volumeClaimTemplates: # StatefulSet 特有的,为每个 Pod 动态创建 PVC - metadata: name: mysql-data spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 1Gi --- apiVersion: v1 kind: Service metadata: name: mysql-service spec: selector: app: mysql ports: - port: 3306 targetPort: 3306 clusterIP: None # Headless Service,用于 StatefulSet 的 DNS 解析

应用所有配置:

kubectl apply -f mysql-configmap.yaml kubectl apply -f mysql-statefulset.yaml

5.5 验证与连接

# 查看 Pod 状态 kubectl get pods -l app=mysql -w # 等待状态变为 Running # 查看 PVC 绑定状态 kubectl get pvc # 进入 MySQL Pod 执行命令 kubectl exec -it mysql-0 -- mysql -uroot -pMyStrongPassword123! # 或者在集群内其他 Pod 中,通过 Service 名连接 # mysql -h mysql-service -uroot -p

6. 常见问题与排查思路

在学习和使用 Docker 与 K8S 的过程中,你一定会遇到各种问题。以下是高频问题排查指南。

问题现象可能原因排查思路与解决方案
Docker 命令报错Got permission denied当前用户不在docker用户组。1.sudo usermod -aG docker $USER
2.注销并重新登录(或执行newgrp docker)。
docker pull速度极慢或超时默认 Docker Hub 镜像源在国内访问慢。配置国内镜像加速器(见 3.2 节/etc/docker/daemon.json)。
kubeadm init卡在pull image或失败无法拉取k8s.gcr.io镜像。1. 使用--image-repository参数指定阿里云等国内镜像源。
2. 或提前用docker pull拉取镜像并打标签。
kubectl get pods显示PendingPod 无法被调度到节点。1.kubectl describe pod <pod-name>查看事件。
2. 常见原因:资源不足、节点有污点(Taint)、未安装网络插件。
kubectl get pods显示ImagePullBackOff无法拉取容器镜像。1.kubectl describe pod查看具体错误。
2. 检查镜像名称拼写、镜像仓库权限、网络。
kubectl get pods显示CrashLoopBackOff容器启动后立即退出。1.kubectl logs <pod-name>查看容器日志。
2. 检查应用配置、依赖、启动命令、端口冲突。
Pod 间网络不通Pod 网络插件(CNI)未正常工作。1.kubectl get pods -n kube-system检查kube-flannel-*等 CNI Pod 状态。
2. 查看 CNI Pod 日志:kubectl logs -n kube-system <cni-pod-name>
Service 无法通过 NodePort 访问防火墙未放行端口、节点 IP 错误。1. 检查服务器防火墙(如ufw)是否允许 NodePort 范围(30000-32767)。
2.curl http://<节点内网IP>:<NodePort>测试。
kubectl命令报错The connection to the server was refusedKubernetes API Server 未运行或配置错误。1.sudo systemctl status kubelet检查 kubelet 状态。
2. 检查$HOME/.kube/config文件是否存在且内容正确。
3. 确认kubeadm init已成功完成。
磁盘空间不足容器镜像、日志、未清理的停止容器占用空间。1.docker system df查看 Docker 磁盘使用。
2.docker system prune -a清理(谨慎,会删除未使用的镜像)。
3. 清理 K8S 日志:journalctl --vacuum-time=7d

通用排查命令

  • kubectl describe <资源类型> <资源名>:查看资源的详细状态和事件,是排错第一选择。
  • kubectl logs <pod-name> [-c <container-name>]:查看 Pod 或指定容器的日志。
  • kubectl exec -it <pod-name> -- /bin/sh:进入 Pod 内部调试。
  • kubectl get events --sort-by=.metadata.creationTimestamp:查看集群级别的事件。

7. 最佳实践与工程建议

将技术用于生产环境,必须考虑稳定性、安全性和可维护性。

7.1 Docker 最佳实践

  1. 使用多阶段构建:对于编译型语言(如 Go, Java),在第一个阶段编译,在第二个仅包含运行环境的阶段拷贝二进制文件,极大减小镜像体积。
    # 以 Go 应用为例 FROM golang:1.20 AS builder WORKDIR /app COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -o myapp . FROM alpine:latest WORKDIR /root/ COPY --from=builder /app/myapp . CMD ["./myapp"]
  2. 使用.dockerignore文件:避免将node_modules,.git, 日志等不必要的文件拷贝进镜像,加速构建并减小体积。
  3. 以非 root 用户运行容器:在 Dockerfile 中创建并使用非 root 用户,增强安全性。
    RUN addgroup -g 1000 appuser && adduser -u 1000 -G appuser -s /bin/sh -D appuser USER appuser
  4. 明确指定镜像标签:避免使用latest标签,应指定具体版本号(如nginx:1.25-alpine),保证环境一致性。
  5. 限制容器资源:使用-m,--cpus等参数限制容器内存和 CPU 使用,防止单个容器耗尽主机资源。

7.2 Kubernetes 最佳实践

  1. 使用 Namespace 隔离环境:为开发、测试、生产环境创建不同的命名空间。
    kubectl create namespace dev kubectl create namespace prod kubectl config set-context --current --namespace=dev # 切换当前上下文命名空间
  2. 为 Pod 设置资源请求和限制:这是 K8S 进行合理调度和防止资源争抢的基础。
    resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
  3. 使用 Readiness 和 Liveness 探针:确保流量只被发送到已准备好的 Pod,并能自动重启不健康的 Pod。
    livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5
  4. 将配置与镜像分离:永远不要将配置文件、密码等硬编码在镜像中。使用 ConfigMap 和 Secret,并通过环境变量或卷挂载注入容器。
  5. 制定更新策略:在 Deployment 中配置strategy,实现零停机的滚动更新。
    strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # 更新过程中可以超出期望 Pod 数的最大值 maxUnavailable: 0 # 更新过程中不可用 Pod 的最大数量
  6. 做好日志与监控:集群层面部署 EFK (Elasticsearch, Fluentd, Kibana) 或 Loki 日志系统,以及 Prometheus + Grafana 监控系统。

7.3 云计算运维视角

从运维角度看,Docker 和 K8S 带来了基础设施即代码 (IaC) 和 GitOps 的实践。

  • 版本化一切:将 Dockerfile、K8S YAML、Helm Charts 纳入 Git 仓库管理。
  • CI/CD 流水线:将镜像构建、安全扫描、推送仓库、部署到 K8S 的过程自动化。
  • 不可变基础设施:一旦部署,不再直接登录容器修改配置。任何变更都应通过更新镜像或 ConfigMap,然后重新部署来实现。
  • 关注安全:定期扫描镜像漏洞、使用 Pod 安全策略、管理好 RBAC 权限、保护 etcd 数据。

8. 总结与学习路线

通过本文,你应该已经完成了一个从零到一的 Docker 与 Kubernetes 实战旅程:从 Linux 基础、Docker 安装与镜像构建,到 K8S 单节点集群搭建、核心对象操作,再到部署有状态的 MySQL 应用。我们不仅涵盖了操作步骤,更深入探讨了排错方法和生产级的最佳实践。

下一步学习建议

  1. 深入 K8S 核心概念:学习Ingress(七层负载均衡)、ConfigMap/Secret高级用法、RBAC(权限控制)、Helm(包管理)。
  2. 搭建多节点集群:尝试使用kubeadm添加 Worker 节点,理解集群高可用架构。
  3. 体验云厂商托管服务:在阿里云 ACK、腾讯云 TKE、华为云 CCE 上创建托管集群,体会云原生的便捷。
  4. 学习服务网格:了解IstioLinkerd,这是处理微服务间通信、安全、可观测性的下一代技术。
  5. 参与实际项目:将你的个人项目或公司的一个非核心服务容器化并部署到 K8S,这是最好的学习方式。

技术的道路很长,但每一步都算数。容器化和云原生不是银弹,但它们确实是构建现代可扩展、高可用应用架构的基石。希望这份教程能成为你探索这个广阔领域的坚实起点。如果在实践中遇到新的问题,欢迎随时回顾文中的排查思路,或查阅官方文档。动手去做,遇到问题解决问题,才是掌握技术的唯一捷径。

🚀 30+款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度