十二.运行容器
1.容器概念
1.1容器技术介绍
应用程序的运行依赖于"运行时环境"(runtime environment),包括库、配置文件、服务等
1.1.1传统模式的"依赖困境"
(1)依赖与系统强绑定
应用程序的"运行时环境"运行在物理主机 或虚拟机上的操作系统 中,应用程序依赖项与该操作系统 一起安装在主机上 的操作系统中。
示例:
在物理机上部署一个 Java 应用,需要的 JDK、依赖库会直接安装在主机的 OS 里。
(2)RPM的依赖管理能力
RHEL通过RPM包管理器来管理依赖;
如:
安装httpd(Apache 服务)时,RPM 会自动检查并安装所需的依赖库,确保应用能正常运行。但这只解决了同一系统内 的依赖兼容问题,无法应对更复杂的场景。
(3)版本冲突
应用可能需要与操作系统预装版本不同的软件;
或
同一系统上的两个应用,可能需要同一软件的不兼容版本(比如应用 A 需要 MySQL 5.7,应用 B 需要 MySQL 8.0)。
1.1.2容器的特性
容器是应对传统部署困境的技术方案 ,核心特性是"隔离 " 和 "打包":
(1)隔离性:进程 与内容 的双重隔离
容器是"进程的集合 ":容器内的进程与 主机系统、其他容器的进程相互隔离;
容器的"内容隔离":每个容器的文件、配置、依赖都是独立的,不会与其他容器或主机系统产生冲突。
示例:
容器 A 装了 Python 3.9,容器 B 装了 Python 3.6,两者互不影响。
(2)打包性:简化部署与管理
容器将应用程序 + 所有依赖(库、配置、运行时) 打包成一个独立单元。
无论部署到哪台主机,只要主机支持容器运行 ,应用 就能 "开箱即用",彻底解决了 "环境不一致导致的部署失败" 问题。
(3)RHEL 实现容器依赖三大核心技术
Control Groups(CGroups,控制组):
限制 容器的资源使用(比如 CPU、内存配额)。
Namespaces(命名空间):
实现 进程、网络、文件系统等层面的隔离,让容器"误以为"自己是独立系统。
SELinux/Seccomp:
强化 容器的安全性,防止容器内进程越权访问主机资源。
1.2 容器与虚拟化的对比
简言之,虚拟化是"虚拟出完整的机器 ",容器是"虚拟出应用的运行环境"。
1.2.1虚拟机:
虚拟机是"硬件级虚拟化 ",通过 hypervisor (虚拟化层 ,如 KVM、VMware ESXi)将物理硬件拆分 为多个 "虚拟硬件",每个虚拟机都运行完整的 Guest OS(客户机操作系统),再在 Guest OS 上部署应用。
1.2.2容器
容器是"操作系统级虚拟化 ",直接运行在主机操作系统内核上,通过 Namespaces(进程 / 网络隔离)、cgroups(资源限制)等技术实现进程级隔离,无需独立的 Guest OS。
|------------|----------------------|---------------------|
| 对比 | 容器(操作系统级虚拟化) | 虚拟机(硬件级虚拟化) |
| 虚拟化层 | 直接运行在主机内核上 | 通过 hypervisor 虚拟硬件 |
| 操作系统 | 共享主机内核,无独立 OS | 每个虚拟机含完整 Guest OS |
| 资源占用 | 轻量,启动快(毫秒级) | 重量级,启动慢(分钟级) |
| 隔离级别 | 进程级隔离 | 完全硬件隔离 |
1.3运行无根的容器
在容器主机上(虚拟服务器),用户能以根用户(root用户)或普通用户运行容器;
1.3.1两种身份运行容器
(1)无根容器(rootless)
能以非特权用户运行的容器称为无根容器(rootless);
(2)rootful容器
以****根用户(root)****运行的容器,拥有主机1的最高权限;
1.3.2安全与限制
(1)无根容器的安全性
由于以普通用户身份运行,即使容器内的应用存在漏洞被攻击,攻击者也难以获取主机的root权限,大幅降低了 "容器漏洞影响主机系统" 的风险。
(2)无根容器的限制
最典型的限制是无法使用特权端口(1024 以下的端口) 提供网络服务。
示例:
若要让容器内的 Web 服务通过80端口(HTTP 默认特权端口)对外提供服务,无根容器因权限不足无法绑定该端口,需改用1024以上的端口(如8080)。
|------------|------------------------|-------------------------------|
| 特性 | 无根容器(rootless) | rootful 容器(root 用户运行) |
| 安全性 | 高,漏洞攻击不影响主机 root 权限 | 低,拥有主机最高权限 |
| 端口限制 | 无法使用 1024 以下特权端口 | 无端口限制 |
| 适用场景 | 普通业务服务(Web、应用程序) | 需特权操作的服务(系统工具) |
1.4 设计容器的架构
(1)可移植性:
容器可移植性好,可以容易的从一个环境转移到另一个环境;
示例:
开发人员在本地用容器运行 Java Web 应用,直接将容器镜像推送到生产服务器,无需在生产环境重新安装 JDK、Tomcat 等依赖,就能保证应用运行一致。
(2)版本化管理
可以保存容器的多个版本,根据需要快速访问每个版本;
示例:
电商系统的支付服务迭代到 v3 版本后出现漏洞,可立即切换回经过验证的 v2 镜像,保障业务连续性。
(3)临时与持久存储
容器本身是临时的------ 容器销毁后,其内部生成的临时数据(如运行日志、用户上传的临时文件)会丢失。因此需要将关键数据挂载到持久存储(如外部磁盘、云存储服务)中,确保数据永久保存。
示例:
MySQL 数据库容器运行时,需将数据目录挂载到宿主机的持久目录,即使容器被删除重建,数据库数据也不会丢失。
(4)节能性
容器通常在运行时启动 ,不需要时停止并删除容器 ,释放资源;下一次需要时 再启动新的容器,保证每次运行的环境纯净。
示例:
定时数据备份任务,每天凌晨启动一个容器执行备份脚本,任务完成后容器自动销毁,避免长期占用服务器资源。
(5)单一职责性
可以在单个容器 中安装 含有多个 服务的软件应用;
但这种方式会导致管理复杂度剧增------ 单个服务的更新、故障排查会牵连整个容器,甚至引发连锁故障。
示例:
一个容器同时运行 Nginx(Web 服务)、MySQL(数据库),若 MySQL 需要升级版本,可能会意外影响 Nginx 的配置,导致 Web 服务不可用。
优化设计:
在单独的容器 中运行每个组件 (如 Web 服务器、数据库、消息队列),每个容器只负责一个组件;这样每个组件可以独立更新、扩展、故障隔离,不会因单个组件的变动影响整个应用系统。
示例:
电商系统中,用户模块、订单模块、支付模块分别部署在独立容器中。当支付模块需要扩容以应对大促流量时,只需增加支付容器的实例数,不会影响用户模块和订单模块的运行。
1.5容器的管理工具
RHEL提供了一套容器工具,可以在单一服务器上运行多个容器:
(1)podman:管理容器和容器镜像(image)
(2)skopeo:检查、复制、删除和签名image
(3)Buildah:创建新的容器镜像
这些工具与开放容器倡议(OCI) 完全兼容。OCI 是行业公认的容器标准组织,定义了容器镜像格式和运行时规范。这意味着:
它们可以管理任何符合 OCI 标准的容器引擎(如 Docker)创建的 Linux 容器,实现跨工具、跨平台的容器生态互通,避免 "厂商锁定"。
示例:
用 Docker 构建的镜像,可通过 podman 直接运行;用 podman 构建的镜像,也能在 Docker 环境中正常启动。
1.6容器镜像和注册表
1.6.1容器镜像
容器镜像(Container Image )是容器技术的核心基石,本质是一个只读的 (不可更改) 、分层的 、可移植的文件系统模板 ------ 它打包了运行应用所需的所有依赖(代码、运行时、系统库、配置文件、环境变量等);
它的核心价值是 "一次构建,处处运行 "------ 无论在开发电脑、测试服务器还是生产环境,只要拉取同一个镜像 ,启动的容器环境完全一致,彻底解决环境差异问题。
它是容器运行的"蓝图"或"安装包",没有镜像就无法创建容器。
1.6.2容器注册表
容器注册表(registry)是存储、管理和分发容器镜像 的存储库 ,是容器生态中 "镜像共享与版本管理" 的核心基础设施,核心作用是连接镜像构建与容器运行:
(1)存储与检索:
开发者将本地构建的镜像 推送到注册表 ,用户再从注册表拉取镜像 到本地运行容器。
(2)类别:
公共注册表(Public Registry):
对外开放的镜像库 (如 Docker Hub),包含官方、社区维护的镜像,优势是资源丰富 ,劣势是镜像安全性需自行评估。
私有注册表:
企业自建的镜像库 (如红帽 Quay、Harbor),用于存储内部业务镜像,可通过权限控制、漏洞扫描确保镜像安全,适合敏感业务场景。
1.7容器镜像、注册表与容器的关系

简单比喻:
容器镜像 = 软件安装包(.exe/.dmg文件)
容器注册表 = 应用商店(App Store/软件仓库)
容器 = 正在运行的程序进程
1.8 配置容器registries
建议以普通用户管理容器,因此配置文件遵循 "用户级覆盖系统级"的规则:
(1)用户级配置
编辑文件:
$HOME/.config/containers/registries.conf(仅对当前用户生效,可自定义注册表行为)。
示例:


标准格式:

(2)系统级配置
/etc/containers/registries.conf(全局默认配置,所有用户继承)。
这种设计既保证了系统配置的统一性,又支持用户根据需求自定义注册表规则。
1.9 使用ContainerFile构建容器镜像
ContainerFile 是一个纯文本文件 ,包含了构建容器镜像 的所有指令(如基础镜像选择、依赖安装、启动命令等)。
生成的容器镜像由多个只读层组成 ,每一层对应 ContainerFile 中的一条指令。
1.10规模化容器管理
Kubernetes(K8s)是开源的容器编排平台,用于自动化容器化应用的部署、扩展、管理和运维,专为规模化管理容器而生,是大规模容器环境的"操作系统"。
管理:
(1)跨主机部署与管理:
可在多台容器主机 (节点)上统一 部署、管理容器,打破单主机的资源限制。
(2)服务发现与 DNS 管理:
新容器启动时自动更新 DNS,让容器间能通过 "服务名" 互相访问(无需硬编码 IP)。
(3)负载均衡:
将外部流量自动分发到多个容器实例,避免单容器过载。
(4)弹性伸缩:
支持"手动/自动调整容器数量"------ 比如根据 CPU 利用率自动扩容,应对流量高峰。
(5)健康检查与自愈:
支持用户定义的运行状态检查,监控容器状态,若容器故障则自动重启,保证服务可用性。
以上为容器技术的核心概念,后续将逐步展开容器的部署、资源管理与服务化配置。