I'm trying to connect to a PostgreSQL database hosted on Azure from a Dockerized Node app with Sequelize. However, I'm getting an error that the libpq dependency can't be found when run in the container. It works fine on my local machine.
(node:40) UnhandledPromiseRejectionWarning: Error: Error loading shared library /usr/app/node_modules/libpq/build/Release/addon.node: Exec format error
at Object.Module._extensions..node (internal/modules/cjs/loader.js:1122:18)
I've found a few similar errors out there and tried different methods in the Dockerfile to ensure the dependency is loaded with no success. I've also ensured that my Node version matches on my local machine and in the Docker container.
FROM node:14-alpine
WORKDIR /usr/app
COPY package*.json ./
RUN \
apk add --no-cache g++ make python3 postgresql-libs
RUN \
apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev && \
npm install libpq && \
apk --purge del .build-deps
COPY . .
CMD ["npm", "start"]
Here is my docker-compose.yml
version: "3.8"
services:
api:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/usr/app
ports:
- "3000:3000"
docker-compose.dev.yml
version: "3.8"
services:
api:
command: npm run dev
environment:
- NODE_ENV=development
Running the following to build the image and start the container:
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up
The libpq dependency comes from the fact that I need to use native: true
in the sequeqlgze connection to enforce SSH. Which requires the pg-native
package.
// PostgreSQL connection
exports.connect = async () => {
const sequelize = new Sequelize(
config.DATABASE_NAME,
config.DB_USERNAME,
config.DB_PASSWORD,
{
host: config.DB_HOSTNAME,
port: config.DB_PORT,
dialect: "postgres",
native: true, // enables ssl
}
);
https://github.com/nodejs/node-gyp/issues/1855
Using Docker with nodejs with node-gyp dependencies
Step 5/7 : RUN apk add --no-cache --virtual .build-deps gcc musl-dev postgresql-dev && npm install libpq && apk --purge del .build-deps
---> Running in 20f7406e6abc
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.11/community/x86_64/APKINDEX.tar.gz
(1/4) Installing pkgconf (1.6.3-r0)
(2/4) Installing openssl-dev (1.1.1g-r0)
(3/4) Installing postgresql-dev (12.5-r0)
(4/4) Installing .build-deps (20201207.093711)
Executing busybox-1.31.1-r9.trigger
OK: 243 MiB in 47 packages
> libpq@1.8.9 install /usr/app/node_modules/libpq
> node-gyp rebuild
make: Entering directory '/usr/app/node_modules/libpq/build'
CXX(target) Release/obj.target/addon/src/connection.o
CXX(target) Release/obj.target/addon/src/connect-async-worker.o
CXX(target) Release/obj.target/addon/src/addon.o
In file included from ../../nan/nan.h:56,
from ../src/addon.h:4,
from ../src/addon.cc:1:
/root/.cache/node-gyp/14.15.1/include/node/node.h:758:43: warning: cast between incompatible function types from 'void (*)(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE)' {aka 'void (*)(v8::Local<v8::Object>)'} to 'node::addon_register_func' {aka 'void (*)(v8::Local<v8::Object>, v8::Local<v8::Value>, void*)'} [-Wcast-function-type]
758 | (node::addon_register_func) (regfunc), \
| ^
/root/.cache/node-gyp/14.15.1/include/node/node.h:792:3: note: in expansion of macro 'NODE_MODULE_X'
792 | NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage)
| ^~~~~~~~~~~~~
../src/addon.cc:76:1: note: in expansion of macro 'NODE_MODULE'
76 | NODE_MODULE(addon, InitAddon)
| ^~~~~~~~~~~
SOLINK_MODULE(target) Release/obj.target/addon.node
COPY Release/addon.node
make: Leaving directory '/usr/app/node_modules/libpq/build'
> nodemon@2.0.6 postinstall /usr/app/node_modules/nodemon
> node bin/postinstall || exit 0
Love nodemon? You can now support the project via the open collective:
> https://opencollective.com/nodemon/donate
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.1.3 (node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.3: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
+ libpq@1.8.9
added 222 packages from 187 contributors and audited 224 packages in 13.185s
12 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
WARNING: Ignoring APKINDEX.70f61090.tar.gz: No such file or directory
WARNING: Ignoring APKINDEX.ca2fea5b.tar.gz: No such file or directory
(1/4) Purging .build-deps (20201207.093711)
(2/4) Purging postgresql-dev (12.5-r0)
(3/4) Purging openssl-dev (1.1.1g-r0)
(4/4) Purging pkgconf (1.6.3-r0)
Executing busybox-1.31.1-r9.trigger
OK: 233 MiB in 43 packages
Removing intermediate container 20f7406e6abc
---> 86a68c654898
Step 6/7 : COPY . .
Thank you David! Looks like I wasn't preserving node_modules in my docker-compose.yml file.
Adding: - /usr/app/node_modules
to the volumes did the trick!
version: "3.8"
services:
api:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/usr/app
- /usr/app/node_modules
ports:
- "3000:3000"