Hi Alex,
I’ve actually been able to reproduce this problem by using balena local push -s .. This is a mechanism of how builds take place using this command, whereby the local directory is first synced to the remote device. This means that regardless of the .dockerignore file, the node_modules on your machine is being synced, and the incorrect ELF binaries being used.
I’ve verified this on my own setup by locally install the node dependencies into node_modules on my development machine and then using balena local push to the device (whereby it understandably fails), and then removing the container/images from the device, removing the node_modules from my development machine and pushing again, where it then works (as the wrong architecture node_modules bindings are not being used).
However, we are moving over to a unified push mechanism (which is present in the latest version of the balena-cli) which we strongly advise users to use instead. Using this mechanism, the build will work correctly as it mimics the Docker build process correctly. You should be able to run the following (from any version of balena-cli that includes it, I’m using 9.5.0, which is the current):
balena push <ipAddressOfDevice> -s .
regardless of what’s in the same directory on your development machine, and the device will rebuild everything correctly.
Additionally, as mentioned by Robert previously, the base image you’re inheriting from includes the build-essential toolchain, which includes everything node-gyp needs to create native bindings, so you absolutely don’t need these in your Dockerfile (I have actually tried your project verbatim with the above, which works), so I’d suggest the following Dockerfile instead:
FROM resin/raspberrypi3-node:8
# Defines our working directory in container
WORKDIR /usr/src/app
# Copies the package.json first for better cache on later pushes
COPY package.json package.json
# COPY package-lock.json package-lock.json
# This install npm dependencies on the balena build server,
# making sure to clean up the artifacts it creates in order to reduce the image size.
RUN JOBS=MAX npm install --production --unsafe-perm && rm -rf /tmp/*
RUN uname -a
# This will copy all files in our root to the working directory in the container
COPY . ./
# Enable systemd init system in container
ENV INITSYSTEM on
# server.js will run when container starts up on the device
CMD ["npm", "start"]
I’ve used this Dockerfile as well to successfull build and run your project.
If you could try your project with balena push, and then cut down the Dockerfile and verify that that also works for you, hopefully everything should build and run as expected!
Please let us know if it doesn’t, and we’ll continue looking into it.

- here are the results:
(no need to follow the optional install instructions in the
--> but it’s worth the wait!