资讯动态

Docker部署Rocky Linux实战:构建企业级基础镜像全指南

发布时间:2026/9/15 13:07:12 来源:尧图企业网站定制
开篇我先说个背景2024 年 CentOS 7 停止维护之后大量跑在旧系统上的业务开始迁往新平台而 Rocky Linux 几乎成了迁移清单里的默认答案。它跟 RHEL 高度一致又能免费商用配合 Docker 做企业级基础镜像算是性价比极高的一条路。这篇文章我打算把「Docker 部署 Rocky Linux」这件事拆开讲透包括怎么选镜像、怎么配静态 IP、怎么处理 systemd 和时区、怎么把常用软件塞进基础镜像以及我自己踩过的坑。适合两类人看一类是想给公司搭一套标准基础镜像平台的运维另一类是刚上手 Docker、想知道 Rocky Linux 容器该怎么玩的开发。1. 为什么企业级基础镜像首选 Rocky Linux1.1 RHEL 兼容意味着什么先说兼容性。Rocky Linux 是 RHEL 的社区重建版核心目标就是和 RHEL 保持 bug-for-bug 级别的兼容。这意味着绝大多数针对 RHEL 编写的软件包、安装脚本、安全基线、操作习惯在 Rocky 上都能直接套用。实际用起来有两点特别省心第一企业采购的商业软件常常只在认证列表里写 RHEL不会写 Rocky但你在 Rocky 容器里装的时候会发现依赖一点问题没有行为也一样第二团队成员如果习惯了 CentOS 或 RHEL 的操作方式切到 Rocky 几乎没有学习成本yum/dnf 命令、firewalld 规则、SE Linux 策略这些都能无缝衔接。还有个容易被忽略的点既然要做基础镜像那底层系统的稳定性和更新节奏很关键。Rocky 采用滚动发布模型小版本会持续累积安全补丁不用像某些激进发行版那样频繁跨大版本对镜像平台来说这种「稳定优先」的策略是对的。1.2 生命周期与商业软件兼容的隐性成本选基础镜像不能只看「能不能跑」还要看「能跑多久」。CentOS 7 停止维护后还在用它的团队会面临安全补丁缺失和商业软件适配滞后的问题。Rocky Linux 的生命周期长达 10 年这个周期基本覆盖了多数企业硬件和业务系统的服役年限。从成本角度看用 Rocky 做基础镜像也能节省隐性开销。团队不需要额外学习 openSUSE 的 zypper 或者 Ubuntu 的 apt安全扫描、合规审计、监控脚本大多沿用 RHEL 系那一套改造量小。加上 Docker 镜像一旦构建好就被固化下来底层到底是哪个发行版其实对业务透明团队只需要维护一套标准镜像即可。2. 环境准备与镜像拉取不是 docker pull 那么简单2.1 宿主机 Docker 环境准备在开始之前先确认宿主机 Docker 环境没问题。Linux 服务器上安装 Docker 通常就三步配置 yum 仓库、安装 docker-ce、启动服务。如果你用的是 Windows 或 macOS建议直接用 Docker Desktop但要注意虚拟化支持必须打开不然会报virtualization support not detected这种错误。Windows 上开启虚拟化要在 BIOS 里启用 Intel VT-x 或 AMD-V然后确认 Hyper-V 和 Windows 虚拟机监控程序平台这两个功能是启用的。Docker Desktop 启动失败时十有八九是这两个开关没打开。Linux 宿主机的话装完 Docker 后建议顺手验证几个点docker version能正常输出客户端和服务端信息docker info里存储驱动是 overlay2Cgroup 版本是 v2。这些参数直接影响容器运行性能和稳定性后面排查问题也用得上。注意不要在没配置 Docker 镜像加速的情况下直接拉取大镜像尤其是基础镜像动辄几百 MB网络质量差的时候很容易超时。国内环境建议提前配好镜像加速地址。2.2 拉取与验证 Rocky Linux 镜像版本选择与签名校验Rocky Linux 官方在 Docker Hub 上有两个镜像rockylinux和rockylinux/rockylinux。前者是最小镜像适合做基础平台后者在某些版本里包含更多工具但通常我们用前者就够了。拉取命令很简单docker pull rockylinux:9 docker pull rockylinux:8版本选择上如果你所在的企业环境还在用兼容 RHEL 8 的软件那就用 8.x如果新项目起步直接用 9.x 更合理。拉取完成后建议做一次签名校验docker image inspect rockylinux:9 --format {{.RepoDigests}}输出结果里的 digest 就是镜像的加密摘要pull 下来的镜像和官方仓库一致。企业安全要求高的话还可以在部署流程里加一步 digest 校验防止供应链攻击。2.3 第一轮运行直接进入容器交互环境拉取完镜像先别急着写 Dockerfile直接跑一个容器进去看看环境docker run -it --rm rockylinux:9 /bin/bash进去之后cat /etc/os-release你会看到 Rocky Linux 的版本信息。注意此时容器里可能连vim、net-tools都没有这是正常的最小镜像只带基础软件包。这一步是用来确认容器能正常启动、网络能通、shell 能用。如果连这一步都失败大概率是宿主机 Docker 的问题优先检查 Docker 服务状态和镜像完整性。还可以试一下能不能访问外网curl -I https://repo.rockylinux.org网络通不了的话后面安装软件会很痛苦得提前排查宿主机 DNS 和防火墙规则。3. 网络方案容器内静态 IP 的精髓3.1 为什么容器里要折腾静态 IP很多人觉得容器 IP 无所谓反正通过端口映射访问就行。但实际做企业级基础镜像平台时静态 IP 的需求很常见某些传统软件在配置里写死了 IP监控系统按 IP 维度采集数据多个容器之间通过 IP 而非服务名通信还有一些带 license 的软件授权跟 IP 绑定重启后 IP 变了授权就失效。Docker 默认的 bridge 网络使用 DHCP 分配 IP容器重启后 IP 可能漂移。解决方式就是自定义网络并指定静态 IP。这个操作不是 Rocky Linux 特有的但既然做基础镜像平台网络规划一定得在一开始就定好。3.2 基于自定义 bridge 网络的静态 IP 配置Docker 里配静态 IP 需要先创建自定义网络因为默认 bridge 网络不支持手动指定 IP。下面的命令创建一个子网为172.20.0.0/24的网络docker network create --subnet172.20.0.0/24 --gateway172.20.0.1 rocky-net然后指定 IP 运行容器docker run -d --name rocky-base --network rocky-net --ip 172.20.0.10 rockylinux:9 sleep infinity--ip参数只能在自定义网络里使用而且要注意 IP 不能在子网里冲突。生产环境建议把 IP 规划表维护好谁用哪个 IP 提前分清楚不然等容器多了再改 IP 特别痛苦。还有一种方式是在 docker-compose 里配置 networks后面会讲到。但不管哪种方式容器内部的/etc/hosts和路由都会由 Docker 自动维护基本不需要手动改。3.3 docker-compose 网络配置与 DNS 解析docker-compose 是编排多个容器时的标配下面是一个示例version: 3.8 services: rocky-app: image: rockylinux:9 container_name: rocky-app networks: rocky_net: ipv4_address: 172.20.0.11 volumes: - app_data:/data restart: always networks: rocky_net: external: true注意这里network: external: true表示使用前面通过docker network create创建的网络。如果你想在 compose 里直接创建网络不写 external 就行networks: rocky_net: driver: bridge ipam: config: - subnet: 172.20.0.0/24 gateway: 172.20.0.1DNS 解析方面容器默认使用宿主机配置的 DNS。如果公司内部有自建 DNS 或者需要解析内部服务名可以在 compose 里加services: rocky-app: dns: - 10.10.10.1 - 8.8.8.8也可以改/etc/docker/daemon.json设置全局 DNS{ dns: [10.10.10.1, 8.8.8.8] }改完重启 Docker 生效。这里要提醒一句容器内手动改/etc/resolv.conf不是不行但容器重建后就没了所以正确做法是在 Docker 层配置。经验我见过不少人在容器里手改 resolv.conf改完当时有效容器一重启又恢复原样然后回来问我为什么没生效。记住Docker 容器是「不可变基础设施」理念运行时配置要么通过docker run参数要么通过 compose 文件直接进容器改配置只适合临时调试。4. 系统级优化时区、字符集、systemd 与依赖库4.1 时区与语言环境基础镜像默认时区是 UTC这在国内业务环境下会导致日志时间差 8 小时排查问题的时候特别容易懵。首先推荐在镜像构建阶段直接把时区设置好因为你的业务容器通常跑在 UTC 环境里但是日志和定时任务都需要东八区时间。一种做法是在 Dockerfile 中设置时区FROM rockylinux:9 RUN yum install -y tzdata \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ echo Asia/Shanghai /etc/timezone另一种做法是运行时挂载主机的时区文件docker run -v /etc/localtime:/etc/localtime:ro -v /etc/timezone:/etc/timezone:ro rockylinux:9个人更推荐第一种因为它在镜像里固化了时区信息任何人在任何宿主机上运行都能保持一致。语言环境也一样最好在 Dockerfile 里设置ENV LANGen_US.UTF-8 \ LANGUAGEen_US.UTF-8 \ LC_ALLen_US.UTF-8如果没有这一步很多 Java 应用和 Python 脚本处理中文时会出现乱码尤其是做文档转换、报表导出这类功能时特别明显。4.2 systemd 不是你想用就能用容器里跑 systemd 是个经典大坑。默认情况下容器内没有 PID 1 进程是 init 系统直接运行systemctl start xxx会报错System has not been booted with systemd as init system (PID 1). Cant operate.。解决方案有两个方向。第一个方向是避免使用 systemd改用前台进程方式启动服务。例如启动 nginxdocker run -d rockylinux:9 /usr/sbin/nginx -g daemon off;这种方案是最推荐的也是 Docker 设计初衷。第二个方向是使用支持 systemd 的特权容器在docker run时加参数docker run -d --name rocky-systemd \ --privileged \ -v /sys/fs/cgroup:/sys/fs/cgroup:rw \ rockylinux:9 \ /usr/sbin/init然后进入容器使用 systemctl。这种方案多用于模拟完整系统环境、做系统级测试的场景生产环境不建议滥用因为它绕过了 Docker 进程隔离的优势安全性和稳定性都有代价。4.3 常用依赖与中文字体LibreOffice 实战基础镜像的另一个重要作用是预装通用依赖。比如很多团队会做文档在线预览、格式转换服务底层依赖 LibreOffice。在 Rocky Linux 基础镜像里安装 LibreOffice 大版本很简单FROM rockylinux:9 RUN yum install -y libreoffice-headless libreoffice-writer libreoffice-calc \ yum clean all但有几个坑值得提前防着第一LibreOffice 需要中文字体才能正常渲染中文文档否则转换出来的 PDF 全是方块。安装字体包可以用yum install -y wqy-microhei-fonts wqy-zenhei-fonts或者把公司统一字体文件复制到/usr/share/fonts/目录然后执行fc-cache -f刷新字体缓存。第二LibreOffice 依赖的共享库比较多如果你的基础镜像删得太狠运行时容易报libXext.so.6这类缺失。解决方案是安装时用libreoffice-headless而不是libreofficeheadless 版本依赖更少更适合容器里跑。第三如果业务是通过 Java 调用 LibreOffice比如用 JODConverter要确保容器里装了fontconfig和freetype并且 JAVA_HOME 环境变量正确。5. 构建企业级基础镜像Dockerfile 与镜像分层设计5.1 一个可复用的基础镜像 Dockerfile前面说了一堆概念这里给一个可以直接用于生产的基础镜像 Dockerfile。它做的事情包括设置时区和字符集、安装常用工具、预装语言运行环境和文档转换工具、清理缓存。FROM rockylinux:9 LABEL maintaineropsexample.com \ version1.0.0 \ descriptionRocky Linux 9 enterprise base image ENV TZAsia/Shanghai \ LANGen_US.UTF-8 \ LANGUAGEen_US.UTF-8 \ LC_ALLen_US.UTF-8 RUN yum install -y \ tzdata \ langpacks-en \ fontconfig \ freetype \ wqy-microhei-fonts \ wqy-zenhei-fonts \ vim \ curl \ wget \ tar \ unzip \ which \ procps \ iputils \ net-tools \ yum install -y \ java-17-openjdk-headless \ libreoffice-headless \ yum clean all \ rm -rf /var/cache/yum \ ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \ echo Asia/Shanghai /etc/timezone WORKDIR /app CMD [/bin/bash]这个镜像包含 Java 17 运行环境因为大量企业应用是 Java 写的。如果你不需要 Java把这行去掉就行。LibreOffice headless 版本用来处理文档转换中文字体保证中文渲染正常。工具链包含了日常排障需要的命令基本可以覆盖大多数场景。构建命令docker build -t registry.internal/rocky-base:9-1.0.0 .5.2 镜像瘦身与缓存优化基础镜像不是越大越好但也不能一味追求小。每条安装指令都会创建一层层数多会导致镜像体积膨胀构建时间变长。常见的优化措施包括合并 RUN 指令。把多个yum install合并到同一个 RUN 里减少层数。使用dnf的缓存挂载功能构建时缓存下载的 RPM 包加速重复构建RUN --mounttypecache,target/var/cache/dnf \ yum install -y some-package这点在 CI 环境非常管用否则每次构建都从零下载依赖。清理不需要的文档和缓存。yum clean all之后还可以删掉/usr/share/doc、/usr/share/man这类目录。所有清理动作要在同一个 RUN 指令里完成确保清理发生在同一层否则旧的层还是会保留被删除的文件。5.3 基于基础镜像扩展业务镜像基础镜像平台搭好后业务团队只需要在自己的 Dockerfile 里FROM这个基础镜像不用再做系统层配置。比如部署 MySQL 8 的业务镜像FROM registry.internal/rocky-base:9-1.0.0 RUN yum install -y mysql-server yum clean all COPY my.cnf /etc/my.cnf EXPOSE 3306 CMD [mysqld]部署 Redis 主从也是类似思路先装 redis然后通过 compose 编排主从节点。用统一基础镜像的好处在于安全补丁只要在基础镜像层更新一次重新构建业务镜像就能继承团队之间的环境差异也降到最低Dev、Test、Prod 跑的是同一套底层。6. 常见问题与排查实录6.1 启动失败、退出码崩溃容器一启动就退出几乎每个做过 Docker 的人都会遇到。最典型的症状是docker run -d rockylinux:9之后容器立即变成 Exited 状态。原因是rockylinux:9默认没有常驻进程启动后 shell 执行完就退出。解决办法是给容器指定一个阻塞命令比如sleep infinity或者启动实际的服务进程。排查时用docker logs container看有没有报错信息用docker inspect container看退出码和错误日志字段。6.2 systemd 相关错误如果在容器里执行systemctl start sshd报System has not been booted with systemd参考 4.2 节。如果想完整模拟系统环境使用带 systemd 的启动方式如果只是跑业务服务老老实实用前台模式。还有一种情况是安装了某个软件后安装脚本里自动执行了systemctl enable xxx这时候会报错Failed to get D-Bus connection。解决方法是安装时加--norestart或者手动禁用 post-install 脚本里对 systemd 的调用。6.3 时区与字符集问题Java 应用打印日志时间差了 8 小时或者报Unknown timezone需要确认两部分系统时区文件是否指向 Asia/Shanghai以及TZ环境变量是否设置。字符集问题更隐蔽终端里看着正常但程序处理中文时乱码多半是LC_ALL没设置程序用了默认的 POSIX 或 C 字符集。6.4 网络异常问题容器能启动但 ping 不通外网优先排查宿主机的 IP 转发是否开启sysctl net.ipv4.ip_forward如果输出是 0需要修改/etc/sysctl.conf或执行sysctl -w net.ipv4.ip_forward1。宿主机防火墙也可能拦截容器流量需要放行 Docker 使用的网段。DNS 解析失败的话检查/etc/docker/daemon.json里的 dns 配置重启 Docker 后生效。6.5 依赖包安装失败在最小镜像上安装软件时经常遇到No package xxx available。这是因为默认的 yum 源不包含某些软件包需要启用 CRBCodeReady Builder仓库或 EPEL 仓库dnf install -y epel-release dnf config-manager --set-enabled crb装完后记得再yum clean all。如果安装过程中出现 GPG key 检查失败可以在命令后面加--nogpgcheck但生产环境不建议这么干最好先更新 GPG key。结尾小经验最后分享一个我自己多年实践下来的习惯基础镜像一定要做版本锁定。不要直接在业务 Dockerfile 里写FROM rockylinux:9这种浮动的 tag因为rockylinux:9会在小版本更新时变化哪天重新构建出来的镜像跟之前的行为不一样排查起来非常头疼。正确做法是把基础镜像构建好之后推送到私有仓库比如registry.internal/rocky-base:9-1.0.0锁定这个不可变的 tag。等基础镜像需要更新安全补丁时重新构建一个新版本 tag业务团队再主动升级这样整个平台的变更可追溯、可回滚。这也是我理解的「企业级基础镜像平台」最核心的一件事。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价