Docker、AlpineLinux 和 Ubuntu - 为啥`node_modules` 不同

Posted

技术标签:

【中文标题】Docker、AlpineLinux 和 Ubuntu - 为啥`node_modules` 不同【英文标题】:Docker, AlpineLinux and Ubuntu - why does `node_modules` differentDocker、AlpineLinux 和 Ubuntu - 为什么`node_modules` 不同 【发布时间】:2021-10-31 04:37:25 【问题描述】:

环境

我确实使用 gitlab 的 CI/CD 来捆绑我的应用程序。 我确实使用 node:14-alpine 作为图像并运行 yarn 来构建我的应用程序。

构建完成后,我确实通过 rsync 将我的应用程序部署到运行 ubuntu 20.04 的目标服务器。

在这台服务器上,我确实使用 pm2 来启动应用程序并使其保持运行。

问题

如果我查看日志,我确实会看到如下错误:

我搜索了一下,发现问题可能是由于缺少musl-dev 造成的。 我已将它安装在我的 serverdocker-container 中,但结果相同。

但是,如果我确实从服务器上删除了 node_modules 目录,并在服务器上运行 yarn install,应用程序将按预期运行

问题

那么为什么会出现这个问题呢?我必须在我的 docker-container 中拥有相同的 Linux 发行版和版本以适应所有依赖项吗?

【问题讨论】:

你能分享你的 Dockerfile 吗? npm install 可能会构建特定于平台的代码作为安装模块的一部分——您应该使用与部署相同的操作系统来构建node_modules 您是在 ubuntu 服务器上运行 CICD 管道中的最终映像还是只运行二进制文件? 您将此标记为 Docker 问题; Docker 映像通常应该是自包含的,主机上安装了什么并不重要。您是否有证明问题的minimal reproducible example?您能否重新配置您的 CI 系统以生成文本而不是图像的错误消息,并在问题中包含文本格式错误? 【参考方案1】:

如果您在 Ubuntu 上部署,请勿使用 Alpine 映像。

那么为什么会出现这个问题呢?

两者的基本C standard library 实现不同(Alpine 使用musl libc;Ubuntu 和所有其他发行版或多或少都使用GNU C Library (glibc))。

尝试将针对一个 libc 实现构建的二进制文件(例如可能出现在 node_modules 中的原生模块的二进制文件)移动到使用另一个 libc 实现的系统可能会很痛苦或根本不起作用(如您所见)。

我的 docker-container 中必须有相同的 Linux 发行版和版本才能适应所有依赖项吗?

如果没有任何依赖项使用本机代码,那么您应该能够毫无问题地移动内容,但否则将是最简单的(例如,考虑您的依赖项可能链接的其他库的版本)只使用与您的目标操作系统版本相同 - 或者,如果您不想考虑,只需将您的应用程序部署为 Docker 容器。

【讨论】:

【参考方案2】:

即使@AKX 的建议是一个很好的答案,我也尝试了一些方法来弄清楚如何解决这种特殊情况。

这是我的解决方案:

    在服务器上安装musl-dev 将其链接到 /lib
apt-get install musl-dev
ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1

在我的情况下,只有这个单一的依赖会导致麻烦。如果我得到更多这个,我会按照 AKX 的建议,选择一个 debian/ubuntu-like 发行版来捆绑它。

【讨论】:

只是好奇:您是否有特定的理由在 CI 中运行 Alpine? 最小化 gitlab 项目所需的 CI/CD 构建时间,以尽可能好地为该项目使用免费层。 您是否测量过使用常规的node:14 图像会慢得多?慢的部分是什么?

以上是关于Docker、AlpineLinux 和 Ubuntu - 为啥`node_modules` 不同的主要内容,如果未能解决你的问题,请参考以下文章

docker --Docker微容器Alpine Linux

构建属于自己的 jre Docker 镜像

docker自定义镜像上传阿里云

Docker之Alpine制作镜像且上传至阿里云

安卓docker使用Alpine Term

Docker镜像的管理和创建