bcrypt 和 Docker bcrypt_lib.node:无效的ELF头部

5

我看到了一些关于macOS、Docker和Node.js中bcrypt的问题。 这个 答案似乎是最接近我的问题,但它没有奏效。

我的Dockerfile

FROM node:6.4.0

COPY . /app
RUN ls -la /app
WORKDIR /app

RUN cd /app; npm install
CMD ["node", "index.js"]

我的.dockerignore文件:

node_modules

我的package.json依赖项:

"dependencies": {
  "bcrypt": "1.0.0",
}

启动容器时,我遇到了这个错误:

/app/node_modules/bcrypt/build/Release/bcrypt_lib.node: invalid ELF header

通过在 Dockerfile 中运行 ls -la /app 命令,我可以看到主机(macOS)上的 node_modules 文件夹肯定没有被复制:

drwxr-xr-x  6 root root  4096 Dec  7 21:29 .
drwxr-xr-x 47 root root  4096 Dec  7 21:29 ..
-rw-r--r--  1 root root   763 Dec  7 20:55 .dockerignore
-rw-r--r--  1 root root   122 Dec  7 21:18 Dockerfile
rw-r--r--  1 root root 13525 Dec  7 19:43 index.js
-rw-r--r--  1 root root   947 Dec  7 21:28 package.json
bcryptnpm install日志:
> bcrypt@1.0.0 install /app/node_modules/bcrypt
> node-pre-gyp install --fallback-to-build

node-pre-gyp info it worked if it ends with ok
node-pre-gyp info using node-pre-gyp@0.6.30
node-pre-gyp info using node@6.4.0 | linux | x64
node-pre-gyp info check checked for "/app/node_modules/bcrypt/lib/binding/bcrypt_lib.node" (not found)
node-pre-gyp http GET https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.0/bcrypt_lib-v1.0.0-node-v48-linux-x64.tar.gz
node-pre-gyp http 404 https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.0/bcrypt_lib-v1.0.0-node-v48-linux-x64.tar.gz
node-pre-gyp ERR! Tried to download: https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.0/bcrypt_lib-v1.0.0-node-v48-linux-x64.tar.gz
node-pre-gyp ERR! Pre-built binaries not found for bcrypt@1.0.0 and node@6.4.0 (node-v48 ABI) (falling back to source compile with node-gyp)
node-pre-gyp http Pre-built binary not available for your system, looked for https://github.com/kelektiv/node.bcrypt.js/releases/download/v1.0.0/bcrypt_lib-v1.0.0-node-v48-linux-x64.tar.gz
gyp info it worked if it ends with ok
gyp info using node-gyp@3.3.1
gyp info using node@6.4.0 | linux | x64
gyp info ok
gyp info it worked if it ends with ok
gyp info using node-gyp@3.3.1
gyp info using node@6.4.0 | linux | x64
gyp info spawn /usr/bin/python2
gyp info spawn args [ '/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args   'binding.gyp',
gyp info spawn args   '-f',
gyp info spawn args   'make',
gyp info spawn args   '-I',
gyp info spawn args   '/app/node_modules/bcrypt/build/config.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/root/.node-gyp/6.4.0/include/node/common.gypi',
gyp info spawn args   '-Dlibrary=shared_library',
gyp info spawn args   '-Dvisibility=default',
gyp info spawn args   '-Dnode_root_dir=/root/.node-gyp/6.4.0',
gyp info spawn args   '-Dnode_gyp_dir=/usr/local/lib/node_modules/npm/node_modules/node-gyp',
gyp info spawn args   '-Dnode_lib_file=node.lib',
gyp info spawn args   '-Dmodule_root_dir=/app/node_modules/bcrypt',
gyp info spawn args   '--depth=.',
gyp info spawn args   '--no-parallel',
gyp info spawn args   '--generator-output',
gyp info spawn args   'build',
gyp info spawn args   '-Goutput_dir=.' ]
gyp info ok
gyp info it worked if it ends with ok
gyp info using node-gyp@3.3.1
gyp info using node@6.4.0 | linux | x64
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory '/app/node_modules/bcrypt/build'
  CXX(target) Release/obj.target/bcrypt_lib/src/blowfish.o
  CXX(target) Release/obj.target/bcrypt_lib/src/bcrypt.o
  CXX(target) Release/obj.target/bcrypt_lib/src/bcrypt_node.o
  SOLINK_MODULE(target) Release/obj.target/bcrypt_lib.node
  COPY Release/bcrypt_lib.node
  COPY /app/node_modules/bcrypt/lib/binding/bcrypt_lib.node
  TOUCH Release/obj.target/action_after_build.stamp
make: Leaving directory '/app/node_modules/bcrypt/build'
gyp info ok
node-pre-gyp info ok

更新: 我尝试在容器内运行bcrypt,看起来可以正常工作:
docker run identity file /app/node_modules/bcrypt/build/Release/bcrypt_lib.node
/app/node_modules/bcrypt/build/Release/bcrypt_lib.node: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=2a9d4a04f6f9c548f8035b9b737c1efac5d774d2, not stripped

无法重现,我在 Docker 4 Mac 1.12.3 (13776) 上运行正常。 - Stefan Scherer
感谢您的测试。进行了Docker重置,但没有帮助。 - Alexander Zeitler
我在我的 Mac 上安装和在 Heroku dyno 上安装版本 1.0.1 时都遇到了这些错误,但是 0.8.7 可以顺利安装。我不确定为什么最新的 npm 安装会引用那个已经不存在的 URL,可能存在问题。 - poutyboi
4个回答

5

Stefan Scherer的评论表明我的问题代码是有效的并且应该可以工作,并促使我寻找问题的其他原因。

最终,我发现这是由于启动容器的docker-compose.yml文件中将容器作为多个服务的一部分的原因。

该问题是由于容器的此volume条目引起的:

volumes :
- ../identity/:/app

因此,主机上的node_modules文件夹再次映射到容器中,bcrypt ELF头确实无效。
解决方法是从映射中排除node_modules文件夹(如这里所述)。
volumes :
    /app/node_modules/

我也遇到了同样的问题,但你是怎么解决的呢?我在容器内启动构建(npm install),但即使在本地删除了node_modules目录,仍然会出现ELF错误。 - mistertee
你是否已经启用了卷映射? - Alexander Zeitler
你应该将以下内容添加到你的答案中: https://dev59.com/OF4b5IYBdhLWcg3waA5P。它展示了如何从映射中删除一个目录,因为使用.dockerignore对我来说并不起作用。 - Matt Jensen
1
@MattJensen 这正是我最终解决它的方法。我将其添加到了我的答案中。 - Alexander Zeitler
对于路径“/app/node_modules”,它是相对于项目目录的吗? - user1790300
在我的情况下,它是在Dockerfile中声明为WORKDIR的路径,因此它是项目目录。 - Alexander Zeitler

5

我发现如果完全排除本地的 node_modules 目录,你将无法安装 npm 包,并使你的 Docker 容器实时跟踪这些更改。为了让其他包更改被跟踪,请只在容器卷中指定 bcrypt 目录:

volumes: 
  - .:/app
  - /app/node_modules/bcrypt/

0
经过数小时的努力,我找到了根本原因。
在我的情况下,我使用了Docker,运行了docker-compose up来启动我的应用程序。我在Linux中构建了我的代码,然后提交了代码,接着在Windows中使用Docker拉取并运行代码时遇到了问题。
经过数小时的谷歌搜索,我的解决方案是:
我将Windows中的文件夹/node_modules/bcrypt/node_modules/bcrypt-pbkdf替换为来自我的Linux PC的文件夹bcryptbcrypt-pbkdf
然后我再次运行docker-composed up,它就可以正常工作了。
希望我的分享能够帮助那些遇到类似问题的人节省时间。

你是怎么替换它的?你能解释一下答案吗? - undefined

0
根本原因是 => Docker 上下文。Docker 上下文将您的根文件夹中的所有内容复制到目标容器的工作目录。
因此,您的 node_modules(以及根据主机操作系统的加载机制)也会被复制到容器的工作目录中。
因此,您必须添加一个 .dockerignore 文件并添加这些条目(以及您想要忽略的任何其他文件)。
  • node_modules
  • npm-debug.log

现在,当您构建容器时,它将根据容器的操作系统构建所有内容,您将不会收到无效的ELF头错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接