-
Notifications
You must be signed in to change notification settings - Fork 33
Open
Labels
bugSomething isn't workingSomething isn't working
Description
只要是 docker node:*-alpine 镜像 就会有问题,在Docker node:18-alpine 镜像容器中,新建一个测试脚本
docker run -it --rm node18:alpine sh
mkdir test
cd test
npm init
npm i imagescript sharp
vi test.js
//test.js
const { arch, platform } = require('os');
console.log(arch(), platform())
try {
module.exports = require(`imagescript/codecs/node/bin/${arch()}-${platform()}.node`);
}catch (err) { throw new Error('unsupported arch/platform: ' + err.message); }
执行就会报错 :Segmentation fault (core dumped)
同样的引用node原生模块,sharp库就不会报错
console.log(platformAndArch())
try {
module.exports = require(`sharp/build/Release/sharp-${platformAndArch()}.node`);
} catch (err) {
throw new Error('unsupported arch/platform: ' + err.message);
}
比较后,发现主要是因为platform这个变量取值以及Alpine 的 musl libc 兼容性问题,主要原因是:
1、musl 与 glibc 二进制不兼容
.node 文件是 Node.js 原生模块(C/C++ 编译的二进制文件),若该文件是在 glibc 系统(如 Ubuntu、CentOS)上编译的,而 Alpine 使用 musl libc,两者的二进制接口不兼容,会导致 Node.js 无法正确加载模块(即使文件存在)。
2、获取当前运行环境的平台信息的方式有问题:
// imagescript/codecs/node/index.js
const { arch, platform } = require('os');
module.exports = require(`./bin/${arch()}-${platform()}.node`);
简单通过os.platform获取的值,无法区分linux(Ubuntu、CentOS) 和 linuxmusl(Docker alpine容器),可以参考 sharp库的做法写一个方法来获取platform和arch:
function platformAndArch() {
const arch = env.npm_config_arch || process.arch;
const platform = env.npm_config_platform || process.platform;
const libc = process.env.npm_config_libc ||
/* istanbul ignore next */
(detectLibc.isNonGlibcLinuxSync() ? detectLibc.familySync() : '');
const libcId = platform !== 'linux' || libc === detectLibc.GLIBC ? '' : libc;
const platformId = [];
if (arch === 'arm') {
const fallback = process.versions.electron ? '7' : '6';
platformId.push(`armv${env.npm_config_arm_version || process.config.variables.arm_version || fallback}`);
} else if (arch === 'arm64') {
platformId.push(`arm64v${env.npm_config_arm_version || '8'}`);
} else {
platformId.push(arch);
}
platformId.push(`${platform}${libcId}`);
return platformId.join('-');
}
在Docker alpine 容器中调用platformAndArch()将得到的platform和arch是 “x64-linuxmusl”
3、本身提供的imagescript/codecs/node/bin/*.node 文件中也没有包含支持x64-linuxmusl.node的文件
需要重新编译一份适配linuxmusl的模块文件(x64-linuxmusl.node),并添加到imagescript/codecs/node/bin/目录下。
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working