Hi, I am trying to use the prebuilt version of oracledb in a docker environment, but I am not sure if I am able to use oracledb with alpine based images such as frolvlad/alpine-glibc.
Any advice on how I could proceed?
Hi @bliu13 ,
I`m not sure about those images in specific, but I do know that the binaries work with the RHEL 7 based images such as ones used by Openshift tool.
https://docs.openshift.com/container-platform/3.4/using_images/s2i_images/nodejs.html
I think in your case it is just a matter of getting the linux prebuilt binaries and testing a sample application to see whether the image works well with it or not, which I see no reason for not working.
@bliu13 try it and let us know how it goes.
I have gotten oracledb to work using an image that uses glibc. Here is the Dockerfile that I am have.
FROM node:carbon
EXPOSE 3000
# Data service and all COPY actions will be stored under the service directory.
WORKDIR /service
# Setting the arguments for the environment variables.
# Will expect 'dev', 'tqa', 'stg', or 'prd' without quotes.
# https://stackoverflow.com/questions/31198835/can-we-pass-env-variables-through-cmd-line-while-building-a-docker-image-through
ARG NODE_ENV=
ENV NODE_ENV ${NODE_ENV}
COPY package*.json ./
RUN npm install --only=production
COPY . .
RUN apt-get update && apt-get install libaio1 unzip
# Configuring Oracle Instant Client
RUN unzip instantclient_12_2.zip && \
mv instantclient_12_2/ /usr/lib/ && \
rm instantclient_12_2.zip && \
ln /usr/lib/instantclient_12_2/libclntsh.so.12.1 /usr/lib/libclntsh.so && \
ln /usr/lib/instantclient_12_2/libocci.so.12.1 /usr/lib/libocci.so && \
ln /usr/lib/instantclient_12_2/libociei.so /usr/lib/libociei.so && \
ln /usr/lib/instantclient_12_2/libnnz12.so /usr/lib/libnnz12.so
ENV ORACLE_BASE /usr/lib/instantclient_12_2
ENV LD_LIBRARY_PATH /usr/lib/instantclient_12_2
ENV TNS_ADMIN /usr/lib/instantclient_12_2
ENV ORACLE_HOME /usr/lib/instantclient_12_2
RUN apt-get -y remove unzip && \
apt-get clean
# Command to run when the container starts.
CMD ["node", "."]
I am trying to use Loopback to create micro services and I have the requirement to have it work with Oracle databases. Loopback uses loopback-connector-oracle, which depends on oracledb, which depends on Oracle Instant Client to be able to interact with Oracle databases. The resulting image size after building the container image is 1 gigabyte. Using an image that uses Alpine would really help in these kinds of situations.
I have found that the other database connectors for mysql, postgresql, sql server, don't have these kinds of complexities. I don't know anything about the software design choices that were made, but would it make sense to just build oracledb with whatever it needs from the Basic Instant Client? It honestly makes absolutely no sense have people register an account with Oracle just so we can use some sort of software to connect to their type of database.
@bliu13 Can you show us the output of docker history [image-name]?
Here is the history
IMAGE CREATED CREATED BY SIZE COMMENT
4898a1dd689c 2 hours ago /bin/sh -c #(nop) CMD ["node" "."] 0B
fb8f2c5e0700 2 hours ago /bin/sh -c apt-get -y remove unzip && apt-… 1.94MB
7cfe5098ca39 2 hours ago /bin/sh -c #(nop) ENV ORACLE_HOME=/usr/lib/… 0B
785d38b41851 2 hours ago /bin/sh -c #(nop) ENV TNS_ADMIN=/usr/lib/in… 0B
2cfadb8c2195 2 hours ago /bin/sh -c #(nop) ENV LD_LIBRARY_PATH=/usr/… 0B
71b7e1ca0958 2 hours ago /bin/sh -c #(nop) ENV ORACLE_BASE=/usr/lib/… 0B
589182c5cfb9 2 hours ago /bin/sh -c unzip instantclient_12_2.zip && … 222MB
93c173ef2579 2 hours ago /bin/sh -c apt-get update && apt-get install… 12.4MB
4be2c0d495a1 2 hours ago /bin/sh -c #(nop) COPY dir:159f43924347518c5… 69.1MB
5049ce765eea 2 hours ago /bin/sh -c npm install --only=production 56.4MB
8079ef4e1ff1 2 hours ago /bin/sh -c #(nop) COPY multi:af7f068a680223a… 141kB
5ec3643a15ec 2 hours ago /bin/sh -c #(nop) ENV NODE_ENV=dev 0B
48880ef8005e 2 hours ago /bin/sh -c #(nop) ARG NODE_ENV= 0B
c74760845d05 2 hours ago /bin/sh -c #(nop) EXPOSE 3000 0B
5cf1b6d2148f 2 hours ago /bin/sh -c #(nop) WORKDIR /service 0B
b87c2ad8344d 6 days ago /bin/sh -c #(nop) CMD ["node"] 0B
<missing> 6 days ago /bin/sh -c set -ex && for key in 6A010… 4.17MB
<missing> 6 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.3.2 0B
<missing> 6 days ago /bin/sh -c ARCH= && dpkgArch="$(dpkg --print… 56.9MB
<missing> 6 days ago /bin/sh -c #(nop) ENV NODE_VERSION=8.9.4 0B
<missing> 4 weeks ago /bin/sh -c set -ex && for key in 94AE3… 129kB
<missing> 4 weeks ago /bin/sh -c groupadd --gid 1000 node && use… 335kB
<missing> 4 weeks ago /bin/sh -c set -ex; apt-get update; apt-ge… 324MB
<missing> 4 weeks ago /bin/sh -c apt-get update && apt-get install… 123MB
<missing> 4 weeks ago /bin/sh -c set -ex; if ! command -v gpg > /… 0B
<missing> 4 weeks ago /bin/sh -c apt-get update && apt-get install… 44.6MB
<missing> 4 weeks ago /bin/sh -c #(nop) CMD ["bash"] 0B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:1dd78a123212328bd… 123MB
That looks to be about 1037MB...
If you follow the dependency tree for FROM node:carbon, you'll find it's based on debian, not alpine. That image gets quite large after all the installs it does: 676MB.
Though I understand your point on the OCI files, there's likely nothing we can do about that. Have you tried node:8-slim? That alone seems to shave 445MB (231MB uncompressed). That might work now that we have pre-built binaries.
Also use Instant Client Basic Light and remove unnecessary libraries (e.g. JDBC etc). The required libs are given in https://docs.oracle.com/en/database/oracle/oracle-database/12.2/lnoci/instant-client.html#GUID-E436205F-2A39-45AC-BD28-969D4B74128B
OCI provides all of the key functionality for DB access and lets us reuse that functionality across all Oracle client applications.
You could also look into multi-stage builds. This could help if you need some builds but don't want to include the stuff needed to do the build in the final build.
@dmcghan Thank you for all the suggestions. Using "node:carbon-slim" cut down the final image to 447 MB and I will look into multi-stage builds.
@cjbj Thank you for the suggestion, I switched to the Instant Client Basic Light which reduced the amount of data needed to copy around. Serious question though, is it really unlikely that the OCI files can be included with oracledb, and be hosted on npm repository? Is it a licensing issue, technical challenge, or policy?
I really appreciate the help.
It's a licensing issue.
@cjbj Ok, my sympathies. Thanks for the help.
Just for the record, I'm using node:8-alpine and this configuration works for me:
Dockerfile:
...
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \
apk add --update libaio libnsl && \
ln -s /usr/lib/libnsl.so.2 /usr/lib/libnsl.so.1
...
edge repository is needed in order to be able to install libnsl. You also need to install libaio.
I've used instant client 12_1 that includes the following (note that .jar files are not needed, just listing what the instant client version I'm using has):
BASIC_README
genezi
glogin.sql
libclntshcore.so.12.1
libclntsh.so (this is a symlink to libclntsh.so.12.1)
libclntsh.so.12.1
libnnz12.so
libocci.so.12.1
libociei.so
libocijdbc12.so
libons.so
liboramysql12.so
libsqlplusic.so
libsqlplus.so
ojdbc6.jar
ojdbc7.jar
sqlplus
SQLPLUS_README
uidrvci
xstreams.jar
I've tried so far a connection and a query. So far is working good.
@gentunian Thanks for sharing. Keep us posted.
I've decided to give Instant Client Basic Light a try and it seems that it's even worse than the libraries I was using.
Let's inspect a little bit.
This client has cut off languages for error reporting and some enconding. You could get it from oracle here.
The library libclntsh.so.12.1 is 69MB and has these dependencies:
linux-vdso.so.1 (0x00007ffeaa2ac000)
libmql1.so => not found
libipc1.so => not found
libnnz12.so => not found
libons.so => not found
libdl.so.2 => /lib64/libdl.so.2 (0x00007fe5b719d000)
libm.so.6 => /lib64/libm.so.6 (0x00007fe5b6e52000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe5b6c34000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007fe5b6a1c000)
librt.so.1 => /lib64/librt.so.1 (0x00007fe5b6814000)
libaio.so.1 => /lib64/libaio.so.1 (0x00007fe5b6612000)
libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fe5b63fb000)
libc.so.6 => /lib64/libc.so.6 (0x00007fe5b6045000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe5bae46000)
libclntshcore.so.12.1 => not found
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fe5b5e2e000)
So, in order for this to work, it's not quite true what oracle docs says about it that you _need_ 4 files. Also, you will need to install libresolv.so.2 somehow.
I had this downloaded maybe 2 years ago. This version 12.1.0.1.0 has smaller size 53MB and different dependencies:
linux-vdso.so.1 (0x00007ffd01df4000)
libnnz12.so => not found
libons.so => not found
libdl.so.2 => /lib64/libdl.so.2 (0x00007f2c28948000)
libm.so.6 => /lib64/libm.so.6 (0x00007f2c285fd000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2c283df000)
libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f2c281c7000)
librt.so.1 => /lib64/librt.so.1 (0x00007f2c27fbf000)
libc.so.6 => /lib64/libc.so.6 (0x00007f2c27c09000)
libaio.so.1 => /lib64/libaio.so.1 (0x00007f2c27a07000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2c2b839000)
libclntshcore.so.12.1 => not found
No libresolv, no libipc (although is provided by oracle), and no libmql1 (also provided by oracle).
I managed to reduce to this libraries in order to connect to a remote database:
libclntshcore.so.12.1
libclntsh.so.12.1
libnnz12.so
libociei.so
libons.so
Totaling 192MB.
If you download version 12.1.0.2.0, more dependencies appears, like libipc, libmql, and size reduces to 92MB approximately but with the need to install libresolv.
Trying to find the official 12.1.0.1.0 version from oracle I've found this repo: https://github.com/bumpx/oracle-instantclient where you can find instant client versions and, at your own risk, use them in your Dockerfiles.
We recently cleaned up all the old Instant Client downloads so only the terminal releases are available now. I've alerted the OCI doc writer to the issues with the doc.
@gentunian, any chance you could post more of a "generic" dockerfile?
@jeffm13 I've wrapped all the info into this dockerfile:
FROM node:8-alpine
# the client version we will download from bumpx repo
ENV CLIENT_FILENAME instantclient-basic-linux.x64-12.1.0.1.0.zip
# work in this directory
WORKDIR /opt/oracle/lib
# take advantage of this repo to easily download the client (use it at your own risk)
ADD https://github.com/bumpx/oracle-instantclient/raw/master/${CLIENT_FILENAME} .
# we need libaio and libnsl, the latter is only available as package in the edge repository
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \
apk add --update libaio libnsl && \
ln -s /usr/lib/libnsl.so.2 /usr/lib/libnsl.so.1
# unzip the necessary libraries, create the base symlink and remove the zip file
RUN LIBS="*/libociei.so */libons.so */libnnz12.so */libclntshcore.so.12.1 */libclntsh.so.12.1" && \
unzip ${CLIENT_FILENAME} ${LIBS} && \
for lib in ${LIBS}; do mv ${lib} /usr/lib; done && \
ln -s /usr/lib/libclntsh.so.12.1 /usr/lib/libclntsh.so && \
rm ${CLIENT_FILENAME}
Using this image with my examples is working OK. Image size is: 348MB
These are the libraries sizes for version 12.1.0.1.0:
52.9M instantclient_12_1/libclntsh.so.12.1
6.4M instantclient_12_1/libclntshcore.so.12.1
6.0M instantclient_12_1/libnnz12.so
129.9M instantclient_12_1/libociei.so
324.0K instantclient_12_1/libons.so
Totalling: 195.5M
Just for the record, I'm using
node:8-alpineand this configuration works for me:Dockerfile:
... RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \ apk add --update libaio libnsl && \ ln -s /usr/lib/libnsl.so.2 /usr/lib/libnsl.so.1 ...edge repository is needed in order to be able to install libnsl. You also need to install libaio.
I've used instant client 12_1 that includes the following (note that .jar files are not needed, just listing what the instant client version I'm using has):
BASIC_README genezi glogin.sql libclntshcore.so.12.1 libclntsh.so (this is a symlink to libclntsh.so.12.1) libclntsh.so.12.1 libnnz12.so libocci.so.12.1 libociei.so libocijdbc12.so libons.so liboramysql12.so libsqlplusic.so libsqlplus.so ojdbc6.jar ojdbc7.jar sqlplus SQLPLUS_README uidrvci xstreams.jarI've tried so far a connection and a query. So far is working good.
I ran api add --no-cach libaio libnsl but I don't see libclntsh.so or much else besides the libnsl.so* mentioned. what am I missing?
Here are my thoughts: Use an operating system supported by Oracle, thus avoiding the headache of hacking Alpine and the uncertainty that it won't fall over at a critical time. And thus giving you some confidence your business won't be negatively impacted. In the Docker container world that means using the Oracle Linux 'slim' images oraclelinux:7-slim such as shown in https://github.com/oracle/docker-images/tree/master/OracleInstantClient
Here are my thoughts
the topic is on alpine, not your thoughts 😁
@madsteer libclntsh.so is provided by the instant client package. You need to download it from the official oracle site.
@gentunian please don't recommend random 3rd party download sites that may or may not be trustable, and don't respect the licensing. Official places to get Instant Client include OTN, which requires a click-through, and yum.oracle.com (which doesn't need a click through).
@cjbj I don't recommend its use. I'm just posting a workaround to a community member with community resources in a community repository without any warranty. Just like it's written in the repo:
Please follow up rules on the Oracle website (x86 http://www.oracle.com/technetwork/topics/linuxsoft-082809.html) (x64 http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html).
Taken from:
https://github.com/bumpx/oracle-instantclient
Thanks for your consideration though.
@gentunian then don't make me grumpy by mentioning it :)
IANAL but I spend too much time talking to them. What you are suggesting doesn't satisfy any licensing I know of, and therefore doesn't do the end user any real favor.
@cjbj do you mean that by only suggesting I'm breaking a license? I'm not a lawyer either, but as I said, I don't recommend its use by either because violates a license or may harm any hardware/software by any means. I'm just sharing knowledge just like - _don't do this at home_ (where home could be production/something).
I will sign off of this licensing discussion, but continue sharing any knowledge I've learned through community resources and efforts.
And please! don't get grumpy :)
Best regards,
I've recently made an experiment with docker images containing node 12.10 and Oracle Client basic (lite). Both were working.
Here is the summary:
70 MB node:12.10-alpine
208 MB instantclient-basic-linux.x64-12.1.0.1.0
278 MB total
162 MB node:12.10-buster-slim
100 MB instantclient-basiclite-linux.x64-12.2.0.1.0.tar.xz
262 MB total
Unfortunately instant client for alpine distribution is more than 100 MB larger because we need to take an older version which does not depend on libresolv.so.2.
My take here is to go with a glibc-based distribution because the resulting size is smaller and because I can use the latest 12.x Oracle client (presumably containing security fixes).
@ivosh thanks for sharing. You may be interested in these presentation slides: https://static.rainfocus.com/oracle/oow19/sess/1553560683840001mfXq/PF/DEV4626-Developing-and-Deploying-Python-and-Node.js-Applications-in-Docker_1568845042122001Vsfl.pdf At some stage in the next couple of weeks I'll write up a blog on them (it'll be on blogs.oracle.com/opal)
Thanks @cjbj , when using alpine with bumpx file some of query doesn't work. And then I follow this tutorial, and it's work very well 😄
@ahmadarif I'm glad you found it useful. There is now content in the installation guide too: https://oracle.github.io/node-oracledb/INSTALL.html#docker
I've recently made an experiment with docker images containing node 12.10 and Oracle Client basic (lite). Both were working.
Here is the summary:70 MB node:12.10-alpine 208 MB instantclient-basic-linux.x64-12.1.0.1.0 278 MB total162 MB node:12.10-buster-slim 100 MB instantclient-basiclite-linux.x64-12.2.0.1.0.tar.xz 262 MB totalUnfortunately instant client for alpine distribution is more than 100 MB larger because we need to take an older version which does not depend on libresolv.so.2.
My take here is to go with a glibc-based distribution because the resulting size is smaller and because I can use the latest 12.x Oracle client (presumably containing security fixes).
@ivosh do you have the dockerfile that come with your experiment ?
Thank you,
@FrancoisXavierNoe serious question: why do you really want Alpine?
If you want Dockerfiles for Debian or RH, check the node-oracledb install manual and my recent blog post series (yes, part 2 is coming a few days): Docker for Oracle Database Applications in Node.js and Python.
The Alpine images are significantly smaller than the slim images and still include tools for debugging and working inside of the container (like curl and such)
@daveisfera I need more detail when I internally champion better Alpine support. Why is space so important vs critical stability and lack of new features (if you're stuck with 12c client)? How did you decide the tradeoff?
When designing a system, there are multiple variables and considerations into development, ops and debugging costs, I've found that Alpine has several benefits for that (i.e. the small image that's still "batteries included"). Yes, looking through the lens of "just building an Oracle client", may not reveal the same benefits and has some additional costs (i.e. there's not currently a turn key solution like there is with Debian and CentOS), but most people are building a system that uses the Oracle client and not "just an Oracle client".
why do you really want Oracle?
@gretel no need for that kind of statement.
@daveisfera Isn't the point that the whole system has a purpose, and that purpose is to run reliably? So tell me your tradeoff?
I could guess - and have done so when discussing the question of Alpine support in Oracle meetings - but it helps to really understand the rationale. Is this for all containers? Or some?
"that kind of statement" is as defined as "run reliably" which is nil at most.
Yes, run reliably is a requirement, but there's nothing in an Alpine containers are just as capable as doing that as Debian/Centos/Windows/whatever variant you want to list here. Also, the fact that Alpine is a very common base image (might even be the most common base image, if it's not second to Debian) means that it has a lot of attention and focus from the community and is used to run in production environments the world over.
Plus, once you have established that something can run reliably, then cost of development/maintenance/deployment because the primary driver and Alpine has several benefits in those areas (as I previously listed).
@daveisfera are these business critical apps? If there was a problem are you able to swap OS quickly (or do you need lengthy internal review etc)? What Oracle client version are you using? My concern with stability is do with the hacks needed to install glibc - or do you perceive the glibc variants of Alpine as widely used and trustable?
The Oracle Linux kernels do have updates for Oracle software that may not have made it upstream, though I admit the Oracle Client isn't as heavy a user as the DB would be.
Docker makes swapping OS a possibility but I've never heard of a use case like this. It's usually used to control versions and make updating to a newer version of an OS simpler (i.e. just change a line and rebuild to move to release N+1 and not maintain multiple OSes or switch between OSes).
To properly use Alpine, you shouldn't be installing glibc. You should be building against musl.
Also, if using an Oracle OS is the only fully supported way of using the Oracle client, then I'm probably just wasting my time trying to argue that Oracle should put effort into helping people use their tools on different platforms (i.e. the few customers we had that were using Oracle have moved away because "support was a huge pain" and we've been trying to maintain support in case other customers wanted it in the future, but maybe we just need to walk away as well)
@daveisfera there are various officially certified Linux distros, but Alpine is not one of them. I'm sure many customers are using a wide variety of distros for the application tier, and that is their choice. What I'm am trying to do is gather your specific feeling on Alpine so I can convey the case for it when I'm in review and planning meetings.
@cjbj Could you give us a hand to build a smaller image possible?
I made a comparison with the supported images here
https://github.com/oracle/docker-images/issues/1593
Resurrecting this further, @cjbj, the debian based distros come with a host of security issues otb. It'd be nice to use Alpine based on this alone.
Most helpful comment
@jeffm13 I've wrapped all the info into this dockerfile:
Using this image with my examples is working OK. Image size is: 348MB
These are the libraries sizes for version 12.1.0.1.0: