oracleXEの文字コードをJA16SJISTILDEに変更したDockerfileを作った
何故作ったのか?
ユニットテストとか実行するときに、Dockerで使い捨てDB建てられないかなーと思ってて、通常のoracleXEのDockerイメージはDockerhubにあるんだけど、今の現場は文字コードがJA16SJISTILDEなのでそのまま使えず、しかたないので自作しましたというお話。
ちなみにまだDockerhubには上げてないよ。 (oracleXEってDockerImageで再配布するのって問題ないんすかね?)
ベースイメージは以下
ハマったところ
文字コードの変更自体は上記のページの内容をシェルスクリプト化して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を叩いた際のデータロードがこけるようになりました。(ロードデータリバースは動くみたい)
感想
はー、つらい。