Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[BUG] 无法在docker node:*-alpine 镜像中运行 #44

Copy link
Copy link
@wtone

Description

@wtone
Issue body actions

只要是 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/目录下。

Originally posted by @wtone in #30

Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.