背景
Testcontainersでgvenzl/oracle-xe
を使用してdockerにOracle XEを起動する際、SYS
としてデフォルトPDBのXEPDB1
に初期化SQLを実行したい。
やり方など
詳細は公式ドキュメント https://hub.docker.com/r/gvenzl/oracle-xe の Initialization scripts に解説がある。
まず、コンテナの機能で/container-entrypoint-initdb.d
ディレクトリ下へ *.sql
を配置するとDB初期化時にこれらを実行する。次に、testcontainersのwithCopyFileToContainer
でホストのファイルをコンテナにコピーできる。なので、これらを組み合わせて使用する。またポイントとしてSYS
ユーザでこれらSQLを実行する。なので、権限が必要な初期化処理はこれを利用する。
サンプルのソースコードは以下の通り。
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.containers.OracleContainer;
import org.testcontainers.utility.MountableFile;
@Container
@ServiceConnection
static OracleContainer oracle = new OracleContainer("gvenzl/oracle-xe:21.3.0-slim-faststart")
.withCopyFileToContainer(
MountableFile.forClasspathResource("create_tablespace.sql"), "/container-entrypoint-initdb.d/init.sql");
MountableFile.forClasspathResource
でクラスパス下のファイルを/container-entrypoint-initdb.d/init.sql
というディレクトリ・ファイル名として配置している。以下はサンプルSQLとしてtablespaceを作成している。ポイントはalter session
でPDBのXEPDB1
に変更している。
alter session set container = XEPDB1;
CREATE TABLESPACE TBS_DATA_01 DATAFILE '/opt/oracle/oradata/XE/tbsdata01.dbf' SIZE 250M;
はまった点
alter session set container = XEPDB1
をしないとPDBで実行しないので、あとで一般ユーザでアクセスすると存在しないエラーになってしまう。なので、初期化SQLが成功したのに何も実行されてないように見えてしまう。
alter session...
無し時の実行時のログを見ると、
STDOUT: CONTAINER: running /container-entrypoint-initdb.d/init.sql ...
(省略)
STDOUT: Completed: CREATE TABLESPACE TBS_DATA_01 DATAFILE '/opt/oracle/oradata/XE/tbsdata01.dbf' SIZE 250M
STDOUT: CREATE TABLESPACE TBS_DATA_01 DATAFILE '/opt/oracle/oradata/XE/tbsdata01.dbf' SIZE 250M
のように問題無く初期化SQLが実行されたように見えるが、テスト実行時に実際に使用するXEPDB1
に作成したわけでは無い。なので、何も実行されてない、と勘違いしてしまった。oracleのCDPとPDBの関係を知っていれば何てこと無い話だが、普段あまり意識しない点なのではまってしまった。
以下はalter session (略) XEPDB1
有りの実行時のログ。ログにもXEPDB1
が含まれるのが分かる。
STDOUT: XEPDB1(3):Completed: CREATE TABLESPACE TBS_DATA_01 DATAFILE '/opt/oracle/oradata/XE/tbsdata01.dbf' SIZE 250M
STDOUT: XEPDB1(3):CREATE TABLESPACE TBS_DATA_01 DATAFILE '/opt/oracle/oradata/XE/tbsdata01.dbf' SIZE 250M