node.jsdockerbcryptmacos-sierra

bcrypt and Docker bcrypt_lib.node: invalid ELF header


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

Solution

  • 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/