Docker node app failing

Expected behavior

Node app that runs on Windows already, but uses remote DB for development. Expected to set up docker environment with node app running and linking to a local database instance. App uses nodemon to restart often during development.

Actual behavior

App fails to install because of binary modules, ELF headers are wrong because it uses windows version. So remove node_modules and reinstall. Then fails due to trying to create symlinks, so pass -no-bin-links to npm but this causes max call stack error (as per https://github.com/npm/npm/issues/10776)

Implement loop that handles this in shell script, but then app fails due to BCrypt bindings not being found:

web_1  | Error: Could not locate the bindings file. Tried:
web_1  |   /app/node_modules/bcrypt/build/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/build/Debug/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/build/Release/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/out/Debug/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/Debug/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/out/Release/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/Release/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/build/default/bcrypt_lib.node
web_1  |   /app/node_modules/bcrypt/compiled/4.4.3/linux/x64/bcrypt_lib.node
web_1  |     at bindings (/app/node_modules/bindings/bindings.js:88:9)
web_1  |     at Object.<anonymous> (/app/node_modules/bcrypt/bcrypt.js:3:35)
web_1  |     at Module._compile (module.js:409:26)
web_1  |     at Object.Module._extensions..js (module.js:416:10)
web_1  |     at Module.load (module.js:343:32)
web_1  |     at Function.Module._load (module.js:300:12)
web_1  |     at Function.Module._load (/app/node_modules/require-in-the-middle/index.js:22:24)
web_1  |     at Module.require (module.js:353:17)
web_1  |     at require (internal/module.js:12:17)
web_1  |     at Object.<anonymous> (/app/server/plugins/auth/lib/auth.js:1:78)
web_1  |     at Module._compile (module.js:409:26)
web_1  |     at Object.Module._extensions..js (module.js:416:10)
web_1  |     at Module.load (module.js:343:32)
web_1  |     at Function.Module._load (module.js:300:12)
web_1  |     at Function.Module._load (/app/node_modules/require-in-the-middle/index.js:22:24)
web_1  |     at Module.require (module.js:353:17)
web_1  |     at require (internal/module.js:12:17)
web_1  |     at Object.<anonymous> (/app/server/plugins/auth/index.js:9:14)
web_1  |     at Module._compile (module.js:409:26)
web_1  |     at Object.Module._extensions..js (module.js:416:10)
web_1  |     at Module.load (module.js:343:32)
web_1  |     at Function.Module._load (module.js:300:12)
web_1  |     at Function.Module._load (/app/node_modules/require-in-the-middle/index.js:22:24)
web_1  |     at Module.require (module.js:353:17)
web_1  |     at require (internal/module.js:12:17)
web_1  |     at Object.exports.compose.steps.push.steps.push.steps.push.steps.push.internals.parsePlugin (/app/node_modules/glue/lib/index.js:185:23)
web_1  |     at /app/node_modules/glue/lib/index.js:113:39
web_1  |     at Array.map (native)
web_1  |     at /app/node_modules/glue/lib/index.js:110:58
web_1  |     at /app/node_modules/glue/lib/index.js:129:9
web_1  |     at iterate (/app/node_modules/items/lib/index.js:36:13)
web_1  |     at done (/app/node_modules/items/lib/index.js:28:25)
web_1  |     at /app/node_modules/glue/lib/index.js:101:13
web_1  |     at /app/node_modules/glue/lib/index.js:129:9
web_1  |     at iterate (/app/node_modules/items/lib/index.js:36:13)
web_1  |     at done (/app/node_modules/items/lib/index.js:28:25)
web_1  |     at /app/node_modules/glue/lib/index.js:92:9
web_1  |     at /app/node_modules/glue/lib/index.js:129:9
web_1  |     at iterate (/app/node_modules/items/lib/index.js:36:13)
web_1  |     at done (/app/node_modules/items/lib/index.js:28:25)
web_1  |     at /app/node_modules/glue/lib/index.js:74:13
web_1  |     at /app/node_modules/glue/lib/index.js:129:9
web_1  |     at iterate (/app/node_modules/items/lib/index.js:36:13)
web_1  |     at Object.exports.serial (/app/node_modules/items/lib/index.js:39:9)
web_1  |     at Object.exports.compose.steps.push.steps.push.steps.push.steps.push.Items.serial [as compose] (/app/node_modules/glue/lib/index.js:127:11)
web_1  |     at /app/server/index.js:12:10
web_1  |     at new wrappedPromise (/app/node_modules/opbeat/lib/instrumentation/async-hooks.js:337:18)
web_1  |     at module.exports.Glue.compose.server.on.server.app.runQuery.Promise (/app/server/index.js:10:10)
web_1  |     at Object.<anonymous> (/app/index.js:16:1)
web_1  |     at Module._compile (module.js:409:26)
web_1  |     at Object.Module._extensions..js (module.js:416:10)
web_1  |     at Module.load (module.js:343:32)
web_1  |     at Function.Module._load (module.js:300:12)
web_1  |     at Function.Module.runMain (module.js:441:10)
web_1  |     at startup (node.js:139:18)
web_1  |     at node.js:968:3

Information

Dockerfile:

FROM node:4

EXPOSE 10000
EXPOSE 5858

COPY ./ /app
WORKDIR /app

docker-compose.yml

version: '2'
services:
  web:
    build: .
    command: ./bin/docker-run-local.sh
    ports:
      - "10000:10000"
      - "5858:5858"
    depends_on:
      - db
    volumes:
      - .:/app
    environment:
      NODE_ENV: 'local'

  db:
    image: mysql:5.6
    environment:
      MYSQL_DATABASE: 'local_db'
      MYSQL_ROOT_PASSWORD: 'password'

docker-run-local.sh

#!/usr/bin/env bash

npm install -g npm@latest

NPM=-1
GUARD=20
COUNTER=1
until [ ${NPM} -eq 0 ] || [ ${COUNTER} -gt ${GUARD} ]; do
  npm i --no-bin-links
  let NPM=$?
  let COUNTER+=1
done

node --debug=5858 index.js --color=always

Command to start:

nodemon -x docker-compose up

Steps to reproduce the behavior

See above config files, create app that include a binary module like BCrypt that requires bindings to be used.