高山 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的主要内容,如果未能解决你的问题,请参考以下文章