5

I've seen several questions regarding macOS, Docker and bcrypt on Node.js. This seems the closest answer to my problem but it didn't work.

My Dockerfile:

FROM node:6.4.0

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

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

My .dockerignore file:

node_modules

My package.json dependencies:

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

When starting the container, I get this error:

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

From the ls -la /app command in the Dockerfile I can see that the node_modules folder definitely isn't copied from the host (macOS):

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

The bcrypt npm install log:

> 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

Update: I tried to run bcrypt inside the container which seems to work fine:

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
Community
  • 1
  • 1
Alexander Zeitler
  • 11,919
  • 11
  • 81
  • 124

4 Answers4

5

The comment from Stefan Scherer has shown that my code in the question is valid and should work and made me search for other causes of the problem.

In the end I found out that it is caused by the docker-compose.yml which started the container as part of multiple services.

The problem was caused by this volume entry for the container:

volumes :
- ../identity/:/app

Thus the node_modules folder from the host again is mapped into the container and the bcrypt ELF header is indeed invalid again.

The solution is to exclude the node_modules folder from the mapping (as also explained here):

volumes :
    /app/node_modules/
Alexander Zeitler
  • 11,919
  • 11
  • 81
  • 124
  • I have the same issue but what was your solution to it? I launch the build (`npm install`) inside the container but still get the ELF error even after removing the node_modules directory locally. – mistertee Jan 12 '17 at 09:03
  • Do you have the volume mapping active? – Alexander Zeitler Jan 12 '17 at 12:10
  • You should add this to your answer: https://stackoverflow.com/questions/29181032/add-a-volume-to-docker-but-exclude-a-sub-folder#answer-37898591 It shows how you remove a directory from the mapping. It was necessary because using .dockerignore was not effective for me. – Matt Jensen Sep 07 '18 at 20:16
  • 1
    @MattJensen That's exactly how I solved it in the end. Added it to my answer. – Alexander Zeitler Sep 08 '18 at 13:33
  • For the path "/app/node_modules", would that be relative to the project directory? – user1790300 Jan 27 '19 at 16:52
  • In my case it’s the path declared as WORKDIR in the Dockerfile so it is the project directory. – Alexander Zeitler Jan 27 '19 at 19:32
5

I have found that excluding the entire local node_modules directory does not allow you to install npm packages and have your docker container track those changes in the container on the fly. In order to have other package changes tracked specify only the bcrypt directory in the container volume:

volumes: 
  - .:/app
  - /app/node_modules/bcrypt/
Andrew Quartey
  • 101
  • 2
  • 7
0

The root cause is => Docker Context. Docker context is copying everything from your root folder to destination container working directory.

So your node_modules (& loading mechanism as per your host OS) is also copied to container working directory.

So you have to add a .dockerignore file and add these entries (with any other files that you want to ignore)

  • node_modules
  • npm-debug.log

And now when you will build your container, it will build everything as per container's OS and you will not get invalid ELF header error

0

After hours, I've found out the root cause.

In my case, I used Docker, I ran docker-compose up to start my app. I built the my code in Linux and then committed code, then I pulled the code and ran the code with Docker in Window and I faced the problem.

My solution after hours google searched was:

I replace folder /node_modules/bcrypt and /node_modules/bcrypt-pbkdf (in Windows) by the folder bcrypt and bcrypt-pbkdf from my Linux PC.

Than I ran docker-composed up again and it worked.

Hope my share can have people who are facing the problem can save their time.

dqthe
  • 683
  • 5
  • 8