How to Install node-oracledb 5.5 and Oracle Database on Apple M1/M2 Silicon

Christopher Jones
Oracle Developers
Published in
5 min readApr 5, 2023

This post shows how you can use node-oracledb 5.5 on Apple Silicon and also run Oracle Database.

A random picture of 7 adjacent leaves hanging down from a horiztonal string. Each leaf is a different color. The left hand is green, the middle is yellow, and the right is red.
Photo by Chris Lawton on Unsplash

Typically if you try to install node-oracledb 5.5 on Apple M1/M2 Silicon you will get:

$ npm install oracledb
...
npm ERR! oracledb ERR! NJS-067: a pre-built node-oracledb binary was not found for darwin arm64
...

Or you might stumble around some information gleaned from the web and get Error: NJS-045: cannot load a node-oracledb binary for Node.js 16.20.0 (darwin arm64)

The reason there is no binary is that we are all still waiting for a release of Oracle Instant Client for Apple M1/M2 Silicon that would be usable by node-oracledb.

[Update: node-oracledb 6.0 has been released! See the announcement. The default, new, pure JavaScript ‘Thin’ mode works nicely on my M1 mac without needing Instant Client!]

In the meantime, here’s how you can use node-oracledb 5.5 on Apple Silicon. The steps will also be useful if you want to run node-oracledb 6.0 in Thick mode (which is equivalent to the node-oracledb 5.5 architecture and uses Oracle Instant Client). Many thanks to the community members firstly for their patience, and secondly for sharing information about the installation steps that worked for them. It’s greatly appreciated now that I have an M1 machine myself. The key thing is to use a Node.js Intel binary so that the Instant Client Intel packages can be used, all running magically via Apple’s Rosetta.

Installing Node.js and node-oracledb 5.5 on Apple M1/M2 Silicon

I run multiple Node.js versions on my machines, so I use nvm to manage them. On macOS, I get this from homebrew:

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Check the homebrew doc for details and any extra steps to update your PATH.

Now install nvm:

$ brew install nvm

Swap to an Intel shell. This is the key step:

$ arch -x86_64 zsh

If you now run arch it should show i386.

Install Node.js, for example version 16:

$ nvm install 16
Downloading and installing node v16.20.0...
Downloading https://nodejs.org/dist/v16.20.0/node-v16.20.0-darwin-x64.tar.xz...
########################################################################################################################## 100.0%
Computing checksum with shasum -a 256
Checksums matched!

Since I have various Node.js versions installed, I make sure nvm is using this new version:

$ nvm use v16
Now using node v16.20.0 (npm v8.19.4)

Install node-oracledb. This will install the pre-built binary package for Apple Intel:

$ npm install oracledb

added 1 package in 2s

Install the Oracle Instant Client for macOS (Intel x86) Basic package. I typically also install the optional SQL*Plus package, since this is handy for ad-hoc SQL access:

$ cd $HOME/Downloads
$ curl -O https://download.oracle.com/otn_software/mac/instantclient/198000/instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg
$ curl -O https://download.oracle.com/otn_software/mac/instantclient/198000/instantclient-sqlplus-macos.x64-19.8.0.0.0dbru.dmg
$ hdiutil mount instantclient-basic-macos.x64-19.8.0.0.0dbru.dmg
$ hdiutil mount instantclient-sqlplus-macos.x64-19.8.0.0.0dbru.dmg
$ /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru/install_ic.sh
$ hdiutil unmount /Volumes/instantclient-basic-macos.x64-19.8.0.0.0dbru
$ hdiutil unmount /Volumes/instantclient-sqlplus-macos.x64-19.8.0.0.0dbru

Note you only need to run the install script once.

Create a Node.js application, for example v.js:

const oracledb = require('oracledb');

if (process.platform === 'darwin') {
oracledb.initOracleClient({libDir: process.env.HOME + '/Downloads/instantclient_19_8'});
}

async function doit() {
console.log("Run at: " + new Date());
console.log("Node.js version: " + process.version + " (" + process.platform, process.arch + ")");
console.log("Node-oracledb version:", oracledb.versionString);
console.log("Oracle Client library version:", oracledb.oracleClientVersionString);

let connection = await oracledb.getConnection(
{
user: process.env.NODE_ORACLEDB_USER,
password: process.env.NODE_ORACLEDB_PASSWORD,
connectString: process.env.NODE_ORACLEDB_CONNECTIONSTRING
});

console.log("Oracle Database version:", connection.oracleServerVersionString);

const sql = `SELECT UNIQUE CLIENT_OCI_LIBRARY, CLIENT_VERSION, CLIENT_DRIVER
FROM V$SESSION_CONNECT_INFO
WHERE SID = sys_context('USERENV', 'SID')`;

const result = await connection.execute(sql);
console.dir(result.rows[0], { depth: null });

connection.close();

}

doit();

Set the three referenced environment variables to match your database environment, for example:

$ export NODE_ORACLEDB_USER='system'
$ export NODE_ORACLEDB_PASSWORD='xxxx'
$ export NODE_ORACLEDB_CONNECTIONSTRING='localhost/xepdb1'

Now you can run the script:

$ node v.js
Run at: Wed Apr 05 2023 10:36:13 GMT+1000 (Australian Eastern Standard Time)
Node.js version: v16.20.0 (darwin x64)
Node-oracledb version: 5.5.0
Oracle Client library version: 19.8.0.0.0
Oracle Database version: 21.3.0.0.0
[ 'Full Instant Client', '19.8.0.0.0', 'node-oracledb : 5.5.0' ]

If you don’t have Apple’s Rosetta installed, it should prompt you to download and install it, see How to install Rosetta.

From the output of v.js, you can see it ran the x64 version of Node.js and loaded Instant Client. To really prove I am on Apple Silicon:

$ sysctl -a | grep brand
machdep.cpu.brand_string: Apple M1 Max

And that’s it.

Every time you want to run Node.js you will need to do:

$ arch -x86_64 zsh
$ nvm use v16

Oracle Database on Apple M1/M2 Silicon

“But what about the database?” I hear you ask.

These are the steps I have used. (Update: now that Oracle has an ARM Linux database distribution, the emulation may not be required, but you would need to use a different container than shown below)

I have Rancher installed (but not running) which provides the ‘docker’ command.

Then install colima and a database container from my colleague. Now that Oracle Database 23c Free is out, I use the updated container:

$ brew install colima
$ colima start --arch x86_64 --memory 4
$ docker run -d -p 1521:1521 --name free -e ORACLE_PASSWORD=mysecret1 -e APP_USER=cj -e APP_USER_PASSWORD=mysecret2 -v oracle-volume:/opt/oracle/oradata gvenzl/oracle-free

I can then run commands like this from my macOS shell. Note the shell can be arm64 or i386:

$ sqlplus -l system@localhost/FREEPDB1

To stop the system run:

$ docker stop xe
$ colima stop

And then later, when you want to restart the DB container, you can do:

$ colima start --arch x86_64 --memory 4
$ docker start free

Summary

This post has shown one way of using Node.js with Oracle Database on Apple M1/M2 Silicon. You may alternatively want to explore running Oracle Linux ARM (aarch64) in a container and/or use the Oracle Instant Client for Linux ARM (aarch64) package.

Keep an eye out for new releases of Instant Client, node-oracledb, and Oracle Database. These will make the steps in this post obsolete.

Resources

Home page: https://oracle.github.io/node-oracledb/

Installation: https://node-oracledb.readthedocs.io/en/latest/user_guide/installation.html

Documentation: https://node-oracledb.readthedocs.io/en/latest/

Questions: https://github.com/oracle/node-oracledb/discussions/

Source code: https://github.com/oracle/node-oracledb

Npm repository: https://www.npmjs.com/package/oracledb

--

--

Christopher Jones
Oracle Developers

Oracle Database Product Manager for language drivers including Python python-oracledb, Node.js node-oracledb, PHP OCI8 and more! On Mastodon: @cjbj@phpc.social