I am building a Docker based Flask API that needs to connect to a remote Oracle Database. I can get it to work on my machine outside of Docker but when I go to containerize it I get the error. I have tried every article I can find on stackoverflow and I still get the error:
load by OS failure: libclntsh.so: cannot open shared object file: No such file or directory
I have tried 3 different ways:
FROM python:3.9-buster
ENV DPI_DEBUG_LEVEL=64
# Installing Oracle instant client
# INSTALL TOOLS
RUN apt-get update \
&& apt-get -y install unzip \
&& apt-get -y install libaio1 libaio-dev \
&& mkdir -p /opt/data/api
ADD ./oracle-instantclient/ /opt/data
ADD ./install-instantclient.sh /opt/data
ADD ./requirements.txt /opt/data
WORKDIR /opt/data
ENV ORACLE_HOME=/opt/oracle/instantclient
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ORACLE_HOME
ENV OCI_HOME=/opt/oracle/instantclient
ENV OCI_LIB_DIR=/opt/oracle/instantclient
ENV OCI_INCLUDE_DIR=/opt/oracle/instantclient/sdk/include
RUN ./install-instantclient.sh
# Python set up
# set working directory
WORKDIR /usr/src/app
# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
# add and install requirements
COPY ./requirements.txt .
RUN pip install -r requirements.txt
# add app
COPY . .
# add entrypoint.sh
COPY ./entrypoint.sh .
RUN chmod x /usr/src/app/entrypoint.sh
This was the first way I tried for instant client:
# Install system dependencies and clean up rpms afterwards
RUN apt-get update \
&& apt-get -y install alien unzip libaio1 \
&& apt-get clean
# ZIP Install
ENV DPI_DEBUG_LEVEL=64
ENV INSTANT_CLIENT_FILE=instantclient-basic-linux.x64-19.13.0.0.0dbru.zip
RUN mkdir -p /opt/oracle
ADD ./resources/${INSTANT_CLIENT_FILE} /opt/oracle
RUN apt-get -y install unzip
RUN unzip /opt/oracle/${INSTANT_CLIENT_FILE} -d /opt/oracle
RUN ln -s /opt/oracle/instantclient_19_13/libclntsh.so.19.13 /usr/lib/libclntsh.so
RUN rm -rf /opt/oracle/${INSTANT_CLIENT_FILE}
# This needs to be set to the path that was created when the unzip occurred
# I figured out what the directory name after /opt/oracle was going to be by
# unzipping the file on my computer
ENV ORACLE_HOME=/opt/oracle/instantclient_19_13
ENV LD_LIBRARY_PATH=${ORACLE_HOME}
ENV ORACLE_BASE=${ORACLE_HOME}
ENV PATH="${ORACLE_HOME}:${PATH}"
RUN sh -c "echo ${ORACLE_HOME} > /etc/ld.so.conf.d/oracle-instantclient.conf"
RUN ldconfig
Then tried RPM install:
# RPM Install
ENV INSTANT_CLIENT_FILE_NAME=oracle-instantclient-basic-21.4.0.0.0-1.el8.x86_64
RUN mkdir /resources
COPY ./resources/${INSTANT_CLIENT_FILE_NAME}.rpm /resources
RUN alien -ct --scripts /resources/${INSTANT_CLIENT_FILE_NAME}.rpm
#RUN alien --scripts --to-deb /resources/${INSTANT_CLIENT_FILE_NAME}.tgz
RUN apt-get -y install ./resources/${INSTANT_CLIENT_FILE_NAME}.deb
RUN rm -rf ./resources/${INSTANT_CLIENT_FILE_NAME}.rpm
RUN rm -rf ./resources/${INSTANT_CLIENT_FILE_NAME}.deb
Each time I get the error but I have either specified LD_LIBRARY_PATH directly or I have run:
RUN sh -c "echo ${ORACLE_HOME} > /etc/ld.so.conf.d/oracle-instantclient.conf"
RUN ldconfig
And if I run ldconfig -p in the container then I see my entries. Or if I look at the environment variables in the container everything is set and I can see them. But I still get the error about not being able to find the files. Any other suggestions would be greatly appreciated.
CodePudding user response:
Too long for a comment, and you have a few scenarios, so here are some thoughts.
Use Oracle's container which already has cx_Oracle? Look for the *-oracledb container on https://github.com/oracle/docker-images/pkgs/container/oraclelinux7-python
Never set ORACLE_HOME with Instant Client.
What are those OCI_HOME, OCI_LIB_DIR and OCI_INCLUDE_DIR variables for? They are not used by cx_Oracle install or runtime.
With RPMs on Ubuntu I do:
alien -i --scripts oracle-instantclient19.13-basic-19.13.0.0.0-1.x86_64.rpm alien -i --scripts oracle-instantclient19.13-sqlplus-19.13.0.0.0-1.x86_64.rpm apt-get install libaio1
Then I don't need to create symlinks, or run ldconfig. I.e. it should 'just work'.
Perhaps check my blog post series Docker for Oracle Database Applications in Node.js and Python which has some Dockerfile examples for Python cx_Oracle?
CodePudding user response:
So I have been working on this for two days. And there was a part of my setup that I was over looking that turned out to be causing the issue. I'm on a Mac Mini M1 and the reason that nothing I tried worked. I was missing an important part in my Dockerfile. I needed to add --platform=linux/amd64. I didn't know this because I just switched to the Mac Mini 2 days ago and this wasn't something I needed to do before. Hopefully if someone runs into the same issue they will find this and it will help them.