Search code examples
node.jsdockerwebpack-dev-servernode-sasswebpack-style-loader

Node/Docker is node-sass not finding installed bindings (via Webpack)


I'm struggling to get the webpack dev server setup in a docker container based on node:latest

Despite trying all the various incantations in Node Sass could not find a binding for your current environment, I keep getting the same error:

web_1         | ERROR in ./~/css-loader!./~/sass-loader/lib/loader.js!./src/sass/style.sass
web_1         | Module build failed: Error: Missing binding /prject/node_modules/node-sass/vendor/linux-x64-59/binding.node
web_1         | Node Sass could not find a binding for your current environment: Linux 64-bit with Node.js 9.x
web

here's the current

# Dockerfile
RUN yarn cache clean && yarn install --non-interactive --force
RUN rm -rf node_modules/node_sass
RUN npm rebuild node-sass

the rebuild step suggests that the binary is installed and checks out:

Binary found at /advocate/node_modules/node-sass/vendor/linux-x64-59/binding.node
Testing binary
Binary is fine

Also confusing to me is that I do get this

web_1         | Found bindings for the following environments:
web_1         |   - OS X 64-bit with Node.js 7.x

which makes me think it's using the host platform in some capacity that I don't quite follow.


Solution

  • The state of the node_modules directory is being taken from the development host into the container. This is an issue when platform based decisions have been made during an npm/yarn install, normally modules that use native code.

    Dockerfile builds

    Add node_modules to your .dockerignore file. The install will take a bit longer in the container but you should never get any cross over between your dev environment and container.

    Mounted Development Volumes

    Mounting your development code with node_modules into the container can also cause the same problems. Running a yarn install --force on the new platform before using it should normally be enough to switch it over/back.

    There's not a simple way to ignore a directory when mounting a volume. You could mount every directory/file in your project individually and then ignore node_modules but that's a lot of work.

    Syncing Development Volumes

    This is a way to avoid mounting volumes. docker-sync has an rsync strategy that can ignore files. This might also speed some apps up that have heavy file access patterns. File access is slow on volumes mounted from osx > vm > docker.

    version: '2'
    
    options:
      verbose: true
    
    syncs:
      yourproject_data:
        sync_strategy: 'rsync'
        src: './'
        sync_host_port: 10872
        sync_args: '-v' 
        sync_excludes:
          - '.sass-cache/'
          - 'sass-cache/'
          - 'vendor/'
          - 'bower_components/'
          - 'node_modules/'
          - '.git/'
    

    File deletion doesn't sync to the container by default though, which you need to take into consideration. I do an occasional delete of the synced volume when I need things cleaned up.