infinitered / nsfwjs

NSFW detection on the client-side via TensorFlow.js
https://nsfwjs.com/
MIT License
7.89k stars 524 forks source link

NSFW through Docker reports an error - maybe provide Docker support? #859

Open DavidGarciaCat opened 3 months ago

DavidGarciaCat commented 3 months ago

Good day,

I have tried to use this library through a Docker container, but it seems to fail.

My setup includes AMQP + MariaDB so

If I run the source code locally (on my host machine) the process seems to work as expected:

node consumer/nsfwjs.js
[x] NSFW Model "file://./models/mobilenet_v2/" loaded successfully!
[x] Connected to MariaDB server "localhost:3306"
[*] Waiting for messages in "js_nsfw_checker". To exit, press CTRL+C

However, if I try to run the same logic through Docker, then it seems to have problems loading the node_modules dependencies:

docker run --rm --workdir /nsfwjs --volume "./:/nsfwjs" node:20.9.0-bullseye-slim node consumer/nsfwjs.js

node:internal/modules/cjs/loader:1327
  return process.dlopen(module, path.toNamespacedPath(filename));
                 ^

Error: /nsfwjs/node_modules/@tensorflow/tfjs-node/lib/napi-v8/tfjs_binding.node: invalid ELF header
    at Module._extensions..node (node:internal/modules/cjs/loader:1327:18)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12)
    at Module.require (node:internal/modules/cjs/loader:1115:19)
    at require (node:internal/modules/helpers:130:18)
    at Object.<anonymous> (/opt/project/node_modules/@tensorflow/tfjs-node/dist/index.js:72:16)
    at Module._compile (node:internal/modules/cjs/loader:1241:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12) {
  code: 'ERR_DLOPEN_FAILED'
}

Node.js v20.9.0

Do you have any suggestions?

== EDIT ==

I can confirm the "non-existing" file exists:

docker run --rm --workdir /nsfwjs --volume "./:/nsfwjs" node:20.9.0-bullseye-slim ls -lha /nsfwjs/node_modules/@tensorflow/tfjs-node/lib/napi-v8/tfjs_binding.node
-rwxr-xr-x 2 root root 104K Apr 30 11:32 /nsfwjs/node_modules/@tensorflow/tfjs-node/lib/napi-v8/tfjs_binding.node
DavidGarciaCat commented 3 months ago

Steps to reproduce the error in a Docker container:

We can launch a new, empty container for it:

$ docker run --rm --workdir /nsfwjs -it node:20.9.0-bullseye-slim bash

Now, we can install the project dependencies, as defined in the README - Node JS App section (please note that the Docker container gives us access as the root user):

# npm install axios nsfwjs @tensorflow/tfjs-node

Then, we can install VIM (or Nano, or any other editor) to create the sample file:

# apt update && apt install -y vim

And now we can add the sample content to the file:

# vi nsfwjs.js
const axios = require("axios"); //you can use any http client
const tf = require("@tensorflow/tfjs-node");
const nsfw = require("nsfwjs");
async function fn() {
  const pic = await axios.get(`https://via.placeholder.com/250x135`, {responseType: "arraybuffer"});
  const model = await nsfw.load(); // To load a local model, nsfw.load('file://./path/to/model/')
  // Image must be in tf.tensor3d format
  // you can convert image to tf.tensor3d with tf.node.decodeImage(Uint8Array,channels)
  const image = await tf.node.decodeImage(pic.data, 3);
  const predictions = await model.classify(image);
  image.dispose(); // Tensor memory must be managed explicitly (it is not sufficient to let a tf.Tensor go out of scope for its memory to be released).
  console.log(predictions);
}
fn();

Finally, we can run the logic:

# node nsfwjs.js
node:internal/modules/cjs/loader:1327
  return process.dlopen(module, path.toNamespacedPath(filename));
                 ^

Error: /nsfwjs/node_modules/@tensorflow/tfjs-node/lib/napi-v8/tfjs_binding.node: cannot open shared object file: No such file or directory
    at Module._extensions..node (node:internal/modules/cjs/loader:1327:18)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12)
    at Module.require (node:internal/modules/cjs/loader:1115:19)
    at require (node:internal/modules/helpers:130:18)
    at Object.<anonymous> (/nsfwjs/node_modules/@tensorflow/tfjs-node/dist/index.js:72:16)
    at Module._compile (node:internal/modules/cjs/loader:1241:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1295:10)
    at Module.load (node:internal/modules/cjs/loader:1091:32)
    at Module._load (node:internal/modules/cjs/loader:938:12) {
  code: 'ERR_DLOPEN_FAILED'
}

Node.js v20.9.0

And, definitely, we can confirm the "missing" file actually exists:

# ls -lha /nsfwjs/node_modules/@tensorflow/tfjs-node/lib/napi-v8/tfjs_binding.node
-rwxr-xr-x 1 1258672 89939 86K Apr 30 20:31 /nsfwjs/node_modules/@tensorflow/tfjs-node/lib/napi-v8/tfjs_binding.node