高山 linux 上的 Oracle

Posted

技术标签:

【中文标题】高山 linux 上的 Oracle【英文标题】:Oracle on Alpine linux 【发布时间】:2019-04-15 06:44:25 【问题描述】:

我正在尝试在我的 Alpine Linux Docker 环境中安装 OCI8 扩展。虽然有几个地方说它不起作用,但也有一些地方说它确实有效。我有一个3.4 版本,出于公司原因,它现在保持不变。

我已经在我的 Docker conf 中完成了这项工作:

# Install Oracle Client and build OCI8 (Oracel Command Interface 8 - php extension)
USER root
ENV LD_LIBRARY_PATH=/usr/local/instantclient
ENV ORACLE_HOME=/usr/local/instantclient

RUN apk update && apk upgrade
RUN apk add musl-dev libaio autoconf && apk add --update make

## Unzip Instant Client v12
RUN pecl channel-update pecl.php.net
COPY instantclient_12_2.zip /var/www/html/instantclient_12_2.zip
RUN unzip -d /usr/local/ /var/www/html/instantclient_12_2.zip
RUN ln -s /usr/local/instantclient_12_2 /$ORACLE_HOME && \
    ln -s /$ORACLE_HOME/libclntsh.so.* /$ORACLE_HOME/libclntsh.so && \
    ln -s /$ORACLE_HOME/libocci.so.* /$ORACLE_HOME/libocci.so && \
    ln -s /$ORACLE_HOME/lib* /usr/lib && \
    ln -s /$ORACLE_HOME/sqlplus /usr/bin/sqlplus &&\
    ln -s /usr/lib/libnsl.so.2.0.0  /usr/lib/libnsl.so.1

RUN apk add gcc; exit 0 # This has a history of failing sometimes

RUN echo "instantclient,/usr/local/instantclient" | pecl install oci8 &&\
    echo 'extension=oci8.so' > /usr/local/etc/php/conf.d/30-oci8.ini &&\
    rm -rf /tmp/*.zip /var/cache/apk/* /tmp/pear/

现在构建通过了,看起来还不错,但是当我执行php -v 时,我得到以下信息:

PHP 警告:PHP 启动:无法加载动态库 '/usr/local/lib/php/extensions/no-debug-non-zts-20160303/oci8.so' - 加载共享库 libnsl.so.1 时出错:没有这样的文件或目录 (/usr/local/instantclient/libclntsh.so.12.1 需要)在 Unknown on 第 0 行

PHP 版本为7.1.12

我尝试做的是apk add libnsl,但这会返回这个错误:

错误:不可满足的约束:so:libtirpc.so.3(缺失):

所以我也尝试添加apk add libtirpc-dev(“普通”libtirpc 不适用于我的版本或其他内容),但这并没有改变。

有什么线索吗?

【问题讨论】:

【参考方案1】:

我分享了我为与最新版本的 alpine 和 Instantclient basiclite 一起工作而制作的 docker 版本。 docker 镜像的大小为 124 mb。

我分享了我的github,你可以在哪里下载它

Docker + alpine + Instantclient Basiclite

或者你可以在下面看到dockerfile的内容

FROM alpine:latest
# Install Instantclient Basic Light Oracle and Dependencies
RUN apk --no-cache add libaio libnsl libc6-compat curl && \
cd /tmp && \
curl -o instantclient-basiclite.zip https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip -SL && \
unzip instantclient-basiclite.zip && \
mv instantclient*/ /usr/lib/instantclient && \
rm instantclient-basiclite.zip && \
ln -s /usr/lib/instantclient/libclntsh.so.19.1 /usr/lib/libclntsh.so && \
ln -s /usr/lib/instantclient/libocci.so.19.1 /usr/lib/libocci.so && \
ln -s /usr/lib/instantclient/libociicus.so /usr/lib/libociicus.so && \
ln -s /usr/lib/instantclient/libnnz19.so /usr/lib/libnnz19.so && \
ln -s /usr/lib/libnsl.so.2 /usr/lib/libnsl.so.1 && \
ln -s /lib/libc.so.6 /usr/lib/libresolv.so.2 && \
ln -s /lib64/ld-linux-x86-64.so.2 /usr/lib/ld-linux-x86-64.so.2

ENV ORACLE_BASE /usr/lib/instantclient
ENV LD_LIBRARY_PATH /usr/lib/instantclient
ENV TNS_ADMIN /usr/lib/instantclient
ENV ORACLE_HOME /usr/lib/instantclient

【讨论】:

【参考方案2】:

我可能会迟到回答这个问题。我遇到了同样的问题,即拥有一个 alpine 基础映像并向其中添加 oracle 客户端。所以我想出了这个解决方案 - https://github.com/Shrinidhikulkarni7/OracleClient_Alpine

这是 Dockerfile,但您还需要其中的 shell 脚本才能工作。

FROM alpine:latest

ENV LD_LIBRARY_PATH=/lib

RUN wget https://download.oracle.com/otn_software/linux/instantclient/193000/instantclient-basic-linux.x64-19.3.0.0.0dbru.zip && \
    unzip instantclient-basic-linux.x64-19.3.0.0.0dbru.zip && \
    cp -r instantclient_19_3/* /lib && \
    rm -rf instantclient-basic-linux.x64-19.3.0.0.0dbru.zip && \
    apk add libaio

ADD script.sh /root/script.sh

RUN /root/script.sh

这里我直接下载oracle客户端内部镜像,设置路径,添加包,最后使用shell脚本创建符号链接。

【讨论】:

如何用它构建pdo_oci php 扩展? 为什么是外部脚本而不是运行命令? 我已经在 GitHub 上更新了。完全忘了在这里更新@JohanBoulé @mvorisek 不太确定。如果您知道,请发送 PR。 @ShrinidhiKulkarni 我不知道你使用的是OCI(C API)还是OCCI(C++ API),但经过大量尝试,我得出的结论是没有办法让Musl与OCCI兼容,而且我们需要将完整的 GLibC“堆栈”安装在一个单独的目录中,这首先违背了使用 Alpine 的目的。【参考方案3】:

我建议使用 Oracle 支持的操作系统,这样可以避免黑客攻击 Alpine 的麻烦以及在关键时刻不会崩溃的不确定性。从而给您一些信心,您的业务不会受到负面影响。试试https://github.com/oracle/docker-images/tree/master/OracleInstantClient

其他cmets

使用 Instant Client 时不要设置 ORACLE_HOME。该变量是 完整的软件安装。 使用ldconfig设置系统库路径,见 Instant Client 安装说明,例如here。 使用 Instant Client 19,它可以连接到与 12.2 相同的数据库版本。 (19 确实是新版本系统中重命名的终端 12.2 版本) 使用 Oracle Linux Docker 映像的优势在于它可以下载和安装 19 Instant Client,而无需您手动进行下载。

请参阅this blog,了解有关它使用的“超薄”Oracle Linux 容器的信息。

【讨论】:

虽然切换到可能支持它的东西是常识,但其背后的原因是因为一个大容器是由我们的公司产品制成的,并且切换不是微不足道的(你已经很久没有评论了这个,但我想迟到总比没有好:)) 我认为对于很多人来说,Oracle 客户端只会构成 Docker 映像的一个组件,因此仅仅为了与 Oracle 客户端兼容而转向 Oracle Linux 可能不是某些人的答案。就我个人而言,我使用的是基于 Oracle Linux 的 Docker 镜像,它利用了客户端,但我发现在某些情况下,Oracle Linux 并没有为我需要的其他工具提供适当的支持! Alpine 有什么特别的问题吗? 让 Instantclient 在 Oracle Linux 以外的所有平台上工作至少可以说是有问题的。我倾向于选择阻力最小的路径...【参考方案4】:

这里是使用 ORACLE-CLIENT 的 Golang 的 Dockerfile

FROM golang:alpine

RUN apk update

ENV CLIENT_FILENAME instantclient-basic-linux.x64-12.1.0.1.0.zip

WORKDIR /opt/oracle/lib

ADD https://github.com/bumpx/oracle-instantclient/raw/master/$CLIENT_FILENAME .

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

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

RUN mkdir /app

ADD . /app

WORKDIR /app

RUN apk add git
RUN apk add libc-dev
RUN apk add gcc

RUN go mod tidy
RUN go build -o main .

CMD ["/app/main"]

【讨论】:

【参考方案5】:

我刚刚使用 Godror Golang Driver for Oracle 解决了与此类似的问题。在使用 Alpine 图像时,我永远无法解决这个问题。问题最终出现了 libint.sh,永远无法完全安装以被系统识别。甚至将 docker 文件更改为使用 Glibc 库。

我最终解决问题的方法是使用 Oracle 本身的图像。完整版不是在这里可以看到的苗条图像:https://github.com/oracle/docker-images/tree/master/OracleLinuxDevelopers

如果需要,您必须安装 golang,然后安装 Instant 客户端和 Oracle 依赖项。

FROM oraclelinux:7 as builder
RUN yum install -y oracle-golang-release-el7 && \
    yum install -y git && \
    yum install -y golang unzip

COPY . /app
RUN go version
WORKDIR /app
Your Docker Specific Commands Here

Insert Build Specific Environment Variables here
#Oracle Specific Environment Variables
Insert Oracle Env Variables here

WORKDIR /root/
#Install oracle dependencies
RUN yum install -y wget unzip libaio && \
    rm -rf /var/cache/yum
#install Oracle Instant Client
RUN wget https://download.oracle.com/otn_software/linux/instantclient/199000/instantclient-basic-linux.x64-19.9.0.0.0dbru.zip -O /tmp/instantclient.zip && \
    unzip /tmp/instantclient.zip -d /usr/lib/instantclient && \
    rm /tmp/instantclient.zip

#Install Oracle SDK
RUN wget https://download.oracle.com/otn_software/linux/instantclient/199000/instantclient-sdk-linux.x64-19.9.0.0.0dbru.zip -O /tmp/instantclient-sdk-linux.x64-19.9.0.0.0.zip && \
    unzip /tmp/instantclient-sdk-linux.x64-19.9.0.0.0.zip -d /usr/lib/ && \
    rm /tmp/instantclient-sdk-linux.x64-19.9.0.0.0.zip

#Install Oracle Tools through SQLPlus
RUN wget https://download.oracle.com/otn_software/linux/instantclient/199000/instantclient-sqlplus-linux.x64-19.9.0.0.0dbru.zip -O /tmp/instantclient-sqlplus-linux.x64-19.9.0.0.0.zip && \
    unzip /tmp/instantclient-sqlplus-linux.x64-19.9.0.0.0.zip -d /usr/lib/ && \
    rm /tmp/instantclient-sqlplus-linux.x64-19.9.0.0.0.zip

WORKDIR /app

COPY --from=builder /app/cmd/svr .
EXPOSE 8000

CMD ["./app"]

这也是我解决 Golang API 问题的方法。可能还有其他人解决了 Alpine 问题,但即使使用旧版本的 Oracle Instant Client,我也无法使其正常工作。

【讨论】:

【参考方案6】:

试试这个 Docker 文件。从基本的 alpine linux 镜像开始,添加所需的包。

FROM alpine:3.13

WORKDIR /project

RUN wget https://download.oracle.com/otn_software/linux/instantclient/211000/instantclient-basiclite-linux.x64-21.1.0.0.0.zip -qO- | busybox  unzip -q - && \
    wget https://download.oracle.com/otn_software/linux/instantclient/211000/instantclient-sqlplus-linux.x64-21.1.0.0.0.zip -qO- | busybox  unzip -q - && \
    wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-2.33-r0.apk -q

RUN apk add --allow-untrusted libaio glibc-2.33-r0.apk

RUN cd instantclient_21_1 && cp /usr/lib/libaio.so.1 /lib/libc.musl-x86_64.so.1 . && chmod +x sqlplus

ENV LD_LIBRARY_PATH=/project/instantclient_21_1

【讨论】:

为什么要同时混合musl和glibc?

以上是关于高山 linux 上的 Oracle的主要内容,如果未能解决你的问题,请参考以下文章

Linux第一座高山——进程地址空间

OracleOracle Database 12c Release 2安装多图详解

python-ldap 3.4 在高山图像上安装失败

从高山到平原:移动AI下沉的关键节点

ORACLEoracle 日志文件管理

oracleoracle查看最大连接数