21

I'm attempting to dockerise my node application. My current application is a nodejs express server with postgresql. ExpressJS uses node-sass-middleware to handle the sass assets. When I run node and postgresql locally on my OSX machine everything works fine. When I try to run the app with docker-compose I get a "Missing Binding error"

Here is my Dockerfile:

FROM node:7.2.1
RUN apt-get update -qq && apt-get install -y build-essential
RUN apt-get install -y libpq-dev postgresql-client
ENV APP_HOME /my_app
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
ADD package.json .
RUN npm install
RUN npm rebuild node-sass
ADD . .
CMD [ "npm", "start" ]
EXPOSE 3000

Here is my docker-compose.yml file:

version: '2'
services:
    db:
      image: postgres:9.6.1
      ports:
        - '5432:5432'
    web:
      build: . # use the Dockerfile next to this file
      volumes:
        - .:/my_app
      ports:
        - "3000:3000"
      depends_on:
        - db

When I run docker-compose up I still get the following error:

web_1  | [nodemon] 1.11.0
web_1  | [nodemon] to restart at any time, enter `rs`
web_1  | [nodemon] watching: *.*
web_1  | [nodemon] starting `node ./bin/www`
web_1  | /my_app/node_modules/node-sass/lib/binding.js:15
web_1  |       throw new Error(errors.missingBinary());
web_1  |       ^
web_1  |
web_1  | Error: Missing binding /my_app/node_modules/node-sass/vendor/linux-x64-51/binding.node
web_1  | Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 7.x
web_1  |
web_1  | Found bindings for the following environments:
web_1  |   - OS X 64-bit with Node.js 7.x
web_1  |
web_1  | This usually happens because your environment has changed since running `npm install`.
web_1  | Run `npm rebuild node-sass` to build the binding for your current environment.
web_1  |     at module.exports (/my_app/node_modules/node-sass/lib/binding.js:15:13)
web_1  |     at Object.<anonymous> (/my_app/node_modules/node-sass/lib/index.js:14:35)
web_1  |     at Module._compile (module.js:571:32)
web_1  |     at Object.Module._extensions..js (module.js:580:10)
web_1  |     at Module.load (module.js:488:32)
web_1  |     at tryModuleLoad (module.js:447:12)
web_1  |     at Function.Module._load (module.js:439:3)
web_1  |     at Module.require (module.js:498:17)
web_1  |     at require (internal/module.js:20:19)
web_1  |     at Object.<anonymous> (/my_app/node_modules/node-sass-middleware/middleware.js:3:12)
web_1  |     at Module._compile (module.js:571:32)
web_1  |     at Object.Module._extensions..js (module.js:580:10)
web_1  |     at Module.load (module.js:488:32)
web_1  |     at tryModuleLoad (module.js:447:12)
web_1  |     at Function.Module._load (module.js:439:3)
web_1  |     at Module.require (module.js:498:17)
web_1  | [nodemon] app crashed - waiting for file changes before starting...

I though by adding RUN npm rebuild node-sass to the Dockerfile, it would build the correct binding for the OS in the docker container... But it does not seem to work.

Any thoughts?

jubeless
  • 351
  • 1
  • 3
  • 5

6 Answers6

13

The support for Node.js 7 (for Linux and OSX) seems to have been added in node-sass v3.7.0. Make sure you use a version equal to or newer than this.

Either you can update your Dockerfile:

FROM node:7.2.1
RUN apt-get update -qq && apt-get install -y build-essential
RUN apt-get install -y libpq-dev postgresql-client
ENV APP_HOME /my_app
RUN mkdir $APP_HOME
WORKDIR $APP_HOME
ADD package.json .

# Add the two entries below
RUN mkdir -p node_modules/node-sass/vendor/linux-x64-51
RUN curl -L https://github.com/sass/node-sass/releases/download/v4.5.0/linux-x64-51_binding.node -o node_modules/node-sass/vendor/linux-x64-51/binding.node

RUN npm install
RUN npm rebuild node-sass
ADD . .
CMD [ "npm", "start" ]
EXPOSE 3000

Or you can download the binding locally and then build from the Dockerfile without any modification:

cd /path/to/node_app/node_modules
mkdir -p node-sass/vendor/linux-x64-51
curl -L https://github.com/sass/node-sass/releases/download/v4.5.0/linux-x64-51_binding.node -o node-sass/vendor/linux-x64-51/binding.node

Keep an eye out for different versions for the pre-compiled native bindings at: https://github.com/sass/node-sass/releases

Nehal J Wani
  • 16,071
  • 3
  • 64
  • 89
  • I manage to get the binding file locally and built from the Dockerfile, however the new error I'm getting now is: `web_1 | Error: /my_app/node_modules/node-sass/vendor/linux-x64-51/binding.node: invalid ELF header` Thoughts? – jubeless Jan 30 '17 at 22:15
  • Don't pull stuff on the binaries repo, it's just a scratchpad for the maintainers that will go away. If you're going to curl the binaries, use the GH releases attachments – nschonni Feb 01 '17 at 03:00
  • Using the GH releases attachement did not solve the issue. I'm still getting the error: `Error: /my_app/node_modules/node-sass/vendor/linux-x64-51/binding.node: invalid ELF header` – jubeless Feb 02 '17 at 16:39
  • Which version of node-sass are you using? – Nehal J Wani Feb 02 '17 at 17:00
  • If you're running Alpine, then you'll need the "Musl" variant linux_musl-x64-51_binding.node – nschonni Feb 02 '17 at 19:56
  • I just realized my mistake in the answer. It should have been `curl -L` and not just `curl`. @jubeless Please try again. @nschonni , docker image for node:7.2.1 uses debian8. – Nehal J Wani Feb 03 '17 at 04:11
  • Could you have a look at my question here please: https://stackoverflow.com/questions/60153462/node-sass-could-not-find-a-binding-for-your-current-environment-linux-64-bit-wi +1. – w0051977 Feb 10 '20 at 15:44
  • Any help `node-sass:6.0.0` Failing to build an image tried to use your curl command to get node-sass binding but curl also fails on `node:14.x` base image but does work if base image is on `ubuntu` something wrong to build an image but works on local machine. https://stackoverflow.com/a/69477720/6618218 – khizer Oct 07 '21 at 08:22
10

I have encountered this problem a few times when running my apps within Docker. I believe the problem arises when mounting my local app directory with Docker as this includes the node_modules folder which have been built in a different environment.

My local setup is Mac OSX while Docker is running in linux.

The solution for me was to add a .dockerignore file in the root of my app and add node_modules as per this suggestion https://stackoverflow.com/a/55657576/3258059

I then needed to trigger yarn install to run again in my docker container and also ran the node-sass rebuild command with the docker container: docker-compose run web npm rebuild node-sass where web is the name of my docker container.

I suspect my Dockerfile may have a bit of bloat but I will add in case it helps someone:

FROM ruby:2.3.7
ENV BUNDLER_VERSION=1.17.3
RUN gem install bundler -v "$BUNDLER_VERSION" --no-document
RUN curl -sL https://deb.nodesource.com/setup_8.x | bash -  
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -   
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list   
RUN apt-get update -qq && apt-get install -y nodejs yarn build-essential libpq-dev postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
ENV RAILS_ENV docker    
ENV WEBPACKER_DEV_SERVER_PUBLIC localhost:3035  
ENV WEBPACKER_DEV_SERVER_HOST localhost 
COPY package.json *yarn* ./
RUN bundle install
RUN yarn install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

and my docker-compose.yml

version: '3'
services:
  db:
    image: postgres
    ports: 
      - "5433:5432"
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
  web:
    build: .
    environment: 
      - RAILS_ENV=development
      - NODE_ENV=development
      - WEBPACKER_DEV_SERVER_PUBLIC=localhost:3035
      - WEBPACKER_DEV_SERVER_HOST=localhost
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
      - redis
      #- elasticsearch
  redis:
    image: redis:alpine
whatapalaver
  • 865
  • 13
  • 25
  • 1
    second this solution, worked for me. More about my situation: angular-cli uses node-sass 4.9.3, my macos has node 12; while in container I have node 10 and is debian (make sure your node-sass plays well with your node version - saw several people got caught by this). Exclude `node_module` in `.dockerignore`, do a node-sass rebuild, then TA-DA - it worked. – Shawn Jul 04 '19 at 05:47
  • thanks, `ENV RAILS_ENV docker` doesn't sound right, `ENV RAILS_ENV development` makes more sense, until you go to prod – ecoologic Nov 07 '19 at 11:39
  • You are probably right. I set up a separate environment as not all our devs are using Docker at the moment and I didn't want to interfere with their setup. – whatapalaver Nov 07 '19 at 13:39
  • Thanks very much, the .dockerignore of node_modules did the trick. I didn't appear to need a node-sass rebuild on my end with node 10.16.3 // node-sass 4.13.0, but happily seeing nodemon restarting the docker-compose owned express procs with changes to osx dev env. You rescued me from a brain scratcher :+1: – kian Nov 15 '19 at 05:56
0

I was able to solve this problem by changing:

RUN npm rebuild node-sass

to:

RUN npm rebuild node-sass --sass-binary-name = linux-x64-83

Pointing out which distro to run. In my case I had to see which version I was requesting, which in this case is Linux x64-83.

Here is the list of versions that may exist: https://github.com/sass/node-sass/releases

allenski
  • 1,652
  • 4
  • 23
  • 39
0

I did this for docker, yarn and react

# pull the base image
FROM node:lts-alpine

# set the working direction
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# install app dependencies
COPY package.json ./

COPY yarn.lock ./

# rebuild node-sass
RUN yarn add node-sass

RUN yarn

# add app
COPY . ./

# start app
CMD ["yarn", "start"]
Ian Samz
  • 1,743
  • 20
  • 20
0

for a newbie like me

step 1 : open terminal from docker container

enter image description here

Step 2: then run command `npm rebuild node-sass

enter image description here

Step 3: Restart the container after this it should work

enter image description here

Yusuf Khan
  • 3,032
  • 3
  • 24
  • 31
0

I have a similar error, only when I run the docker container on a Linux machine, in MAC is working perfect!! I think it could be related to the paths? But I am not sure.

ERROR in ./node_modules/slick-carousel/slick/slick.css
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleError: Module Error (from ./node_modules/sass-loader/dist/cjs.js):
globalThis is not defined
    at Object.emitError (/var/www/html/webroot/node_modules/webpack/lib/NormalModule.js:614:6)
    at getSassImplementation (/var/www/html/webroot/node_modules/sass-loader/dist/utils.js:60:21)
    at Object.loader (/var/www/html/webroot/node_modules/sass-loader/dist/index.js:35:59)
 @ ./admin/js/react/templates/Events/EventsList.js 15:0-40
 @ ./admin/js/react/templates/Events/Events.js 10:0-38 119:39-49
 @ ./admin/js/index.js 232:11-58

86 ERRORS in child compilations (Use 'stats.children: true' resp. '--stats-children' for more details)
R0bertinski
  • 517
  • 6
  • 12