换个思路,绕过 MongoDB 8.x 的内核检测技术
本来不打算发文的,但看到市面上基本上没有文章,加上最终使用的手段有点偏Safe,还是简单记录一下过程吧:
新电脑/内核更新后MongoDB用不了了:
ERROR: Detected Linux kernel 7.0.0-30-generic. MongoDB has compatibility issues with the allocator it uses on kernel v6.19 and newer, so this container will not start by default on v6.19+.
试了社区里面流传的一些方法也一样的,常用版本我也都试了,毫无用处,包括怎么让8.x的内存性能优化不要开启,都试过,就是不行

官方说受影响的内核版本号范围是:6.19.0 ~ 7.0.13 ,那就先更新一下看看:sudo apt update && sudo apt upgrade && sudo apt dist-upgrade

的确是更新到官方支持的7.0.14,但很遗憾还是不支持


老外最近也有讨论:https://github.com/docker-library/mongo/issues/765
试到这我其实也不想折腾了,如果放弃,那么就是这几个解决方法:
- 回退支持的内核版本
- 使用旧MongoDB版本
但我想试试MongoDB 8.3.x的Vector Search功能,而且我Linux内核的确也是它官方文档支持的范围了,凭什么不能用?
我被限制并不是真正的版本不匹配导致的不能用,而是官方使用了uname来判断我有没有符合条件,那明显是他的bug,我肯定不服。
那就搞点事情,直接 ==> 绕开当前 Linux 7.0.x + MongoDB 8.x 的 TCMalloc/rseq 问题检测
这种黑锅的事情,肯定是让AI写欺骗脚本了:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <sys/utsname.h>
static int (*real_uname)(struct utsname *buf) = NULL;
int uname(struct utsname *buf)
{
if (real_uname == NULL) {
*(void **)(&real_uname) = dlsym(RTLD_NEXT, "uname");
}
if (real_uname == NULL) {
return -1;
}
int rc = real_uname(buf);
if (rc == 0) {
/*
* Ubuntu 24.04 HWE:
* uname -r => 7.0.0-31-generic
* /proc/version_signature => upstream 7.0.14
*
* MongoDB 8.3.x parses uname().release and therefore
* incorrectly sees 7.0.0.
*
* Only rewrite the known Ubuntu HWE 7.0.0-* form.
*/
if (strncmp(buf->release, "7.0.0-", 6) == 0) {
snprintf(buf->release, sizeof(buf->release), "7.0.14");
}
}
return rc;
}
gcc -shared -fPIC -O2 -o libmongo_uname_shim.so mongo_uname_shim.c -ldl
file libmongo_uname_shim.so

mongo:
# 数据库锁定版本比较合适,最新:mongodb/mongodb-community-server:latest-slim
# ubi9:基于 RedHat Universal Base Image 9;slim:精简版基础镜像, 去掉不必要的软件包
# image: mongodb/mongodb-community-server:8.3.11-ubi9-slim
image: mongo:8.3.11-noble
container_name: mongo-server
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: ${MONGO_ROOT_USERNAME}
MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ROOT_PASSWORD}
TZ: Asia/Shanghai
# MongoDB要求Linux内核必须是:7.0.14+
# 绕开当前 Linux 7.0.x + MongoDB 8.x 的 TCMalloc/rseq 问题检测
# 只修正 MongoDB 对 Ubuntu HWE kernel release 的识别
LD_PRELOAD: /opt/mongo-shim/libmongo_uname_shim.so
ports:
# 外部 27017 -> 容器 27017
- "27017:27017"
volumes:
- ./data/mongodb:/data/db
- ./config/mongodb/libmongo_uname_shim.so:/opt/mongo-shim/libmongo_uname_shim.so:ro
networks:
- bxnet
healthcheck:
test:
[
"CMD-SHELL",
"mongosh --quiet --host 127.0.0.1 --port 27017 -u \"$$MONGO_INITDB_ROOT_USERNAME\" -p \"$$MONGO_INITDB_ROOT_PASSWORD\" --authenticationDatabase admin --eval \"db.adminCommand('ping').ok\" | grep 1"
]
# 检查间隔
interval: 10s
# 超时时间
timeout: 5s
# 重试次数
retries: 5
# 启动宽限期
start_period: 30s
试一下是否真可行,我直接拿最新版本的MongoDB来测试了:

# 看看能不能正常显示
docker run --rm --entrypoint /usr/bin/uname -e LD_PRELOAD=/opt/mongo-shim/libmongo_uname_shim.so -v "$PWD/config/mongodb/libmongo_uname_shim.so:/opt/mongo-shim/libmongo_uname_shim.so:ro" mongodb/mongodb-community-server:8.3.11-ubi9-slim -r
# 运行看看
docker run --rm --name mongo-test -p 27018:27017 --entrypoint /usr/bin/mongod -e LD_PRELOAD=/opt/mongo-shim/libmongo_uname_shim.so -v "$PWD/config/mongodb/libmongo_uname_shim.so:/opt/mongo-shim/libmongo_uname_shim.so:ro" --tmpfs /data/db:rw,mode=1777 mongodb/mongodb-community-server:8.3.11-ubi9-slim --dbpath /data/db --bind_ip_all --port 27017

貌似还真运行起来了,试试compose的方式能否正常

一样凉凉

测试一下:

不执行Mongodb的默认脚本,而是直接打开Mongodb是没问题的(已经成功绕过)
# 不执行Mongodb的默认脚本,而是直接打开Mongodb是没问题的
docker compose -f public-compose.yml run --rm --no-deps -p 27018:27017 --entrypoint /usr/bin/mongod mongo --dbpath /data/db --bind_ip_all --port 27017
得了,MongoDB官方启动的时候估计又搞啥幺蛾子了,再试试Docker官方的镜像:https://hub.docker.com/layers/library/mongo/8.3.11-noble



完事了

PS:AI时代不试试MongoDB 8.3.x的Vector Search功能?

浙公网安备 33010602011771号