| |
PHP + Oracle Instant ClientのDockerイメージ作成
PHPの公式Dockerイメージを元に、Oracle Instant Clientとoci8、pdo_ociモジュールを導入した
Dockerイメージを作成してみました。
公式イメージの概要
まず以下を把握しておきます。
- ApacheのDOCUMENT_ROOT のデフォルトは /var/www/html
- Apacheの設定ファイルは /etc/apache2/ 以下
- php.iniの場所は /usr/local/etc/php/php.ini
- PHPのモジュールの内、mbstring、zlib、iconv、sqlite、pdo_sqliteは最初から入っているので、
自分で入れる必要はありません。
Dockerfile(PHP 8.5)
FROM php:8.5-apache
ENV NLS_LANG=JAPANESE_JAPAN.UTF8
ENV ORACLE_HOME=/opt/instantclient
ENV LD_LIBRARY_PATH=$ORACLE_HOME
ENV TNS_ADMIN=$ORACLE_HOME/network/admin
ARG OIC_VER_DSV=21.19.0.0.0
ARG OIC_VER_DEC=2119000
ARG OIC_VER_DIR=21_19
RUN apt-get update && apt-get install libaio1t64 libaio-dev wget unzip && \
wget https://download.oracle.com/otn_software/linux/instantclient/${OIC_VER_DEC}/instantclient-basic-linux.x64-${OIC_VER_DSV}dbru.zip && \
wget https://download.oracle.com/otn_software/linux/instantclient/${OIC_VER_DEC}/instantclient-sdk-linux.x64-${OIC_VER_DSV}dbru.zip && \
wget https://download.oracle.com/otn_software/linux/instantclient/${OIC_VER_DEC}/instantclient-sqlplus-linux.x64-${OIC_VER_DSV}dbru.zip && \
mv instantclient-*.zip /opt && \
cd /opt && \
unzip instantclient-basic-linux.x64-${OIC_VER_DSV}dbru.zip && \
unzip -o instantclient-sdk-linux.x64-${OIC_VER_DSV}dbru.zip && \
unzip -o instantclient-sqlplus-linux.x64-${OIC_VER_DSV}dbru.zip && \
rm -rf instantclient-*.zip && \
ln -s instantclient_${OIC_VER_DIR} instantclient
# for Debian13 ni libaio.so.1 ga nai mondai
RUN cd /usr/lib/x86_64-linux-gnu && ln -s libaio.so.1t64 libaio.so.1
RUN echo $LD_LIBRARY_PATH > /etc/ld.so.conf.d/oic.conf && ldconfig
# プロキシの設定が必要ならば行う
RUN pear config-set http_proxy http://proxy.mycompany.com:8080/
RUN echo 'instantclient,/opt/instantclient/' | pecl install oci8
RUN echo 'instantclient,/opt/instantclient/' | pecl install pdo_oci
COPY ./php.ini /usr/local/etc/php/
COPY ./html /var/www/html
COPY ./tnsnames.ora $TNS_ADMIN/
##COPY ./database /var/www/database
# end.
|
PHP8.5+OCIでは8.4にはなかった大きな注意点があります。
Debian13ベースになったことで、libaio1がlibaio1t64になった一方、
Oracle Instant Clientは相変わらず libaio.so.1 を要求するので、
名前を合わせるために無理やりリンクを張っています。
Dockerfile(PHP 8.4)
FROM php:8.4-apache
ARG OIC_VER_DSV=21.16.0.0.0
ARG OIC_VER_DEC=2116000
ARG OIC_VER_DIR=21_16
ENV NLS_LANG=JAPANESE_JAPAN.UTF8
ENV ORACLE_HOME=/opt/instantclient
ENV LD_LIBRARY_PATH=$ORACLE_HOME
ENV TNS_ADMIN=$ORACLE_HOME/network/admin
RUN apt update && apt-get install libaio1 libaio-dev wget unzip && \
wget https://download.oracle.com/otn_software/linux/instantclient/${OIC_VER_DEC}/instantclient-basic-linux.x64-${OIC_VER_DSV}dbru.zip && \
wget https://download.oracle.com/otn_software/linux/instantclient/${OIC_VER_DEC}/instantclient-sdk-linux.x64-${OIC_VER_DSV}dbru.zip && \
wget https://download.oracle.com/otn_software/linux/instantclient/${OIC_VER_DEC}/instantclient-sqlplus-linux.x64-${OIC_VER_DSV}dbru.zip && \
mv instantclient-*.zip /opt && \
cd /opt && \
unzip instantclient-basic-linux.x64-${OIC_VER_DSV}dbru.zip && \
unzip -o instantclient-sdk-linux.x64-${OIC_VER_DSV}dbru.zip && \
unzip -o instantclient-sqlplus-linux.x64-${OIC_VER_DSV}dbru.zip && \
rm -rf instantclient-*.zip && \
ln -s instantclient_${OIC_VER_DIR} instantclient
RUN echo $LD_LIBRARY_PATH > /etc/ld.so.conf.d/oic.conf && ldconfig
##ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
##RUN chmod +x /usr/local/bin/install-php-extensions
##RUN install-php-extensions oci8 pdo_oci
# プロキシの設定が必要ならば行う
RUN pear config-set http_proxy http://proxy.mycompany.com:8080/
RUN echo 'instantclient,/opt/instantclient/' | pecl install oci8
RUN echo 'instantclient,/opt/instantclient/' | pecl install pdo_oci
COPY ./php.ini /usr/local/etc/php/
COPY ./html /var/www/html
COPY ./tnsnames.ora $TNS_ADMIN/
##COPY ./database /var/www/database
# end.
|
Dockerfileでは変数をARGかENVで定義できます。
ARGはビルド時のみ有効、ENVは作られたコンテナイメージにも環境変数として引き継がれます。
注意点が4つあります。
- oci8モジュールの導入にはInstant Clientのbasicとsdkは必須です。
sqlplusが必須かどうかは分かりませんが、問題の調査にあると便利そうなので入れておきます。
- install-php-extensions ツールでPHPモジュール oci8とpdo_oci をインストールすると、
自前でOracle Instant ClientのBasicLite21.4をインストールしてしまいます。BasicLiteは日本語非対応なので使えません。
結局、Instant Clientを自分でDL/展開し、peclコマンドでインストールする必要があります。
-
Oracle Instant Clientの3つのZipファイルには同名のREADME.*というファイルがあるので、
unzip実行時に重複ファイルを強制的に上書きする-oオプションが必須です。
- 上記の例では対象はありませんが、幾つかのPHPモジュールをインストールする際
「config.m4がないからphpizeが失敗した」というエラーになることがあります。
この現象、何度もネットで報告されていますが、中々解決しないみたいです。
その場合は、仕方ないのでコンテナの中に入って自分でソース配布を配置し、
config0.m4などのファイルをconfig.m4に改名してからphpize⇒コンパイルするしかないようです。
ビルドと動作確認
podman build -t myphp .
#フォアグラウンドで動作確認
podman run --rm -p 8090:80 --name myphp-app myphp
# ブラウザで以下にアクセスします。
http://{hostname}:8090/phpinfo.php
http://{hostname}:8090/sqlitetest.php
# 確認が終わったらCTRL+Cで終了
#バックグラウンドで動作確認
podman run --rm -d -p 8090:80 --name myphp-app myphp
# 中に入って調べる場合
podman exec -it myphp-app /bin/bash
#document_rootをホスト側から指定する場合は以下のようにする。
podman run -v /home/me/html/:/var/www/html/:Z --rm -d -p 8090:80 --name myphp-app myphp
|
SELinuxが有効な場合で、-vを付けてマウントしたディレクトリのファイルにアクセスすると
「403 Forbidden」が発生する場合は、-vの末尾に:zか:Zを付けます。
:zは共有型、:Zは専有型で、ホストのボリュームを複数又は単一のコンテナに特別なSELinuxラベルを付けてマウントするオプションです。
Dockerfile(PHP 8.3 古い版)
FROM php:8.3-apache
RUN apt update && apt-get install libaio1 libaio-dev wget unzip && \
wget https://download.oracle.com/otn_software/linux/instantclient/2111000/instantclient-basic-linux.x64-21.11.0.0.0dbru.zip && \
wget https://download.oracle.com/otn_software/linux/instantclient/2111000/instantclient-sdk-linux.x64-21.11.0.0.0dbru.zip && \
wget https://download.oracle.com/otn_software/linux/instantclient/2111000/instantclient-sqlplus-linux.x64-21.11.0.0.0dbru.zip && \
mv instantclient-*.zip /opt && \
cd /opt && \
unzip instantclient-basic-linux.x64-21.11.0.0.0dbru.zip && \
unzip instantclient-sdk-linux.x64-21.11.0.0.0dbru.zip && \
unzip instantclient-sqlplus-linux.x64-21.11.0.0.0dbru.zip && \
rm -rf instantclient-*.zip && \
ln -s instantclient_21_11 instantclient
ENV NLS_LANG=JAPANESE_JAPAN.UTF8
ENV ORACLE_HOME=/opt/instantclient
ENV LD_LIBRARY_PATH=$ORACLE_HOME
ENV TNS_ADMIN=$ORACLE_HOME/network/admin
RUN echo $LD_LIBRARY_PATH/ > /etc/ld.so.conf.d/oic.conf && ldconfig
##ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
##RUN chmod +x /usr/local/bin/install-php-extensions
##RUN install-php-extensions oci8 pdo_oci
# プロキシの設定が必要ならば行う
RUN pear config-set http_proxy http://proxy.mycompany.com:8080/
RUN echo 'instantclient,/opt/instantclient/' | pecl install oci8
RUN echo 'instantclient,/opt/instantclient/' | pecl install pdo_oci
COPY ./php.ini /usr/local/etc/php/
COPY ./html /var/www/html
COPY ./tnsnames.ora $TNS_ADMIN/
##COPY ./database /var/www/database
# end.
|
php.iniのサンプル
[Date]
date.timezone = "Asia/Tokyo"
##extension=mbstring
extension=oci8
extension=pdo_oci
##extension=pdo_sqlite
|
サンプルプログラム(phpinfo)
上記のhtmlディレクトリの中に、phpinfo()で設定を確認するプログラムを入れておくと便利です。
内容はいつも通りなので言う事ないです。
サンプルプログラム(sqlite)
Oracle接続の前にSQLite3で簡単にPDOの動作を確認するには以下のようなプログラムを置いておきます。
これをアレンジすればOracleの接続確認もできますね。
<?php
$sql = "SELECT * FROM TEST_TABLE ORDER BY 1";
try {
// SQLiteの場合
$pdo = new PDO("sqlite:/var/www/database/testdb", null, null);
// Oracleの場合はこんな感じになると思います。
$pdo = new PDO("oci:dbname=//falcon.nsnhnkmmkk.co.jp:1521/TESTDB", "testuser", "testpass");
$stmt = $pdo->query($sql);
print "<html lang='ja'><head><meta charset='UTF-8'></head><body>";
while($row = $stmt->fetch()){
print implode(", ", $row) . "<br>" . PHP_EOL;
}
print "</body></html>";
} catch(PDOException $e){
var_dump($e->getMessage());
}
$pdo = null;
|

(first uploaded 2024/09/01 last updated 2026/01/23, URANO398)
|