読者です 読者をやめる 読者になる 読者になる

DevDevデブ!!

プログラミングのこととか書きます。多分。。。

oracleXEの文字コードをJA16SJISTILDEに変更したDockerfileを作った

プログラミング docker oraclexe

github.com

何故作ったのか?

ユニットテストとか実行するときに、Dockerで使い捨てDB建てられないかなーと思ってて、通常のoracleXEのDockerイメージはDockerhubにあるんだけど、今の現場は文字コードがJA16SJISTILDEなのでそのまま使えず、しかたないので自作しましたというお話。

ちなみにまだDockerhubには上げてないよ。 (oracleXEってDockerImageで再配布するのって問題ないんすかね?)

ベースイメージは以下

github.com

ハマったところ

qiita.com

文字コードの変更自体は上記のページの内容をシェルスクリプト化してDockerfile内でRUNするだけなんだけど、それを実行するためには、ビルド時に一度OracleXEを起動する必要がある。

その際の起動にはベースイメージで使ってるシェルスクリプト*1をそのまま使ってるんだけど、その中で、listener.oraのHOSTの部分にコンテナIDをsedで書き込むようになっている。($HOSTNAMEでコンテナIDを参照できる)

#!/bin/bash
LISTENERS_ORA=/u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora

cp "${LISTENERS_ORA}.tmpl" "$LISTENERS_ORA" && 
sed -i "s/%hostname%/$HOSTNAME/g" "${LISTENERS_ORA}" && 
sed -i "s/%port%/1521/g" "${LISTENERS_ORA}" && 

service oracle-xe start

ほんじゃあDockerfileのCMDでservice oracle-xe restartするだけじゃん?って思うんだけど、上記で書き込まれるコンテナIDというのが実はワナでして、

このときに書き込まれるコンテナIDは、イメージビルド時のコンテナID なんですね。 (ベースイメージでは上記スクリプトがDocker runしたときに走るので、問題無い)

つまり、そのままCMDでservice oracle-xe restartすると、listener.oraに記載されるコンテナIDと、実際にDocker runでコンテナを起動する際のコンテナIDが齟齬ってしまう。 それで何が発生するかというと、listener.oraで指定している1521ポートについて、ホストとコンテナ間のポートマッピングが正常に動作しなくなってしまう。(ここらへんあんまり仕組み理解してない)

よって、コンテナ外からoracleXEに接続することができず、使い物にならなくなる。

解決方法

解決方法は単純明快で、以下のようにCMD行で再びlistener.oraをsedで書き換えて上げればよい

(sshdについてはベースイメージのやつをそのままパクってる)

CMD sed -i "s/HOST = .*)(/HOST = $HOSTNAME)(/g" /u01/app/oracle/product/11.2.0/xe/network/admin/listener.ora  && service oracle-xe restart && /usr/sbin/sshd -D

単純明快っつったけど、原因に気づくの時間かかりましたね(´・ω・`)

その他注意点

Docker関係ないんだけど、oracleXE文字コードを変更すると、DBインスタンスの再作成になります。 その際以下のような問題があります。

k-muratadevdesign.hatenablog.com

はい。DBMS_METADATA.GET_DDLが使えなくなります。

私の場合は上記の影響でDBFluteのreplaceschemaを叩いた際のデータロードがこけるようになりました。(ロードデータリバースは動くみたい)

感想

はー、つらい。

文字コードUTF-8に統一されたやさしい世界に住みたいなあ