一课一得:容器云部署与应用实践总结
本文是笔者学习容器云部署与应用课程后的一课一得总结,结合课程理论与实操练习,从容器云基础概念出发,梳理了 Docker 镜像构建、容器编排、Kubernetes 集群部署与应用上线的完整流程,并记录了实操过程中的踩坑与优化心得,希望能给同样入门容器云的同学提供参考。
一、前言:为什么要学习容器云?
在学习容器云之前,我对 “部署应用” 的认知还停留在 “服务器装环境、上传代码、配置依赖、启动服务” 的传统模式里。这种方式的痛点非常明显:
- 环境不一致:本地开发能跑,到测试 / 生产环境就因为依赖版本、系统配置差异报错,也就是经典的 “在我电脑上能跑” 问题;
- 部署效率低:新服务器部署一个应用要花几小时装依赖、配置环境,扩容更是麻烦;
- 资源浪费:传统虚拟机部署每个应用都要占用独立的操作系统资源,硬件利用率低;
- 运维复杂:多应用、多实例的管理、扩缩容、故障恢复全靠人工,效率低还容易出错。
而容器云技术,正是为了解决这些问题而生的。本次课程从 Docker 容器技术入门,延伸到 Kubernetes 容器编排,让我从 0 到 1 完成了容器化应用的构建、部署与管理,也对 “容器化” 的价值有了更深刻的理解。
二、容器云核心基础概念梳理
2.1 容器是什么?和虚拟机有什么区别?
很多新手容易把容器和虚拟机搞混,这里我整理了两者的核心区别:
表格
| 特性 | 虚拟机(VM) | 容器(Container) |
|---|---|---|
| 隔离方式 | 硬件级隔离,每个 VM 有独立的操作系统内核 | 操作系统级隔离,共享宿主机内核,通过 Namespace 和 Cgroups 实现资源隔离 |
| 资源占用 | 每个 VM 都要运行完整的操作系统,占用 GB 级内存 / 磁盘 | 仅运行应用及其依赖,占用 MB 级资源,启动速度秒级 |
| 启动速度 | 分钟级(启动操作系统) | 秒级(直接启动容器进程) |
| 移植性 | 依赖宿主机虚拟化平台,镜像体积大,移植成本高 | 镜像包含所有依赖,一次构建、到处运行,移植成本极低 |
简单来说,容器是打包了应用代码、运行时、依赖库、配置文件的标准化单元,它不包含完整的操作系统,所以更轻量、启动更快、资源利用率更高。
2.2 容器云是什么?Docker 和 K8s 的角色分工
很多同学会把 Docker、K8s、容器云混为一谈,其实它们的定位是不同的:
- Docker:是容器技术的实现之一,提供了容器的创建、运行、镜像构建等基础能力,相当于 “容器的 runtime 工具”,解决了单个容器的打包与运行问题;
- Kubernetes(简称 K8s):是容器编排平台,解决大规模容器集群的管理问题,比如多容器调度、自动扩缩容、故障自愈、负载均衡等,相当于 “容器集群的操作系统”;
- 容器云:是基于容器技术构建的云原生平台,结合了容器 runtime、编排、网络、存储、监控等能力,为应用提供标准化的部署、运行与运维环境,是一套完整的解决方案。
三、Docker 实操:从镜像构建到容器运行
这部分是本次课程的实操重点,我以 CentOS 7 为例,完成了从 Docker 安装到自定义镜像构建、多容器编排的完整流程。
3.1 Docker 安装与基础配置
1. 安装 Docker(CentOS 7)
bash
运行
# 卸载旧版本Docker
yum remove -y docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine
# 安装依赖包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加阿里云Docker YUM源(国内推荐,速度更快)
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装Docker CE
yum install -y docker-ce docker-ce-cli containerd.io
# 启动Docker并设置开机自启
systemctl start docker
systemctl enable docker
# 验证安装是否成功(会输出Docker版本信息)
docker --version
docker run hello-world
2. 配置 Docker 镜像加速器(必做,否则拉取镜像很慢)
编辑/etc/docker/daemon.json文件,添加阿里云镜像加速器(需注册阿里云账号获取专属加速器地址):
bash
运行
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
# 重启Docker生效配置
systemctl daemon-reload
systemctl restart docker
3.2 镜像操作:拉取、构建与推送
1. 拉取公共镜像
从 Docker Hub 拉取官方 Nginx 和 MySQL 镜像:
bash
运行
# 拉取指定版本的Nginx镜像
docker pull nginx:1.25-alpine
# 拉取MySQL 8.0镜像
docker pull mysql:8.0
# 查看本地镜像列表
docker images
2. 构建自定义镜像:Python Flask 应用 Docker 化
这里我写了一个简单的 Python Flask 应用,然后通过 Dockerfile 构建镜像,实现 “一次构建,到处运行”。
第一步:编写 Flask 应用代码(app.py)
python
运行
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, Container Cloud! This is my first Dockerized Flask App."
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
第二步:编写 Dockerfile
dockerfile
# 基础镜像:使用轻量级的Python 3.9 slim镜像,减少镜像体积
FROM python:3.9-slim
# 设置工作目录
WORKDIR /app
# 复制requirements.txt到容器中
COPY requirements.txt .
# 安装Python依赖(--no-cache-dir减少镜像体积)
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码到容器中
COPY app.py .
# 暴露容器端口
EXPOSE 5000
# 容器启动命令
CMD ["python", "app.py"]
requirements.txt 文件
txt
flask==2.3.3
第三步:构建镜像并运行容器
bash
运行
# 构建镜像,命名为flask-app:v1
docker build -t flask-app:v1 .
# 运行容器,映射宿主机8080端口到容器5000端口
docker run -d -p 8080:5000 --name flask-demo flask-app:v1
# 访问测试:curl宿主机IP:8080,会输出Hello, Container Cloud!
curl localhost:8080
💡 小贴士:构建镜像时尽量使用alpine或slim版本的基础镜像,避免使用完整的操作系统镜像,可以大幅减少镜像体积(比如 python:3.9-slim 只有几百 MB,而 python:3.9 完整版有几 GB)。
3. 推送镜像到阿里云镜像服务(私有仓库)
为了后续在 K8s 中使用自定义镜像,我把构建好的镜像推送到了阿里云镜像服务:
bash
运行
# 登录阿里云镜像仓库
docker login --username=你的阿里云账号 registry.cn-hangzhou.aliyuncs.com
# 给镜像打标签(格式:registry地址/命名空间/仓库名:标签)
docker tag flask-app:v1 registry.cn-hangzhou.aliyuncs.com/你的命名空间/flask-app:v1
# 推送镜像到仓库
docker push registry.cn-hangzhou.aliyuncs.com/你的命名空间/flask-app:v1
3.3 容器操作与数据持久化
容器默认是无状态的,容器删除后数据会丢失,所以关键数据必须挂载到宿主机或外部存储实现持久化。这里以 MySQL 容器为例,演示数据卷挂载:
bash
运行
# 创建宿主机数据目录
mkdir -p /data/mysql
# 运行MySQL容器,挂载数据目录、配置文件和日志目录
docker run -d \
--name mysql-demo \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-v /data/mysql:/var/lib/mysql \
-v /etc/mysql/conf.d:/etc/mysql/conf.d \
mysql:8.0
# 验证数据持久化:删除容器后,重新运行容器并挂载同一个目录,数据不会丢失
docker stop mysql-demo
docker rm mysql-demo
# 重新运行容器,挂载同一个/data/mysql目录,之前创建的数据库依然存在
3.4 Docker Compose:多容器应用编排
手动运行多个容器时,需要逐个配置端口、依赖、网络,非常麻烦,Docker Compose 可以通过 YAML 文件定义多容器应用的配置,一键启动 / 停止所有服务。这里我用 Docker Compose 部署了一个 WordPress+MySQL 的博客应用:
docker-compose.yml 文件
yaml
version: '3.8'
services:
db:
image: mysql:8.0
volumes:
- db_data:/var/lib/mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: wordpress
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
wordpress:
depends_on:
- db
image: wordpress:latest
ports:
- "8000:80"
restart: always
environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data:
启动与管理应用
bash
运行
# 启动所有服务(后台运行)
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看服务日志
docker-compose logs -f wordpress
# 停止并删除服务(包括容器、网络,不删除数据卷)
docker-compose down
访问宿主机 IP:8000,就能看到 WordPress 的安装界面,整个部署过程只需要一条命令,非常方便。
四、Kubernetes 基础:单节点集群部署与应用上线
Docker 解决了单个容器的运行问题,但大规模容器集群的管理(比如自动扩缩容、故障自愈、负载均衡)需要 Kubernetes 来实现。本次课程我用 Minikube 搭建了单节点 K8s 集群,完成了应用的部署与测试。
4.1 Minikube 安装与启动(适合本地学习)
bash
运行
# 安装kubectl(K8s命令行工具)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/
# 安装Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube-linux-amd64
mv minikube-linux-amd64 /usr/local/bin/minikube
# 启动Minikube(使用Docker作为驱动,国内用户推荐配置镜像源)
minikube start --driver=docker --image-mirror-country=cn --kubernetes-version=v1.28.3
# 验证集群状态
kubectl cluster-info
kubectl get nodes
4.2 K8s 核心概念快速理解
- Pod:K8s 中最小的调度单元,一个 Pod 可以包含一个或多个容器(比如应用容器 + 日志采集容器),Pod 共享网络和存储资源;
- Deployment:负责管理 Pod 的副本,比如定义运行 3 个 Nginx Pod 副本,当某个 Pod 故障时,Deployment 会自动创建新的 Pod 替换它,实现故障自愈;
- Service:为一组 Pod 提供统一的访问入口,实现负载均衡,支持 ClusterIP(集群内访问)、NodePort(宿主机端口访问)、LoadBalancer(云厂商负载均衡)等类型;
- Namespace:集群内的资源隔离单元,可以用来划分不同的环境(比如 dev、test、prod)。
4.3 部署 Nginx 应用到 K8s 集群
1. 编写 Deployment 配置文件(nginx-deployment.yaml)
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # 运行3个Nginx Pod副本
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
2. 编写 Service 配置文件(nginx-service.yaml)
yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx # 匹配Deployment中Pod的标签
type: NodePort # 暴露为宿主机端口访问
ports:
- protocol: TCP
port: 80 # Service的端口
targetPort: 80 # Pod的端口
nodePort: 30080 # 宿主机端口(范围30000-32767)
3. 部署应用并验证
bash
运行
# 应用Deployment配置
kubectl apply -f nginx-deployment.yaml
# 应用Service配置
kubectl apply -f nginx-service.yaml
# 查看Pod状态(确保所有Pod处于Running状态)
kubectl get pods -o wide
# 查看Service状态
kubectl get svc
# 访问测试:通过Minikube节点IP+NodePort访问Nginx
minikube ip # 获取Minikube节点IP
curl http://$(minikube ip):30080
4.4 部署自定义 Flask 应用到 K8s
把之前推送到阿里云镜像仓库的 Flask 应用部署到 K8s 集群,这里我把镜像设为公开的,直接拉取:
flask-deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: flask-deployment
spec:
replicas: 2
selector:
matchLabels:
app: flask
template:
metadata:
labels:
app: flask
spec:
containers:
- name: flask-app
image: registry.cn-hangzhou.aliyuncs.com/你的命名空间/flask-app:v1
ports:
- containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
name: flask-service
spec:
selector:
app: flask
type: NodePort
ports:
- port: 5000
targetPort: 5000
nodePort: 30081
部署并访问:
bash
运行
kubectl apply -f flask-deployment.yaml
kubectl get pods
curl http://$(minikube ip):30081
五、实操踩坑与优化心得(一课一得核心)
这部分是我在实操过程中遇到的问题和解决方法,也是本次课程最大的收获:
坑 1:Docker 容器启动后马上退出
- 现象:运行容器后,
docker ps看不到容器,docker ps -a显示容器状态为 Exited; - 原因:容器的主进程退出了,比如 Python 应用后台运行、Nginx 以 daemon 模式运行,容器会认为进程结束而退出;
- 解决方法:让容器的主进程在前台运行。比如 Nginx 启动时加上
-g 'daemon off;',Python 应用不要用&后台运行,直接前台启动。
坑 2:K8s 的 Pod 一直处于 Pending 状态
- 现象:Pod 状态为 Pending,
kubectl describe pod显示调度失败; - 原因:集群资源不足(CPU / 内存不够)、没有匹配的节点标签、镜像拉取失败;
- 解决方法:用
kubectl describe pod <pod-name>查看事件日志,根据提示排查问题,比如 Minikube 启动时分配更多内存,或者使用国内镜像源。
坑 3:Docker 镜像体积过大,拉取速度慢
- 现象:构建的镜像有几 GB,推送到仓库和拉取都很慢;
- 优化方法:
- 使用轻量级基础镜像(alpine/slim);
- 多阶段构建:把构建过程和运行环境分开,比如用 Go/Python 构建应用,只把可执行文件复制到运行镜像中;
- 清理构建缓存:比如
apt-get clean、pip install --no-cache-dir; - 合并 RUN 指令:减少镜像层数(Docker 镜像分层存储,每个 RUN 指令会生成一个新层)。
心得 1:容器化不是 “银弹”
不是所有应用都适合容器化,比如小型单体应用,用 Docker Compose 部署就足够了,没必要上 K8s;容器化的核心价值在于标准化和编排,适合微服务、云原生架构的应用。
心得 2:理解概念比敲命令更重要
刚开始学的时候,我只会跟着教程敲命令,遇到问题就懵了。后来才明白,只有理解了 Namespace、Cgroups、Pod、Deployment 这些概念的本质,才能快速定位问题,而不是只会复制粘贴命令。
心得 3:镜像安全很重要
不要使用来源不明的公共镜像,尽量自己构建镜像;不要在镜像中存放敏感信息(比如密码、密钥),可以用 K8s 的 Secret 或 ConfigMap 来管理配置;定期更新镜像的基础镜像,修复安全漏洞。
六、容器云的应用场景与未来学习方向
6.1 容器云的典型应用场景
- 微服务部署:把单体应用拆分成多个微服务,每个微服务打包成容器,独立部署、升级、扩缩容;
- CI/CD 集成:容器镜像作为 CI/CD 的交付产物,实现 “构建一次,到处部署”,简化发布流程;
- 弹性伸缩:根据业务流量自动调整容器实例数量,比如电商大促时自动扩容,流量低峰时缩容,节省资源;
- 混合 / 多云部署:容器镜像不依赖底层基础设施,可以轻松在公有云、私有云、本地数据中心之间迁移;
- DevOps 实践:开发、测试、生产环境都使用相同的容器镜像,消除环境差异,实现开发运维一体化。
6.2 后续学习方向
本次课程只是入门了容器云的基础,后续我打算深入学习:
- K8s 的高级特性:Ingress、持久化存储(PV/PVC)、StatefulSet(有状态应用部署)、监控告警(Prometheus+Grafana);
- CI/CD 工具与容器集成:Jenkins、GitLab CI,实现代码提交后自动构建镜像、部署到 K8s;
- 容器安全:镜像扫描、容器运行时安全、RBAC 权限控制;
- 云原生生态:服务网格(Istio)、无服务器架构(Knative)等。
七、总结
通过本次容器云部署与应用课程的学习和实操,我从一个 “只会手动部署应用” 的新手,掌握了 Docker 容器化、Kubernetes 基础编排的核心技能,也深刻体会到了容器云技术在解决环境一致性、提升部署效率、简化运维管理方面的巨大价值。
“一课一得” 的核心不在于学会多少命令,而在于理解技术背后的设计思想,以及解决实际问题的能力。在后续的学习和实践中,我会继续深入云原生领域,把学到的知识应用到实际项目中,真正做到学以致用。

更多推荐
所有评论(0)