Building a docker image for typescript application that uses mongodb-client-encryption fails in alpine linux

I am trying to build a docker image for my backend app that uses typescript. But the node-gyp is failing. I get the following error.

#29 45.38 make: Entering directory '/app/node_modules/mongodb-client-encryption/build'
#29 45.38   CXX(target) Release/obj.target/mongocrypt/src/mongocrypt.o
#29 45.38   SOLINK_MODULE(target) Release/obj.target/mongocrypt.node
#29 45.38 /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find /app/node_modules/mongodb-client-encryption/deps/lib/libmongocrypt-static.a: No such file or directory
#29 45.38 /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find /app/node_modules/mongodb-client-encryption/deps/lib/libkms_message-static.a: No such file or directory
#29 45.38 /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find /app/node_modules/mongodb-client-encryption/deps/lib/libbson-static-for-libmongocrypt.a: No such file or directory
#29 45.38 collect2: error: ld returned 1 exit status
#29 45.38 make: *** [mongocrypt.target.mk:144: Release/obj.target/mongocrypt.node] Error 1
#29 45.38 make: Leaving directory '/app/node_modules/mongodb-client-encryption/build'
#29 45.38 gyp ERR! build error
#29 45.38 gyp ERR! stack Error: `make` failed with exit code: 2
#29 45.38 gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:201:23)
#29 45.38 gyp ERR! stack     at ChildProcess.emit (node:events:513:28)
#29 45.38 gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:293:12)
#29 45.38 gyp ERR! System Linux 5.15.90.1-microsoft-standard-WSL2
#29 45.38 gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
#29 45.38 gyp ERR! cwd /app/node_modules/mongodb-client-encryption
#29 45.38 gyp ERR! node -v v16.19.1
#29 45.38 gyp ERR! node-gyp -v v9.1.0
#29 45.38 gyp ERR! not ok
#29 ERROR: executor failed running [/bin/sh -c yarn install]: exit code: 1

This is my dockerfile:

FROM node:16-alpine

RUN apk add git make cmake g++ curl bash linux-headers libbson-static musl-dev libc-dev openssl openssl-dev py3-pip

RUN git clone https://github.com/mongodb/mongo-c-driver
WORKDIR /mongo-c-driver
RUN mkdir cmake-build
WORKDIR /mongo-c-driver/cmake-build
RUN cmake -DENABLE_MONGOC=OFF ../
RUN make -j8 install


WORKDIR /
RUN git clone https://github.com/mongodb/libmongocrypt.git
WORKDIR /libmongocrypt
RUN mkdir cmake-build 
WORKDIR /libmongocrypt/cmake-build
RUN cmake -DENABLE_BUILD_FOR_PPA=ON ../
RUN make install
WORKDIR /libmongocrypt
RUN rm -rf cmake-build*

WORKDIR /libmongocrypt/bindings/node/etc
RUN chmod +x build-static.sh
RUN /bin/bash -c ./build-static.sh


WORKDIR /app
COPY package*.json .
RUN yarn install 
COPY . .
RUN yarn build

Hello @md_azmal,

The #1 reason why this will not work, and never work, and why you can’t even troubleshoot this right off the bat, is because you’re using Windows for this.

Docker royally sucks in WSL2, and encryption is not exactly possible between the windows host and WSL VM, the build is likely to never work in this scenario. You’re better off building a VMWare VM, or a Hyper-V VM, and using that instead and retry, if the issue still persists lmk and idm helping out with the Docker config.

@Brock i have used wsl2 with docker for most of my work and it worked fine. But i agree with what you are saying I’ll boot up a vm or a Linux instance in the server and will try this. if it doesn’t work I’ll post here

The main issue is the encryption build.

@md_azmal the encryption won’t really take with WSL as those components are in the Windows Kernel that it’ll rely on, and not the Linux Kernel.

understood! I’ll give it a shot in Linux

If the problem still persists even after that, let me know and I don’t mind going over further configs.

Thanks for helping @Brock I’ll let you know for sure!

@Brock tried with linux vm same issue

#0 38.73 gyp info using node@16.19.1 | linux | x64
#0 38.73 gyp info find Python using Python version 3.10.10 found at "/usr/bin/python3"
#0 38.73 gyp info spawn /usr/bin/python3
#0 38.73 gyp info spawn args [
#0 38.73 gyp info spawn args   '/usr/local/lib/node_modules/npm/node_modules/node-gyp/gyp/gyp_main.py',
#0 38.73 gyp info spawn args   'binding.gyp',
#0 38.73 gyp info spawn args   '-f',
#0 38.73 gyp info spawn args   'make',
#0 38.73 gyp info spawn args   '-I',
#0 38.73 gyp info spawn args   '/app/node_modules/mongodb-client-encryption/build/config.gypi',
#0 38.73 gyp info spawn args   '-I',
#0 38.73 gyp info spawn args   '/usr/local/lib/node_modules/npm/node_modules/node-gyp/addon.gypi',
#0 38.73 gyp info spawn args   '-I',
#0 38.73 gyp info spawn args   '/root/.cache/node-gyp/16.19.1/include/node/common.gypi',
#0 38.73 gyp info spawn args   '-Dlibrary=shared_library',
#0 38.73 gyp info spawn args   '-Dvisibility=default',
#0 38.73 gyp info spawn args   '-Dnode_root_dir=/root/.cache/node-gyp/16.19.1',
#0 38.73 gyp info spawn args   '-Dnode_gyp_dir=/usr/local/lib/node_modules/npm/node_modules/node-gyp',
#0 38.73 gyp info spawn args   '-Dnode_lib_file=/root/.cache/node-gyp/16.19.1/<(target_arch)/node.lib',
#0 38.73 gyp info spawn args   '-Dmodule_root_dir=/app/node_modules/mongodb-client-encryption',
#0 38.73 gyp info spawn args   '-Dnode_engine=v8',
#0 38.73 gyp info spawn args   '--depth=.',
#0 38.73 gyp info spawn args   '--no-parallel',
#0 38.73 gyp info spawn args   '--generator-output',
#0 38.73 gyp info spawn args   'build',
#0 38.73 gyp info spawn args   '-Goutput_dir=.'
#0 38.73 gyp info spawn args ]
#0 38.73 gyp info spawn make
#0 38.73 gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
#0 38.73 make: Entering directory '/app/node_modules/mongodb-client-encryption/build'
#0 38.73   CXX(target) Release/obj.target/mongocrypt/src/mongocrypt.o
#0 38.73   SOLINK_MODULE(target) Release/obj.target/mongocrypt.node
#0 38.73 /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find /app/node_modules/mongodb-client-encryption/deps/lib/libmongocrypt-static.a: No such file or directory
#0 38.73 /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find /app/node_modules/mongodb-client-encryption/deps/lib/libkms_message-static.a: No such file or directory
#0 38.73 /usr/lib/gcc/x86_64-alpine-linux-musl/12.2.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find /app/node_modules/mongodb-client-encryption/deps/lib/libbson-static-for-libmongocrypt.a: No such file or directory
#0 38.73 collect2: error: ld returned 1 exit status
#0 38.73 make: *** [mongocrypt.target.mk:144: Release/obj.target/mongocrypt.node] Error 1
#0 38.73 make: Leaving directory '/app/node_modules/mongodb-client-encryption/build'
#0 38.73 gyp ERR! build error 
#0 38.73 gyp ERR! stack Error: `make` failed with exit code: 2
#0 38.73 gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:201:23)
#0 38.73 gyp ERR! stack     at ChildProcess.emit (node:events:513:28)
#0 38.73 gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:293:12)
#0 38.73 gyp ERR! System Linux 5.19.0-31-generic
#0 38.73 gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
#0 38.73 gyp ERR! cwd /app/node_modules/mongodb-client-encryption
#0 38.73 gyp ERR! node -v v16.19.1
#0 38.73 gyp ERR! node-gyp -v v9.1.0
#0 38.73 gyp ERR! not ok

You goofed,

Upgrade Node to the latest version, then in package.json make sure the latest node version is used.

Also, upgrade python to the latest version of 3.X. You’re using 16.19.1 I just realized for Node.JS, the current node-gyp cannot run on 16.19.

You need Node.JS 19.X or higher, just go to the latest version of Node.JS and this entire problem should go away.

And I do apologize, I didn’t realize what version of Node you were running before.

However, for Alpine Linux because it’s an odd one from what I’m reading, you may need to actually downgrade the Node.JS version to 15 or lower, or could try apt-get install build-essential and then retry building as well. This should upgrade/install all of the current compatible build packages.

So I installed the same Node.JS version, and followed your build config.

What I found allowed the build:
Remove yarn.lock
I ran sudo apt-get install build-essential
upgraded to the latest Node.JS

And then modified package.JSON to include the engine and most current Node.JS and it builds.

@Brock the app was build on node 16 so i used that … anyways I’ll upgrade it, can you share the Dockerfile for me to refer. Also the updated package.json

The Dockerfile is the same as you have above actually, I just copied over what you did, and then opened up the package.json and added to it.

{
  "name": "<NameOfApp",
  "version": "0.0.0",
  "private": true,
  "engines": {
    "node": "<Current version of node that's installed>" 
  },

It didn’t work, gives the same error. Also how will you install build-essentials in alpine, apt is not the package manager for alpine. It uses apk and the Alpine equivalent of build-essentials is build-base which I installed but it still didn’t work

Oh, yeah just install the Debian Repo for Apt Package managers.

curl https://raw.githubusercontent.com/dvershinin/apt-get-centos/master/apt-get.sh -o /usr/local/bin/apt-get
chmod 0755 /usr/local/bin/apt-get

This will install the Apt package manager, sorry about that I thought you knew how to install it. That’s my fault, you would modify the script above based on the source version of your Linux OS, package managers even like pacman are agnostic, you just install them on your linux distribution and you got it.

EDIT:

You can also build the APT package manager from source, too.