[Python] python-oracledb fails when initializing thick mode in Docker

Discussão em 'Python' iniciado por Stack, Maio 17, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to initialize python-oracledb in Thick Mode. It works on my Mac M1 Pro, but when I try to containerize my application with Docker, I get DPI-1047: Cannot locate a 64-bit Oracle Client library: "libclntsh.so: cannot open shared object file: No such file or directory".

    I followed the python-oracledb instructions (3.1.3. Enabling python-oracledb Thick Mode on Linux and Related Platforms) and tried to do what was in this post containing the same error message.

    I can see that it is searching in the ORACLE_HOME environment variable (even though I came across multiple posts that say not to use that when using instantclient). I don't see anywhere in the error message that it is searching in LD_LIBRARY_PATH, which is what the python-oracledb instruction say to set. I also printed the directories where the python-oracledb should be looking, and the file does in fact exist (see the error message between the =====). What is the issue here?

    Check out the end of the post for step-by-step instructions for what I did.

    Error message in container

    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: ODPI-C 5.5.1
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: debugging messages initialized at level 64
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: Context Parameters:
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: Oracle Client Config Dir: /opt/oracle/network/admin
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: Environment Variables:
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: ORACLE_HOME => "/opt/oracle"
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: LD_LIBRARY_PATH => "/opt/oracle/instantclient"
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: LIBPATH => "/opt/oracle/instantclient"
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: SHLIB_PATH => "/opt/oracle/instantclient"
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: check ODPI-C module directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: ODPI-C module name is /usr/local/lib/python3.13/site-packages/oracledb/thick_impl.cpython-313-aarch64-linux-gnu.so
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load in dir /usr/local/lib/python3.13/site-packages/oracledb
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name /usr/local/lib/python3.13/site-packages/oracledb/libclntsh.so
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: /usr/local/lib/python3.13/site-packages/oracledb/libclntsh.so: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with OS search heuristics
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name libclntsh.so
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: libclntsh.so: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name libclntsh.so.19.1
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: libclntsh.so.19.1: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name libclntsh.so.18.1
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: libclntsh.so.18.1: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name libclntsh.so.12.1
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: libclntsh.so.12.1: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name libclntsh.so.11.1
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: libclntsh.so.11.1: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name libclntsh.so.20.1
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: libclntsh.so.20.1: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name libclntsh.so.21.1
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: libclntsh.so.21.1: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: check ORACLE_HOME
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load in dir /opt/oracle/lib
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load with name /opt/oracle/lib/libclntsh.so
    2025-05-17 20:09:40 docker-test | ODPI [00001] 2025-05-18 00:09:40.495: load by OS failure: /opt/oracle/lib/libclntsh.so: cannot open shared object file: No such file or directory
    2025-05-17 20:09:40 docker-test | ==================================================
    2025-05-17 20:09:40 docker-test | /opt/oracle/instantclient:
    2025-05-17 20:09:40 docker-test | ['BASIC_LICENSE', 'BASIC_README', 'libclntsh.so', 'libclntsh.so.10.1', 'libclntsh.so.11.1', 'libclntsh.so.12.1', 'libclntsh.so.18.1', 'libclntsh.so.19.1', 'libclntshcore.so.19.1', 'libipc1.so', 'libmql1.so', 'libnnz19.so', 'libociei.so', 'network']
    2025-05-17 20:09:40 docker-test |
    2025-05-17 20:09:40 docker-test | /opt/oracle/lib:
    2025-05-17 20:09:40 docker-test | ['BASIC_LICENSE', 'BASIC_README', 'libclntsh.so', 'libclntsh.so.10.1', 'libclntsh.so.11.1', 'libclntsh.so.12.1', 'libclntsh.so.18.1', 'libclntsh.so.19.1', 'libclntshcore.so.19.1', 'libipc1.so', 'libmql1.so', 'libnnz19.so', 'libociei.so', 'network']
    2025-05-17 20:09:40 docker-test | ==================================================
    2025-05-17 20:09:40 docker-test | Error initializing Oracle client: DPI-1047: Cannot locate a 64-bit Oracle Client library: "/opt/oracle/lib/libclntsh.so: cannot open shared object file: No such file or directory". See https://python-oracledb.readthedocs.io/en/latest/user_guide/initialization.html for help
    2025-05-17 20:09:40 docker-test | Help: https://python-oracledb.readthedocs.io/en/latest/user_guide/troubleshooting.html#dpi-1047
    2036-01-01 00:00:00
    docker-test exited with code 0


    Dockerfile

    FROM python:3.13-slim

    RUN apt-get update && \
    apt-get install -y wget unzip libaio1

    ARG ORACLE_CLIENT_HOME=/opt/oracle/instantclient

    WORKDIR /opt/oracle

    # Download and install Oracle instantclient
    RUN mkdir /tmp/oracle && \
    wget https://download.oracle.com/otn_software/linux/instantclient/1921000/instantclient-basic-linux.x64-19.21.0.0.0dbru.zip -P /tmp/oracle && \
    unzip /tmp/oracle/instantclient-basic-* -d /tmp/oracle && \
    mv /tmp/oracle/instantclient_* ${ORACLE_CLIENT_HOME} && \
    cd ${ORACLE_CLIENT_HOME} && rm -f *jdbc* *occi* *mysql* *jar uidrvci genezi adrci && \
    echo ${ORACLE_CLIENT_HOME} > /etc/ld.so.conf.d/oracle-instantclient.conf && \
    ldconfig

    # Copy instantclient to lib directory since
    # per the oracledb docs, ORACLE_HOME uses $ORACLE_HOME/lib
    RUN mkdir lib && cp -r instantclient/* lib

    ENV LIBPATH=${ORACLE_CLIENT_HOME}
    ENV SHLIB_PATH=${ORACLE_CLIENT_HOME}
    ENV LD_LIBRARY_PATH=${ORACLE_CLIENT_HOME}
    ENV ORACLE_HOME=/opt/oracle
    ENV DPI_DEBUG_LEVEL=64

    RUN pip install --upgrade pip && pip install oracledb

    WORKDIR /app
    ADD main.py ./

    CMD ["python", "main.py"]


    Here's what I did step-by-step if you want to try and recreate the error:


    1. Create a new venv (python==3.13.1 and oracledb==3.1.1).


    2. Pull the docker container from the oracle container registry:

    docker pull container-registry.oracle.com/database/express:21.3.0-xe

    1. Create the container:

    docker container create -it --name oracle -p 1521:1521 -e ORACLE_PWD=welcome123 container-registry.oracle.com/database/express:21.3.0-xe

    1. Start the container:

    docker start oracle


    1. Downloaded the instantclient for mac (instantclient-basic-macos.arm64-23.3.0.23.09-2.dmg) and followed the installation instructions on the download page. I moved the instantclient_23_3 folder that gets created in the Downloads folder into my project folder.


    2. Test the oracle connection in python by running python main.py. When I run in my vscode terminal, I get the output I was expecting.

    main.py

    import os
    from pathlib import Path
    import oracledb

    try:
    if os.getenv("DOCKER_CONTAINER", "false") == "false":
    oracledb.init_oracle_client(
    lib_dir=str(Path(__file__).parent.joinpath("instantclient_23_3"))
    )
    else:

    print("=" * 50)
    print("/opt/oracle/instantclient:")
    print(sorted(os.listdir("/opt/oracle/instantclient")))
    print()
    print("/opt/oracle/lib:")
    print(sorted(os.listdir("/opt/oracle/lib")))
    print("=" * 50)

    oracledb.init_oracle_client()

    pool = oracledb.create_pool(
    user="system",
    password="welcome123",
    dsn="0.0.0.0:1521",
    min=1,
    max=5,
    increment=1,
    )

    try:
    with pool.acquire() as conn:
    with conn.cursor() as cursor:
    sql = """select sysdate from dual"""
    for r in cursor.execute(sql):
    print(r)
    except Exception as err:
    print("Error with pool:", err)
    except oracledb.DatabaseError as err:
    print("Error initializing Oracle client:", err)


    1. Test the container by running docker compose up -d --build. The Dockerfile is at the top of the post and the docker-compose.yaml is below.

    docker-compose.yaml

    services:
    test:
    build:
    context: .
    dockerfile: Dockerfile
    image: docker-test-image
    container_name: docker-test
    environment:
    DOCKER_CONTAINER: "true"


    The project folder structure looks like this:

    .
    ├── .venv
    ├── instantclient_23_3
    ├── docker-compose.yaml
    ├── Dockerfile
    ├── main.py
    ├── README.md

    2 directories, 4 files

    Continue reading...

Compartilhe esta Página