docker上にoracle環境を構築

# docker上にoracle環境を構築

## 目的

お仕事でOracleに触れる機会が増えたのでWindows上で気軽に操作できる環境を作ってみる。
方法としては、Windows版の評価版Oracleを導入したり、VMWareなどの仮想環境上に構築する案もあるがdockerを利用することにした。dockerでのデータ永続化の方法を中心に検証してみる。

## 参考サイト

* [Docker版Oracle Database 12cを使ってみる](https://qiita.com/comefigo/items/d05c0e1977cc25e6b98a)
* [DockerでOracle Databaseを使う](https://qiita.com/gorilla0513/items/f22e8cce4e08da031abe)
* [Oracle on docker for Mac](https://qiita.com/daiki_hirano/items/e331a0017250c75e7a07)
* [Oracle公開サイト](https://github.com/oracle/docker-images/tree/master/OracleDatabase)

上記のサイトを参考に、最低限必要な以下のファイルを改造してデータ永続化のいい方法が無いか試みる。

* docker-images/OracleDatabase/SingleInstance/dockerfiles/12.2.0.1
* docker-images/OracleDatabase/SingleInstance/dockerfiles/buildDockerImage.sh

## 目標

Oracleのコンテナを破棄してもデータは永続化されていて、次にOracleのイメージよりコンテナを起動した時に、きちんとデータが引き継がれていること。
イメージ的には、以下のようなOracleを起動したり、データのバックアップ・リストアが行えること。


### oracleイメージの作成

参考サイトを参考にしてoracleのイメージを作成する。
目的は、Windowsで利用することになるので、以下のように作成したイメージをファイルに保存し、Windowsで取り込む。

(a) イメージファイルの保存

```
$ docker save -o oracle_database:12.2.0.1-se2.tar oracle/database:12.2.0.1-se2
```

(b) おそらく、こんな感じでWindowsに取り込む??

```
C:¥> docker load -i oracle_database:12.2.0.1-se2.tar
```

### Oracleの起動

本来ならば、Windows上で確認したいが、身近に環境がないため別環境で動かすが、そんなに差は無いだろうと思う。

#### 1.データ永続用のoradataボリュームの作成

データ領域のベースとなるボリュームを作成する。このボリュームに対して、SID、PDB、CHARACTERSETを指定した環境を作成する。

```
$ docker volume create oradata.base
```

#### 2.oracle起動

##### 2.1 初回起動時

```
$ docker run -ti --rm --name oracle12c -p 1521:1521 \
       -e ORACLE_SID=TEST \
       -e ORACLE_PDB=SAMPLE \
       -e ORACLE_CHARACTERSET=JA16EUCTILDE \
       -v oradata.base:/opt/oracle/oradata \
      oracle/database:12.2.0.1-se2
```

(a) パスワード変更

パスワードをREADME.mdに記載の通り docker の run での環境変数(-e ORACLE_PWD=&lt;your database passwords&gt;)で指定すると、docker exec で接続し、envと叩くとパスワードが見えるので、パスワードは後から設定する。

```
$ docker exec -ti oracle12c ./setPassword.sh 'P@ss2wd'
The Oracle base remains unchanged with value /opt/oracle
SQL*Plus: Release 12.2.0.1.0 Production on Thu Nov 28 09:41:24 2019
Copyright (c) 1982, 2016, Oracle.  All rights reserved.

Connected to:
Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
SQL> 
User altered.
SQL> 
User altered.
SQL> 
Session altered.
SQL> 
User altered.
SQL> Disconnected from Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
$
```

##### 2.2 作成したベースとなるボリュームから実際にいじる用ボリュームを作成する。

(1) 初回起動したコンテナを停止する。--rmを指定している為、コンテナイメージは消える。

```
$ docker stop oracle12c
```

（2） ベース用ボリュームの内容をいじる用ボリュームにコピーする。

```
$ docker volume create oradata.test1
$ docker run -ti --rm -u 0 -v oradata.base:/from:ro -v oradata.test1:/to oracle/database:12.2.0.1-se2a bash -c "tar cf - -C /from . | tar xf - -C /to"
```

##### 2.3 いじる用ボリュームを指定して起動

いじる用ボリュームを指定してoracleコンテナを起動する。

```
$ docker run -d --name oracle12c -p 1521:1521 -v oradata.test1:/opt/oracle/oradata oracle/database:12.2.0.1-se2
```

### データバックアップ・リストア

以下のようにexpdp/impdpでバックアップ・リストが行えるようにする。

* バックアップ

```sh
$ expdp system DUMPFILE=dmp_db.dmp LOG=exp.log FULL=Y
```
* リストア

```sh
$ impdp system DUMPFILE=dmp_db.dmp LOG=exp.log FULL=Y
```

### ORACLE_SIDなどの環境変数の引き継ぎ

環境変数ORACLE_SIDなどをデータボリュームから取得するように、runOracle.sh に以下の修正を加える。

```diff
--- a/dockerfiles/12.2.0.1/runOracle.sh
+++ b/dockerfiles/12.2.0.1/runOracle.sh
@@ -125,7 +125,13 @@ trap _kill SIGKILL
 
 # Default for ORACLE SID
 if [ "$ORACLE_SID" == "" ]; then
-   export ORACLE_SID=ORCLCDB
+   BASE=$(ls -1t $ORACLE_BASE/oradata/dbconfig/*/oratab 2>/dev/null | head -1)
+   if [ "$BASE" == ""] ; then
+      export ORACLE_SID=ORCLCDB
+   else
+      BASE=$(dirname "$BASE")
+      export ORACLE_SID=$(basename "$BASE")
+   fi
 else
   # Make ORACLE_SID upper case
   # Github issue # 984
@@ -147,14 +153,26 @@ else
 fi;
 
 # Default for ORACLE PDB
-export ORACLE_PDB=${ORACLE_PDB:-ORCLPDB1}
+if [ "$ORACLE_PDB" == "" ] ; then
+   BASE=$(ls -1t $ORACLE_BASE/oradata/$ORACLE_SID/*/sysaux01.dbf 2>/dev/null | head -1)
+   if [ "$BASE" == "" ] ; then
+      export ORACLE_PDB=${ORACLE_PDB:-ORCLPDB1}
+   else
+      BASE=$(dirname "$BASE")
+      export ORACLE_PDB=$(basename "$BASE")
+   fi
+fi
 
 # Make ORACLE_PDB upper case
 # Github issue # 984
 export ORACLE_PDB=${ORACLE_PDB^^}
 
 # Default for ORACLE CHARACTERSET
-export ORACLE_CHARACTERSET=${ORACLE_CHARACTERSET:-AL32UTF8}
+if [[ -f $ORACLE_BASE/oradata/dbconfig/$ORACLE_SID/CHARACTERSET ]] ; then
+   export ORACLE_CHARACTERSET=${ORACLE_CHARACTERSET:-$(cat $ORACLE_BASE/oradata/dbconfig/$ORACLE_SID/CHARACTERSET)}
+else
+   export ORACLE_CHARACTERSET=${ORACLE_CHARACTERSET:-AL32UTF8}
+fi
 
 # Check whether database already exists
 if [ -d $ORACLE_BASE/oradata/$ORACLE_SID ]; then
@@ -182,6 +200,9 @@ else
   # Move database operational files to oradata
   moveFiles;
    
+  # Default for ORACLE CHARACTERSET
+  echo -n "$ORACLE_CHARACTERSET" > $ORACLE_BASE/oradata/dbconfig/$ORACLE_SID/CHARACTERSET
+
   # Execute custom provided setup scripts
   $ORACLE_BASE/$USER_SCRIPTS_FILE $ORACLE_BASE/scripts/setup
 fi;
 ```

## 検討事項

#### その1

expdp/impdpのデフォルトでのデータ出力先は /opt/oracle/admin/\$ORACLE_SID/dpdump になっているため、コンテナを破棄した時に消えてしまう。
また、別のoracleコンテナを起動した時、/opt/oracle/admin/\$ORACLE_SID/dpdump が作成されなかった。
デフォルトの出力先を /opt/oracle/oradata/$ORACLE_SID/dpdump にどうやって変更するか。

#### その2

2回目以降にOracleコンテナを起動した時、oracleユーザの環境変数にORACLE_SIDが設定されない。
以下のようにコンテナに接続した時、sqlplusを実行するためには手動で設定する必要がある。

```
$ docker exec -ti oracle12c bash
[oracle@674aa42d65a0 ~]$ echo $ORACLE_SID

[oracle@674aa42d65a0 ~]$ export ORACLE_SID=TEST
```