ELF Header or installation issue with bcrypt in Docker container
Asked Answered
S

3

9

Kind of a longshot, but has anyone had any problems using bcrypt in a linux container (specifically docker) and know of an automated workaround? I have the same issue as these two:

Invalid ELF header with node bcrypt on AWSBox

bcrypt invalid elf header when running node app

My Dockerfile

# Pull base image
FROM node:0.12

# Expose port 8080
EXPOSE 8080

# Add current directory into path /data in image
ADD . /data

# Set working directory to /data
WORKDIR /data

# Install dependencies from package.json
RUN npm install --production

# Run index.js
CMD ["npm", "start"]

I get the previously mentioned invalid ELF header error if I have bcrypt already installed in my node_modules, but if I remove it (either just itself or all my packages), it isn't installed for some reason when I build the container. I have to manually enter the container after the build and install it inside.

Is there an automated workaround?

Or maybe, just, what would be a good alternative to bcrypt with a Node stack?

Stigmatize answered 24/7, 2015 at 7:10 Comment(4)
is node_modules/ in your .dockerignore file?Fraxinella
it's not, although that's a good reminder to make oneStigmatize
Whoa Liam, I didn't even realize that was you! Thanks for taking a look.Stigmatize
Haha I had this problem a week ago. Installing the dependencies inside the container, as opposed to copying the current directory (deps included) to the container, solved the issue for me.Fraxinella
C
9

Liam's comment is on the money, just expanding on it for future travellers on the internets.

The issue is that you've copied your node_modules folder into your container. The reason that this is a problem is that bcrypt is a native module. It's not just javascript, but also a bunch of C code that gets compiled at the time of installation.

The binaries that come out of that compilation get stored in the node_modules folder and they're customised to the place they were built. Transplanting them out of their OSX home into a strange Linux land causes them to misbehave and complain about ELF headers and fairy feet.

The solution is to echo node_modules >> .dockerignore and run npm install as part of your Dockerfile. This means that the native modules will be compiled inside the container rather than outside it on your laptop.

With this in place, there is no need to run npm install before your start CMD. Just having it in the build phase of the Dockerfile is fine.

protip: the official node images set NODE_ENV=production by default, which npm treats the same as the --production flag. Most of the time this is a good thing. It is not a good thing when your Dockerfile also contains some build steps that rely on dev dependencies (webpack, etc). In that case you want NODE_ENV=null npm install

pro protip: you can take better advantage of Docker's caching by copying in your package.json separately to the rest of your code. Make your Dockerfile look like this:

# Pull base image
FROM node:0.12

# Expose port 8080
EXPOSE 8080

# Set working directory to /data
WORKDIR /data

# Set working directory to /data
COPY package.json /data

# Install dependencies from package.json
RUN npm install

# Add current directory into path /data in image
ADD . /data

# Run index.js
CMD npm start

And that way Docker will only re-run npm install when you change your package.json, not every time you change a line of code.

Chandler answered 1/6, 2016 at 6:43 Comment(0)
S
3

Okay, so I have a working automated workaround:

Call npm install --production in the CMD instruction. I'm going to wave my hands at figuring out why I have to install bcrypt at the time of executing the container, but it works.

Updated Dockerfile

# Pull base image
FROM node:0.12

# Expose port 8080
EXPOSE 8080

# Add current directory into path /data in image
ADD . /data

# Set working directory to /data
WORKDIR /data

# Install dependencies from package.json
RUN npm install --production

# Run index.js
CMD npm install --production; npm start
Stigmatize answered 24/7, 2015 at 8:6 Comment(1)
Ignoring node_modules per the comments to the question above is the correct approach. Also note that if you're using docker-compose version < 1.5 it doesn't handle .dockerignore correctly.Scene
J
0

Add this command before RUN npm install in your Dockerfile

RUN apk --no-cache add --virtual builds-deps build-base python3

It worked for me. Maybe it will work for you :)

Jean answered 26/7, 2021 at 15:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.