openEuler 的容器支持是我在实际接触这个系统之后觉得最值得花一整章来梳理的部分。Docker 作为目前使用面最广的容器引擎在 openEuler 上部署和使用已经有非常成熟的路径而 iSulad 这个带着明显“原生”标签的轻量级容器运行时才是 openEuler 生态里真正有辨识度的技术点。这篇文章我会把两种引擎的安装、配置、真实使用体验和踩坑记录都整理出来适合刚接触 openEuler 的系统管理员也适合打算在云原生和边缘场景里做容器运行时选型的人。内容不追求面面俱到但会把关键的选择逻辑和操作细节讲透让你看完之后能直接在机器上动手复现。1. openEuler 的容器支持到底是怎么设计的1.1 容器能力在 openEuler 中的优先级openEuler 不是那种“顺手支持一下容器”的发行版。它的目标覆盖服务器、云计算、边缘计算和嵌入式场景而这些场景里现在跑的应用绝大多数都已经容器化了。操作系统要承担的任务很明确把 cgroup、namespace、OverlayFS、网络虚拟化这些底层能力打磨好让上层容器引擎能稳定运行。所以你会看到 openEuler 的内核配置和系统组件在容器方向上是做过专门适配的。我第一次在 openEuler 上部署容器环境时印象最深的一点是系统默认的防火墙、SELinux、内核模块和 Docker 配合得很顺没有出现其他发行版上那种“装完 Docker 还要关一堆安全策略才能跑”的尴尬情况。这背后其实是发行版团队在集成阶段做了大量验证工作。换句话说容器支持不是装个软件包就完事而是整个系统设计的一部分。同时openEuler 的资料体系里专门把容器列为一章并且同时讲 Docker 和 iSulad这个安排很容易被忽略。它表面上是文档并列背后其实在传递一个信号用户应该根据自己的场景选择合适的容器引擎而不是被某一种生态绑死。理解这个出发点后面的选型和配置逻辑就顺了。1.2 Docker 与 iSulad两条路线为什么同时存在Docker 的优势不用多讲生态成熟、资料多、工具链完整。对于大多数做应用部署、CI/CD 或者 Kubernetes 集群的人来说Docker 几乎是默认选项。openEuler 提供 Docker 的完整支持目的很纯粹让习惯 Docker 的用户能够平滑迁移过来不需要改工作习惯。iSulad 则完全是另一套思路。它用 C/C 实现设计目标是在保持 OCI 兼容的前提下把资源占用降到最低特别适合内存小、算力有限、启动要求快的边缘设备或者嵌入式网关场景。iSulad 在 openEuler 里的地位更像是平台真正原生的技术路线承载着内核对容器能力的深度整合。这两个引擎同时存在看起来像是重复造轮子但其实是满足了完全不同的需求Docker 解决通用生态问题iSulad 解决轻量化和深度集成问题。而且因为两者都遵循 OCI 镜像标准同一个镜像可以轻松地在两个引擎之间切换使用不会出现“换个引擎就得重新打包镜像”的麻烦。这一点在后面做引擎迁移时非常重要。2. Docker 在 openEuler 上的部署与配置细节2.1 安装前需要确认的三个前提先别急着敲安装命令建议先花两分钟确认一下当前系统的状态能省掉后面一大半的麻烦。第一是内核版本。openEuler 默认内核版本较新基本都满足 Docker 的运行要求。可以用uname -r确认一下重点看内核是否能正常支持 overlay2 存储驱动这决定后续容器分层文件系统的性能。第二是 cgroup 版本。openEuler 22.03 LTS 之后默认启用 cgroup v2。Docker 对 cgroup v2 的支持已经非常成熟但你如果是从老版本升级上来的要留意系统里是不是还残留 cgroup v1 的挂载配置。混用会引发一些非常隐蔽的资源限制失效问题。第三是磁盘分区的布局。Docker 默认把数据放在/var/lib/docker如果你只是用系统盘装一下、做测试那无所谓但如果是生产环境强烈建议给 Docker 单独准备一个数据盘或者至少把/var/lib/docker独立分区出来。原因后面讲存储驱动时会详细说。确认完这三件事就可以走安装了。2.2 安装与启动验证openEuler 的官方软件源里直接带了 Docker 相关组件不需要像其他某些发行版那样额外折腾第三方源。安装命令很简单dnf install -y docker systemctl enable --now docker安装完成后最重要的不是急着跑容器而是先看一遍docker info的输出docker info重点看几个字段Storage Driver、Cgroup Driver、Cgroup Version、Kernel Version。正常情况下openEuler 上 Storage Driver 应该是overlay2Cgroup Driver 建议是systemdCgroup Version 显示 2。这里多说一句 Cgroup Driver。如果你后续要在 openEuler 上自建 Kubernetes 集群kubelet 的 cgroup 驱动必须和 Docker 保持一致生产环境一般默认都用systemd。Docker 默认可能是cgroupfs所以通常需要手动改配置后面 daemon.json 里会有对应参数。2.3 daemon.json 的配置实践Docker 的核心配置集中在/etc/docker/daemon.json。这个文件常见的错误操作是要么不写等出问题再补要么一上来就甩一大堆参数根本没有验证过哪些是当前环境需要的。我建议的初始配置是这样{ data-root: /data/docker, exec-opts: [native.cgroupdriversystemd], log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, storage-driver: overlay2 }>systemctl daemon-reload systemctl restart docker docker info | grep -A 2 Storage Driver\|Cgroup Driver确认配置生效。如果你是在内网环境还需要增加镜像加速相关的配置项这个在后面的常见问题部分会细说。2.4 存储驱动选择与 overlay2 的坑Docker 在 openEuler 上的默认存储驱动就是 overlay2它是目前综合性能最好的选择镜像层复用效率高启动容器时创建可写层的开销很小。大部分场景下你不需要也不需要修改存储驱动。但 overlay2 有一个非常有名的前提条件底层文件系统必须支持d_type。如果底层文件系统不满足Docker 会直接拒绝启动错误信息类似ERROR: Failed to mount overlay: backing file system is unsupported for overlay mount这个错误非常容易出现在两个场景一是把 Docker 数据目录放在 XFS 文件系统上但分区格式化时没有开启ftype1二是放在某些精简配置的网络存储上。检查方法xfs_info /data | grep ftype如果你的数据盘是 XFS 分区xfs_info的输出里必须能看到ftype1。如果创建分区时用了默认参数有些环境会出现 ftype0那就只能重新格式化分区没有其他取巧的办法。注意生产环境格式化数据盘之前一定要确认分区上还没有重要数据。这个操作不可逆。3. iSuladopenEuler 原生的轻量容器引擎实战3.1 iSulad 的设计目标与技术底子iSulad 从名字上就能看出它和 openEuler 生态的绑定关系。这是一款用 C/C 实现的容器引擎开发初衷不是再造一个 Docker而是想在保持容器接口兼容的前提下把引擎本身降到极轻量级。为什么用 C/C因为容器的核心操作本质上就是对内核接口的封装比如 namespace 切换、cgroup 资源限制、OverlayFS 挂载这些操作在 C/C 层面可以直接高效地调用系统调用不需要像 Go 那样的运行时支持。最终效果就是iSulad 守护进程常驻内存占用比 Docker 低一个量级容器启动速度也快得多。iSulad 与镜像和容器标准是兼容的支持 OCI 规范、支持 Kubernetes 的 CRI 接口意味着它并不是一个“自娱自乐”的封闭实现。生产环境里iSulad 可以作为 Kubernetes 的容器运行时直接对接也能独立管理单机容器。它默认集成的轻量级容器运行时引擎即 LCRLightweight Container Runtime是内部实现的一部分当然也可以通过配置切换成外部的 runC。也就是说它保留了自定义的可扩展性。3.2 安装与启动在 openEuler 上安装 iSulad 同样非常简单dnf install -y iSulad systemctl enable --now isulad注意服务名是isulad不是iSulad输入命令时大小写别搞错。启动后先看状态systemctl status isulad isula infoisula info会显示 iSulad 的版本、存储驱动、运行时信息和 cgroup 配置。刚安装完默认状态通常是正常的但如果看到 daemon 连接失败大概率是服务没起来直接用journalctl -u isulad看日志。3.3 命令对照与基本使用iSulad 的命令设计和 Docker 高度相似很多场景下你几乎不需要翻文档就能猜对用法。常用命令对照如下docker ps对应isula psdocker images对应isula imagesdocker pull对应isula pulldocker run对应isula rundocker exec对应isula execdocker logs对应isula logsdocker inspect对应isula inspect比如启动一个简单的 Nginx 容器isula pull nginx:latest isula run -d --name web-test -p 8080:80 nginx:latest isula ps这个体验对熟悉 Docker 的人来说非常友好。不过 iSulad 的网络模型相对简朴默认没有 Docker 那种自带 bridge 网络的完整封装生产环境里一般要结合 CNI 来做网络规划这一点在使用中要有预期。3.4 配置文件与镜像管理要点iSulad 的主配置文件是/etc/isulad/daemon.json结构上部分设计有相似之处但参数名不完全一样。我常用的配置调整集中在日志和镜像仓库上{ log-driver: json-file, log-level: WARN, log-opts: { max-size: 100m, max-file: 3 } }日志滚动这个习惯我从 Docker 环境带过来的在 iSulad 上同样适用。iSulad 在日志量控制上如果一开始不限制时间长了也会产生大量的磁盘占用问题。镜像管理上iSulad 同样支持save、load操作离线环境下可以用isula save导出镜像再传到目标机器上isula load和 Docker 的迁移思路完全一致。另外当你需要把一个在 Docker 上构建好的镜像拿到 iSulad 里跑的时候不需要做任何转换操作因为镜像格式都是 OCI 标准导入导出全程通用这是我在实际项目里验证过的。提示如果你要把节点上的镜像全部迁移到另一台机器先压缩再传输可以大幅减少网络开销尤其在大镜像场景下效果明显。4. Docker 与 iSulad 怎么选关键对比和决策依据4.1 功能与接口层次的核心差异要回答“到底选 Docker 还是 iSulad”不能只看宣传口号得把关键功能罗列出来对比。对比维度DockeriSulad核心实现语言GoC/C常驻内存占用相对较高低OCI 镜像兼容是是网络默认模型内置 bridge 等完整模型更依赖 CNI 规划Kubernetes 对接需借助适配组件原生 CRI 支持生态工具链丰富成熟相对精简适用场景通用服务器、开发测试、复杂编排边缘设备、嵌入式、资源受限环境注意最后两行是核心区别。Docker 的优势在于“生态”比如各种管理工具、告警监控、SDN 插件基本都有现成的iSulad 的优势在于“轻量”整个运行时对系统资源的索取极低适合在一个只有几百兆内存的设备上跑容器。4.2 资源占用与实际性能感受这里直接给一个我实测的参考数据。同一台 openEuler 机器刚启动完 Docker 服务和 iSulad 服务后内存占用差异非常明显Docker 守护进程加上相关组件常驻内存通常在 150MB 到 200MB 左右iSulad 守护进程的内存占用可以控制在比较低的水平大概只有 Docker 的四分之一到三分之一。容器启动速度上iSulad 也有一定的优势。我测试过连续创建几十个测试容器iSulad 的启动时间更稳定波动更小这在大规模编排场景里是实打实的收益。但要说 Docker 就完全比不上也不公平。在大多数普通服务器上那点内存差几乎可以忽略而 Docker 的排障工具、监控体系、社区经验却能帮你在遇到问题的时候节约大量时间。性能差异必须要结合场景才有意义。4.3 我的选型建议如果你面对的是这些场景我建议直接用 Docker需要在 openEuler 上搭建一套标准的容器化应用环境团队成员对 Docker 已经很熟悉不愿意改习惯有成熟的监控、日志、管理工具链需要接入如果符合下面这些特征把 iSulad 放到评估清单里目标设备是边缘网关、工控机、物联网节点级别的硬件内存和磁盘空间都紧张容不下太重的常驻进程希望容器引擎具备更小的攻击面和精简的依赖项目要求系统组件尽量使用原生实现、减少外部依赖说实话我在大部分 openEuler 服务器上仍然默认用 Docker但在边缘侧的轻量化项目里iSulad 的表现确实更贴合硬件条件。这两者不是替代关系而是互补关系。5. 容器上线后最容易踩的几个坑与排查思路5.1 Docker 服务启动失败且报 iptables 相关错误现象是systemctl start docker之后服务直接失败查看日志能看到 iptables 相关报错。这个问题在 openEuler 上碰到过好几次。大多数原因都是内核模块没有加载。Docker 的网络隔离依赖br_netfilter等模块如果缺失iptables 规则就折腾不起来。解决办法modprobe br_netfilter然后确认模块正常运行再开机自动加载。lsmod | grep br_netfilter如果重启后又变没了就把br_netfilter写进/etc/modules-load.d/docker.conf文件里确保每次开机自动加载。5.2 overlay2 提示备份文件系统不支持这个就是前面提过的d_type问题。出现这个报错时我的排查步骤是先用df -hT确认 Docker 数据目录挂在什么文件系统上。如果是 XFS再用xfs_info查看ftype。如果是 1那都不是底层问题。如果底层文件系统不支持最简单的方案是换一个数据目录位置放到一个兼容的文件系统上或者新建分区格式化成支持ftype1的 XFS然后重新挂载。注意任何分区格式化操作前请务必备份数据。这个动作在测试环境验证一次之后建议直接沉淀成团队的标准操作文档。5.3 isulad 启动正常但 isula 命令连不上 daemon安装完 iSulad 后systemctl status isulad显示正常但执行isula ps报错连接失败。这个问题多半是环境变量导致的 socket 路径不对。直接用默认位置确认一下ls -l /var/run/isulad.sock如果 socket 文件确实存在检查ISULAD_HOST环境变量是否被设置成了非本地路径。有管理工具的同学可能会把环境变量统一写进了配置这会影响命令行工具的连接目标。去掉或者修正环境变量后重新执行即可。5.4 容器内时间和系统时间对不上容器默认复用宿主机的内核时钟但时区是独立的。很多镜像默认使用 UTC 时区你在国内服务器上跑出来的容器日志时间会落后 8 小时排障的时候非常容易产生误解。最简单的处理方式是启动容器时把宿主机的时区文件挂载进去docker run -d --name app -v /etc/localtime:/etc/localtime:ro nginx:latestiSulad 也支持同样的挂载方式。如果是 docker compose 编排就在 volumes 里面加上对应映射。这个细节虽然不起眼但我见过不少新同事花了一下午查日志最后发现只是时区问题。5.5 镜像拉取缓慢问题openEuler 服务器在国内网络环境下拉取外部镜像时速度经常不理想。最佳实践是配置镜像加速器或者自建镜像仓库。Docker 在/etc/docker/daemon.json里增加加速地址{ registry-mirrors: [https://你的镜像加速地址] }iSulad 则是在/etc/isulad/daemon.json里配置同样需要重启服务生效。如果公司内部有私有仓库也可以配置 insecure 仓库或者正式证书仓库来直接对接。这里提醒一句镜像加速地址要选择自己网络环境可达的不要照抄网上的配置否则可能越加速越慢。我在实际项目里的做法是先测试镜像源的连通性和下载速度再写进配置文件。6. 一些我在实操中的体会文章最后不再做总结但我确实想在收尾时分享几个真实环境里的体会希望能帮你少走弯路。第一两个容器引擎可以共存但不要混用。如果你在一台机器上同时安装 Docker 和 iSulad它们各自管理自己的数据目录镜像不会自动共享。虽然都是 OCI 镜像但同一个镜像你得分别拉取一遍。所以生产环境建议要么选一个引擎作为标准要么提前做好镜像分发方案。第二配置文件的变更一定要验证生效。Docker 和 iSulad 的守护进程在配置改动后都需要重启而重启之后没有报错不代表配置全部生效。养成习惯每次改完配置后都执行对应的info命令把关键字段核对一遍再走。第三从 Docker 平滑迁移到 iSulad 的操作没有想象中那么难。因为镜像格式统一你只需要把镜像导出、导入再把 docker 命令翻译成 isula 命令多写几层包装脚本应用层基本感知不到变化。这里的关键是整个环境的镜像标准化程度只要镜像构建时遵循 OCI 规范迁移成本就非常低。第四容器引擎选型不是技术问题更多是运维效率问题。在我自己管理的环境里边缘侧资源受限就上 iSulad普通服务器和云上统一用 Docker。按场景分池管理反而比全公司统一用一种引擎更灵活。最后一个小建议不管是 Docker 还是 iSulad容器引擎的版本升级都要谨慎先在一台测试机上验证镜像兼容性再推进到全量节点。我见过因为升级 Docker 版本导致老镜像分层不兼容的现场教训不算轻。容器技术本身的迭代速度快系统层面的稳定往往不取决于新特性多少而取决于你升级时有多保守。