上周帮一个项目组处理内部数据库环境搭建,服务器在隔离网段,能连通局域网,但连不上外网,也没有可用的软件仓库。需求很明确:CentOS(Linux)系统上装一个 MongoDB 7.0,而且必须纯离线完成。这种活儿看着简单,实际操作时一旦碰上 glibc、openssl 版本不匹配,可能一折腾就是一下午。我这次完整走了一遍,把坑都试出来了,所以把整个过程整理出来。文章会先讲离线安装的方案选择和系统版本要求,再给完整可复现的安装步骤,最后是排障记录和 CentOS 7.9 的特殊处理建议。无论你是运维还是后端开发,照着这份思路基本都能把服务跑起来。
1. 先把方案定清楚:离线装 MongoDB 7.0 之前要明白的事
1.1 什么场景下必须离线安装
我接触到的离线安装需求,大多来自下面几种情况:
- 单位内部有等保要求,生产网段与互联网物理隔离,外网设备不允许接入;
- 内网虽然提供了 yum 源,但里面只有基础系统包,没有 MongoDB,也没有额外的应用仓库;
- 项目交付到客户现场,客户不允许服务器连接公网下载任何安装包;
- 公司有安全审计流程,所有软件必须经过审批和杀毒扫描后才能带入内网。
这些场景的共同点是:你不能在线执行yum install mongodb-org,必须在外部环境把所有软件包准备齐全,再通过 U 盘、FTP、审批流程等方式拷入内网。离线安装最怕的不是“拷一个包进去就完事”,而是“拷进去之后发现它还有一堆依赖库没带全”,来回折腾审批流程极其浪费时间。
所以离线安装的核心思路要提前建立起来:不管最后用 rpm 还是 tar 包,都必须把应用本体和它运行时依赖的库一起准备好,并且提前了解目标机器的系统版本、glibc 版本、openssl 版本,而不是直接去装。
1.2 系统版本选型:为什么我不推荐在 CentOS 7.9 上硬装 7.0
这里要先说实话。MongoDB 官方对 MongoDB 7.0 的平台支持清单里,RHEL 7 / CentOS 7 已经不在支持范围内,官方只发布面向 RHEL 8 / RHEL 9 的二进制包。CentOS 7.9 自带 glibc 2.17,而 MongoDB 7.0 的 RHEL 8 版本要求 glibc 2.28;CentOS 7.9 自带 openssl 1.0.2,而 MongoDB 7.0 需要 openssl 1.1 提供的 libcrypto.so.1.1。因此,在 CentOS 7.9 上直接解压官方 tgz 包,大概率会报GLIBC_2.28 not found或libcrypto.so.1.1: cannot open shared object file。
如果你手头只有 CentOS 7.9,并且确实想用 MongoDB 7.0,硬装不是完全没可能,但代价非常大:要处理 glibc 升级、openssl 替换,操作不当很容易把系统基础环境搞坏,连 ssh、systemd 都可能起不来。我建议走两条更稳的路:
| 方案 | 适用场景 | 推荐程度 |
|---|---|---|
| 换用 Rocky Linux 8.6+ / CentOS Stream 8 / AlmaLinux 8+ | 系统可以重装或迁移 | 最推荐,原生离线安装很干净 |
| CentOS 7.9 + Docker 离线运行 mongodb 镜像 | 系统不能动,又必须用 MongoDB 7.0 | 推荐,绕开 glibc/openssl 问题 |
| CentOS 7.9 原生硬装 | 没有 Docker 也不允许换系统 | 不推荐,风险高且成功率低 |
本文第 3 章的完整安装步骤,我以 RHEL 8 兼容环境(实测用的是 Rocky Linux 8.6)为基准来写;第 5 章单独讲 CentOS 7.9 上的 Docker 替代方案。这样既能满足“CentOS Linux 离线安装 MongoDB 7.0”的项目需求,又不至于让你在错误的路线上浪费时间。
2. 在有外网的机器上把安装包和依赖全部备齐
2.1 需要准备哪些文件
离线安装前,建议先列一份清单。我这次实际用到的文件如下:
mongodb-linux-x86_64-rhel80-7.0.14.tgz mongosh-2.2.6-linux-x64.tgz其中第一个是 MongoDB Server 主程序包,第二个是 MongoDB 官方的命令行客户端。这里很多人会忽略一个问题:MongoDB 7.0 的 Server 包不再内置 mongo shell,而是把 mongosh 单独发布。也就是说,你只拷贝 server 包进内网,装完之后会发现mongo命令不存在,连验证服务都要再折腾一遍。我第一次离线部署 MongoDB 7.0 时就吃过这个亏,所以现在准备物料时一定会把 mongosh 一并放进去。
下载地址我习惯用官方源:
https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.14.tgz https://downloads.mongodb.com/compass/mongosh-2.2.6-linux-x64.tgz同时建议下载对应的 SHA-256 校验文件。离线安装包通常要经过 U 盘拷贝、杀毒扫描、审批流转等多道环节,传输过程中文件被改动或损坏的概率不小,提前校验能省去后面大量排障时间。
2.2 下载与校验
在有外网的环境里执行:
mkdir -p /opt/mongo-offline cd /opt/mongo-offline wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.14.tgz wget https://downloads.mongodb.com/compass/mongosh-2.2.6-linux-x64.tgz wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.14.tgz.sha256校验命令:
sha256sum -c mongodb-linux-x86_64-rhel80-7.0.14.tgz.sha256看到OK说明下载完整。如果输出FAILED,不要犹豫,直接重新下载。这一步几秒钟就能完成,但很多人在内网部署失败后才回头检查,结果发现是包本身被截断了,白白浪费一晚上。
2.3 内网传输与目录规划
把两个 tgz 包通过 U 盘、FTP 或内网跳板机传到目标服务器的/opt/mongo-offline目录。我习惯在目标机器上先建一套清晰的目录结构:
mkdir -p /opt/mongo-offline mkdir -p /usr/local/mongodb/{bin,conf,data,logs} mkdir -p /usr/local/mongosh/bin为什么要把数据目录、日志目录、配置目录单独分出来?因为 MongoDB 运行后会产生大量数据文件和日志,跟二进制文件混在一起,后续备份、日志切割、权限管理都会很痛苦。这种目录规划长期运维时会越来越香。另外,我会把原始安装包复制一份到/root/backup/,防止安装过程中误删导致重新走一遍外部审批。
3. 原生离线安装全流程:实测步骤
3.1 解压并放置二进制
在目标服务器上执行:
cd /opt/mongo-offline tar -zxvf mongodb-linux-x86_64-rhel80-7.0.14.tgz tar -zxvf mongosh-2.2.6-linux-x64.tgz解压后目录名通常是mongodb-linux-x86_64-rhel80-7.0.14,里面bin/下有mongod、mongos等可执行文件。把相关命令复制到规划好的目录:
cp -a mongodb-linux-x86_64-rhel80-7.0.14/bin/* /usr/local/mongodb/bin/ cp -a mongosh-2.2.6-linux-x64/bin/* /usr/local/mongosh/bin/然后添加环境变量,编辑/etc/profile.d/mongodb.sh:
export PATH=/usr/local/mongodb/bin:/usr/local/mongosh/bin:$PATH使环境变量立即生效,并验证:
source /etc/profile.d/mongodb.sh which mongod mongod --version如果mongod --version能正常输出版本信息,说明 MongoDB 二进制在当前系统的 glibc 和 openssl 环境下能跑起来。如果这一步报GLIBC_2.28 not found,说明系统不是 RHEL 8 兼容环境,需要回到第 1 章重新确认系统版本。
mongosh 也验证一下:
mongosh --version这里多说一句:mongos和mongosh是两个完全不同的东西,中间只差一个字母。mongos是 MongoDB 分片集群的路由组件,mongosh才是命令行客户端。我第一次教别人装的时候,有人把mongos当客户端去连接,连不上还以为是离线包少了文件,折腾了很久。
3.2 编写 mongod.conf
MongoDB 从 4.x 开始推荐使用 YAML 格式的配置文件。下面这份是我在离线环境实测可用的最小化配置,放在/usr/local/mongodb/conf/mongod.conf:
# /usr/local/mongodb/conf/mongod.conf systemLog: destination: file path: /usr/local/mongodb/logs/mongod.log logAppend: true storage: dbPath: /usr/local/mongodb/data wiredTiger: engineConfig: cacheSizeGB: 1 processManagement: fork: false net: port: 27017 bindIp: 0.0.0.0几个关键参数解释一下:
systemLog.logAppend: true:日志追加写入而不是覆盖。MongoDB 重启后如果直接覆盖日志,排障时想翻上次的启动记录就找不到了。storage.dbPath:数据文件目录,必须提前建好,并且mongod运行用户要有写权限,否则启动时会报权限相关错误。processManagement.fork:如果用 systemd 托管服务,这里必须写成false。systemd 希望服务进程在前台运行,由它来统一管理守护状态。如果写成true,mongod 会自己 fork 到后台,systemd 会认为服务启动失败或者出现 start timeout。net.bindIp: 0.0.0.0:允许所有网卡监听,便于内网其他机器访问。如果只是本机用,可以写成127.0.0.1,更安全。wiredTiger.engineConfig.cacheSizeGB:WiredTiger 存储引擎默认会占用物理内存的 50%,如果机器内存只有 2G,不显式设置的话可能会触发 OOM。建议根据机器内存提前规划,比如 4G 内存的机器设成 1G 或 1.5G。
3.3 配置 systemd 服务
MongoDB 不建议直接用 root 账号跑,我习惯创建一个独立的系统用户:
useradd -r -s /sbin/nologin mongod chown -R mongod:mongod /usr/local/mongodb然后创建 systemd 服务文件/etc/systemd/system/mongod.service:
[Unit] Description=MongoDB Database Server Documentation=https://docs.mongodb.com/manual After=network.target [Service] User=mongod Group=mongod Environment="LC_ALL=C.UTF-8" Environment="LANG=C.UTF-8" ExecStart=/usr/local/mongodb/bin/mongod --config /usr/local/mongodb/conf/mongod.conf ExecReload=/bin/kill -HUP $MAINPID Restart=always LimitNOFILE=64000 LimitNPROC=64000 [Install] WantedBy=multi-user.target这段配置有几个细节值得注意:
User=mongod和Group=mongod确保 MongoDB 以低权限用户运行,避免写文件权限过高带来的安全风险。Restart=always:MongoDB 意外退出后由 systemd 自动拉起,适合数据库这类需要长期在线的服务。但是,如果重复崩溃,systemd 会按 rate limit 不断重启,所以还是得靠日志定位根因。LimitNOFILE和LimitNPROC:数据库通常需要较多的文件句柄和进程数限制,建议显式调大。LC_ALL和LANG:避免某些环境下 mongod 输出乱码或者 locale 相关告警。
启动服务:
systemctl daemon-reload systemctl enable mongod systemctl start mongod systemctl status mongod启动后立刻看状态和日志:
tail -n 100 /usr/local/mongodb/logs/mongod.log ss -lntp | grep 27017看到27017端口在监听,说明 mongod 进程已经起来了。如果日志中显示waiting for connections on port 27017,说明一切正常。
3.4 用 mongosh 做基础验证
服务起来后,用 mongosh 连接:
mongosh --host 127.0.0.1 --port 27017连接成功后,在 mongosh 里执行:
db.runCommand({ ping: 1 }) db.version()ping返回{ ok: 1 },说明服务端正常工作。再插一条测试数据验证读写:
use testdb db.profile.insertOne({ name: "offline-install-check", ts: new Date() }) db.profile.find()能正常写入和查询,说明这套离线安装的核心链路已经通了。做到这里,原生安装部分基本完成。
4. 启动失败与连接失败:两份排障记录
4.1 报错 libcrypto.so.1.1 或 GLIBC_2.28 not found
这是我被问到最多的错误,几乎每个在 CentOS 7.9 上装 MongoDB 7.0 的人都见过:
mongod: error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory或者:
./mongod: /lib64/libm.so.6: version `GLIBC_2.28' not found原因其实很直白:
- CentOS 7.9 自带 OpenSSL 1.0.2,而 MongoDB 7.0 的 RHEL80 二进制依赖 OpenSSL 1.1 提供的
libcrypto.so.1.1; - CentOS 7.9 的 glibc 版本是 2.17,MongoDB 7.0 要求 glibc 2.28 以上。
排查命令:
# 查看缺失的共享库 ldd /usr/local/mongodb/bin/mongod | grep "not found" # 查看系统当前 glibc 版本 strings /lib64/libc.so.6 | grep GLIBC_ | tail -n 5解决方案并不推荐“硬升级系统 glibc”。替换系统级 glibc 风险极高,因为这个底层库几乎被所有程序依赖,一个不兼容就可能让 ssh、systemd、yum 全部崩掉,生产服务器直接失联。正确处理是:换 RHEL 8 兼容系统,或者用 Docker 跑。网上有一些复制高版本.so到自定义目录再设置LD_LIBRARY_PATH的做法,只能作为临时验证,不建议在业务环境使用,因为 glibc 涉及底层系统调用,不完整的环境容易引发内存校验错误、getaddrinfo 失败等隐蔽问题。
4.2 mongod 启动后立即退出,systemctl 显示失败
现象:
systemctl start mongod systemctl status mongod输出:
● mongod.service - MongoDB Database Server Loaded: loaded (/etc/systemd/system/mongod.service; enabled; vendor preset: disabled) Active: failed (Result: exit-code)我总结下来,最常见的原因有四类:
| 原因 | 典型报错 | 处理方式 |
|---|---|---|
| 数据目录或日志目录不存在 | Cannot create directory /usr/local/mongodb/data | 提前建目录并授权 |
| 目录权限不足 | Permission denied | chown -R mongod:mongod /usr/local/mongodb |
| mongod.conf 格式错误 | Error parsing YAML config file | 检查缩进和大小写 |
| 端口被占用 | Address already in use | ss -lntp找占用进程 |
排查顺序很有讲究:
journalctl -u mongod -n 50这条看 systemd 记录,能快速定位到大概原因。但如果还看不清楚,就直接手动前台启动:
/usr/local/mongodb/bin/mongod --config /usr/local/mongodb/conf/mongod.conf前台启动时,MongoDB 的日志会直接打印到终端,不再经过 systemd 和日志文件,很多问题一眼就能看到。我现在排查 MongoDB 启动故障,几乎都是先跑这条命令,比反复看 journalctl 高效得多。
4.3 远程连不上:防火墙、SELinux 和 bindIp
另一种典型情况是:服务器本机用 mongosh 能连,但局域网内其他机器用mongodb://内网IP:27017就是连不上。
按顺序排查:
第一步,确认mongod.conf里的net.bindIp是不是0.0.0.0。如果保持默认的127.0.0.1,外部网络当然连不上。很多新手改完配置后没有重启服务,配置不生效,也会出现这种情况。
第二步,检查 firewalld:
firewall-cmd --permanent --add-port=27017/tcp firewall-cmd --reload第三步,检查 SELinux。如果getenforce返回Enforcing,那大概率是 SELinux 拦住了 27017 端口。可以临时验证:
setenforce 0设为0之后如果能连上,说明就是 SELinux 的问题。生产环境不建议直接关闭 SELinux,更规范的做法是添加端口规则:
semanage port -a -t mongod_port_t -p tcp 27017CentOS 7 上如果没有mongod_port_t这个类型,可以先安装policycoreutils-python-utils,或者临时用http_port_t等已有类型放行。我个人比较务实:内网开发环境可以接受setenforce 0,但生产环境还是建议用规则放行,不要图省事。
5. 如果你手头只有 CentOS 7.9:一条更稳妥的替代路线
5.1 原生硬装的痛苦总结
再说一遍核心结论:CentOS 7.9 的底层环境是 glibc 2.17 + OpenSSL 1.0.2,MongoDB 7.0 的官方包要求 glibc 2.28 + OpenSSL 1.1,中间差了一个完整的大版本。虽然社区里确实有人通过替换 glibc 和 openssl 成功硬装了 MongoDB 7.0,但这种操作在生产环境里一旦出问题,恢复成本极高。
我的建议很简单:能换系统就换系统。Rocky Linux 8.6、AlmaLinux 8、CentOS Stream 8 都是 RHEL 8 兼容发行版,跟 CentOS 7 的操作习惯差异不大,迁移成本可控。如果你连系统迁移的审批都过不了,那就走 Docker 方案。
5.2 用 Docker 离线运行 MongoDB 7.0
Docker 方案的本质,是把 MongoDB 7.0 运行所需的操作系统环境封装在容器里,和宿主机解耦。这样宿主机是 CentOS 7.9 也没关系,容器内部可以是一个完整的 RHEL 8 兼容环境。
离线准备步骤如下:
第一步,在有外网的机器上拉取官方镜像并保存:
docker pull mongodb/mongodb-community-server:7.0.14 docker save mongodb/mongodb-community-server:7.0.14 -o mongodb-7.0.14.tar第二步,准备好 Docker 引擎本身的离线安装包。CentOS 7 上可以直接用 rpm 方式安装 Docker,提前用外网机器把 docker-ce 及其依赖拉全:
yumdownloader --resolve docker-ce第三步,把mongodb-7.0.14.tar、Docker rpm 包以及依赖全部拷入内网。先离线安装 Docker,再导入镜像:
docker load -i mongodb-7.0.14.tar第四步,启动容器:
docker run -d \ --name mongodb7 \ --restart=always \ -p 27017:27017 \ -v /data/mongodb:/data/db \ mongodb/mongodb-community-server:7.0.14这里我把宿主机的/data/mongodb挂载到容器的/data/db,确保 MongoDB 数据文件保存在宿主机磁盘上。即使容器被删掉、重新创建,数据也不会丢。
Docker 方案最大的优点是可以直接使用官方镜像,稳定性和兼容性有保障;最大的缺点是需要在现场安装 Docker,离线准备量比原生安装多一步。如果你的内网已经有容器化基础设施,这个方案基本就是最优解。
5.3 我踩过几次坑之后的经验
第一,离线安装不是“一次性动作”,而是“维护动作”。我每次装完 MongoDB,都会把用到的 tgz 包、rpm 包、配置文件、systemd unit 文件全部整理到一个目录,比如/opt/offline-packages/mongodb-7.0.14/。以后接新机器、同配置复制、版本升级,直接整套拷过去,比每次重新找包高效得多。
第二,养成“安装前校验”的习惯。离线包经过 U 盘、审批系统、杀毒软件层层流转,文件很难保证完全没被动过。使用前跑一下sha256sum,几秒钟的事,能省下装到一半才报错的排查时间。
第三,MongoDB 7.0 默认使用 WiredTiger 存储引擎,首次启动前一定要把storage.dbPath、wiredTiger.engineConfig.cacheSizeGB、net.bindIp、security.authorization这些关键参数想清楚。首次启动之后再改dbPath、replication这类参数会麻烦很多,一次配好是最省事的。
按这套流程,我在 Rocky Linux 8.6 上离线装 MongoDB 7.0.14 只用了不到半小时;在 CentOS 7.9 上走 Docker 方案也把服务稳定跑起来了。如果你在安装过程中遇到我这里没覆盖到的报错,建议先执行journalctl -u mongod -n 200,再手动前台启动mongod --config mongod.conf看实时日志,绝大多数问题都能在这两步里定位出来。