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:

> [email protected] 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 [email protected]
node-pre-gyp info using [email protected] | 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 [email protected] and [email protected] (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 [email protected]
gyp info using [email protected] | linux | x64
gyp info ok
gyp info it worked if it ends with ok
gyp info using [email protected]
gyp info using [email protected] | 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 [email protected]
gyp info using [email protected] | 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
3
  • Couldn't reproduce it, works for me in Docker 4 Mac 1.12.3 (13776). Commented Dec 7, 2016 at 22:30
  • Thanks for testing. Did a Docker reset, which didn't help. Commented Dec 7, 2016 at 23:17
  • I get these errors on my mac and when installing on a heroku dyno with version 1.0.1, but 0.8.7 installs without errors. I am not sure why the latest npm install is referencing that url which is no longer, might be an issue Commented Dec 8, 2016 at 8:16

5 Answers 5

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/
Sign up to request clarification or add additional context in comments.

Comments

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/

6 Comments

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.
Do you have the volume mapping active?
You should add this to your answer: stackoverflow.com/questions/29181032/… It shows how you remove a directory from the mapping. It was necessary because using .dockerignore was not effective for me.
@MattJensen That's exactly how I solved it in the end. Added it to my answer.
For the path "/app/node_modules", would that be relative to the project directory?
|
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

Comments

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.

2 Comments

replaced it in what way? Can you clarify the answer
Hi @pokumars, replace the folders by the linux version of the folders
0

Other answers hint at a setup using Compose volumes: to inject code into your container. This isn't necessary, though: in between the Dockerfile COPY command RUN npm install, all of the source code and library tree is already built into the image. Using volumes: to replace these means you're running artifacts from your local system, and that can result in wrong-architecture errors like you're seeing. Putting node_modules in an anonymous volume apparently hides this problem, but it means your Docker setup will ignore changes to package.json, and you're still not running any of the code that's actually in the image.

If your Compose file has a volumes: section that overwrites the image code, delete it.

version: '3.8'
services:
  myapp:
    build: .
    ports: ['3000:3000']
    # volumes:               # delete this entirely:
    #   - .:/app             #   use the code in the image
    #   - /app/node_modules  #   and do not try to treat the library tree as user data

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.