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
造成的。
我已将它安装在我的 server
和 docker
-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` 不同的主要内容,如果未能解决你的问题,请参考以下文章