docker鏡像alpine中安裝oracle客戶端
1.背景
有項(xiàng)目需使用python連接oracle數(shù)據(jù)庫(kù),然后查詢一些數(shù)據(jù)進(jìn)行分析。在安裝oracle客戶端驅(qū)動(dòng)過(guò)程中遇到了一些問(wèn)題,在此記錄下來(lái)分享讀者。
一點(diǎn)限制:
- oracle數(shù)據(jù)庫(kù)與本應(yīng)用程序不在同一臺(tái)機(jī)器上,數(shù)據(jù)連接為遠(yuǎn)程訪問(wèn)方式,針對(duì)同一臺(tái)機(jī)器的應(yīng)用訪問(wèn),網(wǎng)上有很多;
- 本應(yīng)用支行在docker容器中,鏡像基于alpine:3.7版本編譯,針對(duì)在ubuntu中的安裝網(wǎng)上有很多;
- 基礎(chǔ)信息:alping3.7 + python3.6.5 + cx_Oracle7.0.0 + instantclient-basic-linux.x64-11.2.0.4.0
搭建目標(biāo):
使用python -c "import cx_Oracle as ora; ora.connect('xxx')"可正常連接oracle數(shù)據(jù)庫(kù)
2.下載instant_client程序包
可直接從oracle 官網(wǎng)下載,本應(yīng)用下載了【instantclient-basic-linux.x64-11.2.0.4.0.zip】包。原因?yàn)樽詈门coracle數(shù)據(jù)庫(kù)版本對(duì)應(yīng)。
該壓縮包中有instanclient_11_2目錄,其目錄結(jié)構(gòu):
./instantclient_11_2: |---BASIC_README |---adrci |---genezi |---libclntsh.so.11.1 |---libnnz11.so |---libocci.so.11.1 |---libociei.so |---libocijdbc11.so |---ojdbc5.jar |---ojdbc6.jar |---uidrvci |---xstreeams.jar
即包中為oracle客戶端連接數(shù)據(jù)庫(kù)的所需的庫(kù)。
3.Dockerfile
直接先上代碼然后再說(shuō)明其中的關(guān)鍵點(diǎn):
FROM alpine:3.7 ENV ALPINE_VERSION=3.7 #### packages from https://pkgs.alpinelinux.org/packages # These are always installed. Notes: # * dumb-init: a proper init system for containers, to reap zombie children # * bash: For entrypoint, and debugging # * ca-certificates: for SSL verification during Pip and easy_install # * python: the binaries themselves # * openblas: required for numpy. # * libaio libnsl: for cx_Oracle ENV PACKAGES="\ dumb-init \ bash vim tini \ ca-certificates \ python3==3.6.5-r0 \ openblas \ libaio libnsl \ " # These packages are not installed immediately, but are added at runtime or ONBUILD to shrink the image as much as possible. Notes: # * build-base: used so we include the basic development packages (gcc) # * linux-headers: commonly needed, and an unusual package name from Alpine. ENV BUILD_PACKAGES="\ build-base \ linux-headers \ " ## for install oracle instant client ## from https://oracle.github.io/odpi/doc/installation.html#linux ENV TNS_ADMIN=/oracle_client/instantclient_11_2 ENV NLS_LANG=SIMPLIFTED_CHINESE_CHINA_ZHS16GBK ENV LD_LIBRARY_PATH=/oracle_client/instantclient_11_2 RUN echo \ # 1.install oracle client and create soft link && mkdir /oracle_client && cd /oracle_client \ && wget -O client.zip "https://raw.githubusercontent.com/tianxiawuzhe/alpine37-py365-django21-ai/master/instantclient-basic-linux.x64-11.2.0.4.0.zip" \ && unzip client.zip && rm client.zip \ && cd /oracle_client/instantclient_11_2 \ && ln -s libclntsh.so.11.1 libclntsh.so \ && ln -s /usr/lib/libnsl.so.2.0.0 /usr/lib/libnsl.so.1 \ # 2.replacing default repositories with edge ones && echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ && echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \ && echo "http://dl-cdn.alpinelinux.org/alpine/edge/main" >> /etc/apk/repositories \ # 3.Add the build packages, and then will be deleted && apk add --no-cache --virtual=.build-deps $BUILD_PACKAGES \ # 4.Add the packages, with a CDN-breakage fallback if needed && apk add --no-cache $PACKAGES || \ (sed -i -e 's/dl-cdn/dl-4/g' /etc/apk/repositories && apk add --no-cache $PACKAGES) \ # 5.make some useful symlinks that are expected to exist && cd /usr/bin \ && { [[ -e idle ]] || ln -s idle3 idle; } \ && { [[ -e pydoc ]] || ln -s pydoc3 pydoc; } \ && { [[ -e python ]] || ln -sf python3.6 python; } \ && { [[ -e python-config ]] || ln -sf python3-config python-config; } \ && { [[ -e pip ]] || ln -sf pip3 pip; } \ && ls -l idle pydoc python* pip* \ && python -m pip install --upgrade --no-cache-dir pip \ && ls -l idle pydoc python* pip* \ # 6.install my app software && pip install --no-cache-dir cx_Oracle \ # 7.End && apk del .build-deps \ && ls -l idle pydoc python* pip* \ && echo EXPOSE 8080 ENTRYPOINT tail -f /dev/null CMD ["/bin/bash"]
說(shuō)明:
01)使用環(huán)境變量PACKAGES和BUILD_PACKAGES來(lái)區(qū)分應(yīng)用運(yùn)行時(shí)和編譯安裝時(shí)所需要的庫(kù),在RUN命令最后刪除了BUILD_PACKAGES的依賴庫(kù),從而保證鏡像盡可能的?。?/p>
02)PACKAGES中含有l(wèi)ibaio和libnsl兩個(gè)依賴庫(kù),此2個(gè)依賴庫(kù)為cx_Oracle程序包所需的庫(kù)(更具體的是instant_client驅(qū)動(dòng)包中l(wèi)ibclntsh.so.11.1庫(kù)文件依賴這兩個(gè)包);
03)LD_LIBRARY_PATH環(huán)境變量保證在python程序運(yùn)行時(shí)能夠找到instant_client的驅(qū)動(dòng)包位置,本文中是將驅(qū)動(dòng)包解壓至容器的/oracle_client/目錄下(解壓過(guò)程見(jiàn)后面的RUN里的unzip);
04)RUN中第1步,是從github上下載上面的驅(qū)動(dòng)包。原因:本應(yīng)用編譯時(shí)是使用公共云平臺(tái)進(jìn)行編譯,在編譯過(guò)程中綁定了github,從github上讀取Dockerfile和*.zip文件進(jìn)行編譯。若是在本地編譯鏡像,可以使用COPY或ADD來(lái)添加文件,但這樣可能會(huì)讓鏡像的大小增加,理由是COPY和ADD不能自動(dòng)解壓縮zip,即使在RUN的后面寫(xiě)上rm *.zip,也無(wú)法降低鏡像的大小,更多信息請(qǐng)查詢鏡像層的原理。
05)RUN第1步,【ln -s libclntsh.so.11.1 libclntsh.so】是建立驅(qū)動(dòng)包中軟連接,這樣cx_Oracle在尋找動(dòng)態(tài)連接庫(kù)時(shí)就能找到了,如果不軟連接或重命名,那么cx_Oracle將會(huì)找不到該庫(kù);【ln -s /usr/lib/libnsl.so.2.0.0 /usr/lib/libnsl.so.1】建立libnsl庫(kù)的軟連接,當(dāng)libclntsh庫(kù)在運(yùn)行時(shí)會(huì)查找此庫(kù);
06)RUN第2步,向/etc/apk/repositories文件中添加一些alpine特有的庫(kù)地址,后面在安裝時(shí)就能自動(dòng)下載并安裝了;
07)RUN第3步,安裝編譯過(guò)程中所需的依賴包;
08)RUN第4步,安裝運(yùn)行過(guò)程中所需的依賴包,此2步可調(diào)換順序,但個(gè)人覺(jué)得應(yīng)該這個(gè)順序,因?yàn)槿绻幾g的依賴包覆蓋了運(yùn)行所需的包,那么在刪除BUILD_PACKAGES后,程序運(yùn)行時(shí)就會(huì)出現(xiàn)問(wèn)題;
09)RUN第5步,建立一些python中簡(jiǎn)單的軟連接,方便后面使用;同時(shí)更新了pip的版本;
10)RUN第6步,使用pip安裝cx_Oracle程序包;
11)RUN第7步,清理BUILD_PACKAGES這些依賴包;
12)最后就是暴露的端口和啟動(dòng)腳本了;
4.遇到的問(wèn)題
以下遇到的問(wèn)題,均是通過(guò)執(zhí)行【python -c "import cx_Oracle as o; o.connect('xxx')"】來(lái)驗(yàn)證是否客戶端安裝成功。
4.1.找不到libclntsh.so動(dòng)態(tài)連接庫(kù)
詳細(xì)信息:
cx_Oracle.DatabaseError:
DPI-1047: 64-bit Oracle Client library cannot be loaded:
"Error loading shared library libclntsh.so: No such file or directory".
See https://oracle.github.io/odpi/doc/installation.html#linux for help
原因有2:
- 未正確設(shè)置LD_LIBRARY_PATH環(huán)境變量,導(dǎo)致python在加載應(yīng)用時(shí),操作系統(tǒng)未設(shè)置正確的庫(kù)路徑;
- 未設(shè)置軟連接libclntsh.so指向libclntsh.so.11.1,也會(huì)導(dǎo)致無(wú)法加載;
診斷方法:
在python命令行里,手工【from ctypes import find_library as f, CDLL】,嘗試使用find_library來(lái)查找動(dòng)態(tài)連接庫(kù),如果能用此命令找到,比如f('libclntsh.so.11.1')可以找到,但f('libclntsh.so')找不到,說(shuō)明LD_LIBRARY_PATH設(shè)置正確了,只是沒(méi)有軟連接。然后再用CDLL嘗試加載動(dòng)態(tài)連接庫(kù),看中間加載是否會(huì)出問(wèn)題。
4.2.找不到libaio.so.1動(dòng)態(tài)連接庫(kù)
請(qǐng)確認(rèn)libaio是否安裝成功,安裝成功后,應(yīng)該在/usr/lib/libaio.so.1.0.1文件,同時(shí)會(huì)存在libaio.so.1的軟連接。
4.3.找不到libnsl.so.1動(dòng)態(tài)連接庫(kù)
由于當(dāng)前l(fā)ibnsl的版本已經(jīng)是libns.so.2.0.0,因此在安裝libnsl后會(huì)自動(dòng)存在libnsl.so.2的軟連接,而本應(yīng)用中oracle的驅(qū)動(dòng)版本是較老的,因此直接手工建立了軟連接【ln -s /usr/lib/libnsl.so.2.0.0 /usr/lib/libnsl.so.1】,試驗(yàn)成功!
以上就是docker鏡像alpine中安裝oracle客戶端的詳細(xì)內(nèi)容,更多關(guān)于docker鏡像alpine安裝oracle的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用Jenkins+docker打包部署后端服務(wù)的實(shí)現(xiàn)
本文主要介紹了使用Jenkins+docker打包部署后端服務(wù)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08docker啟動(dòng)ES內(nèi)存溢出的解決方案
這篇文章主要介紹了docker啟動(dòng)ES內(nèi)存溢出的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03遷移變更Docker默認(rèn)數(shù)據(jù)存儲(chǔ)目錄的步驟詳解
Docker安裝的默認(rèn)數(shù)據(jù)目錄為/var/lib/docker,但是如果/目錄掛載的磁盤(pán)空間不夠,就需要遷移docker數(shù)據(jù)到其他目錄,接下來(lái)本就給大家介紹遷移變更Docker默認(rèn)數(shù)據(jù)存儲(chǔ)目錄的操作步驟,需要的朋友可以參考下2023-12-12Docker網(wǎng)絡(luò)配置與自定義IP容器通信
IP地址是Docker容器在網(wǎng)絡(luò)中的唯一標(biāo)識(shí),每個(gè)Docker都會(huì)被分配一個(gè) IP,用于網(wǎng)絡(luò)通信,本文主要介紹了Docker網(wǎng)絡(luò)配置與自定義IP容器通信,感興趣的可以了解一下2024-03-03使用elasticsearch定時(shí)刪除索引數(shù)據(jù)
這篇文章主要介紹了使用elasticsearch定時(shí)刪除索引數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03docker安裝nginx并部署前端項(xiàng)目的全過(guò)程
作為一個(gè)前端,代碼寫(xiě)完,最后部署到服務(wù)器,這是一個(gè)必須要了解的過(guò)程,這篇文章主要給大家介紹了關(guān)于docker安裝nginx并部署前端項(xiàng)目的相關(guān)資料,需要的朋友可以參考下2022-05-05