macOSでOracle Database使いたい

# ことの発端
ふと思いました。
SQL文だけでなくキチンとデータベース全般の知識つけるべきだと。
クリスマスの夜のことでした。

# 資格がてら
漠然とした目的の次は到達可能な目先の目標が必要です。
知識の定着がどれくらいか測るにはやっぱり資格が便利ですよね。
というわけで、資格試験に使われているデータベースを勉強してその資格を取ることにしました。
探してみるとMySQL、PostgreSQL、SQL Server、Oracle Databaseなど色々あります。
中でも教材と公式ドキュメントが豊富で手に入れやすいのがOracle Databaseだったので、
安直に[Oracle Master Bronze](https://education.oracle.com/ja/oracle-master-bronze-oracle-database-12c/trackp_284)を取ることにしました。

エンジニアはとにかくハンズオンだろ!
ということで冬のボーナスで買ったiMacがようやく活躍する日が来たようです。
早速[Oracleのサイト](https://www.oracle.com/technetwork/jp/database/enterprise-edition/downloads/index.html)でOracle Databaseをインストールしようとしたところ...
<img width="1053" alt="Screen Shot 2018-12-27 at 0.28.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/122955db-647b-9b7c-3721-2c1277ca8ed9.png">
**macOSがない!**

# Dockerさまさま
Oracle DatabaseってmacOSでリリースしてないんですね。
開発環境の構築で挫折することは良くあることですが、今回はあまりに無知でした。
インストールできないんならMySQLかPostgreSQLにスイッチしようかなーとも思いましたが、
22万もしたiMacでメジャーなデータベースがインストールできないなんてこと信じたくありません。
同じ問題にぶち当たった先輩方がいないか探したところ...

- [OS X 10.11で，Oracle Database 12cのDocker Imageを使ってみた](https://qiita.com/lethe2211/items/0bb493fa93a0088cfac9)
- [Oracle on docker for Mac](https://qiita.com/daiki_hirano/items/e331a0017250c75e7a07)

いました。
どうやらDockerなる技術を使えばmacOSでもOracle Databaseが使えそう。
後述の手順はほぼ先輩方の教えのままです。
あと[公式のドキュメント](https://github.com/oracle/docker-images/blob/master/OracleDatabase/SingleInstance/README.md)にもお世話になりました。
Dockerについて色々知る必要はあるけど、ここでは目先の恩恵だけ受けることにして、
具体的に彼が何者なのかは割愛することにします。
とりあえず、Dockerはコンテナと呼ばれる環境を管理するための技術らしい。
そしてコンテナの中でならOracle Databaseが使えるらしい。

早速、[公式サイト](https://www.docker.com/get-started)からmacOS用のDockerをインストールしてみると...
<img width="696" alt="Screen Shot 2018-12-27 at 0.30.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/e10acb91-9b2a-0de4-8399-48b50b2ede33.png">
デスクトップにクジラが現れました。
とりあえず簡単にインストールできます。

# イメージ入手
続いて、コンテナで使うOracle Databaseのイメージ(バイナリ)とそのビルドスクリプトを入手せよとのこと。
まずは[このサイト](https://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html)からバイナリ入手。
<img width="1054" alt="Screen Shot 2018-12-27 at 0.54.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/9b1ebf0e-358f-dd77-ac5e-c51718144886.png">
またmacOSがないけどコンテナを使うということで今回はLinux x86-64をダウンロードすれば良いらしい。
ちなみにダウンロードしたzipの解凍はこのあと入手するビルドスリプトが行うので、
safariでダウンロードする場合はPreferenceで「Open "safe" files after downloading」のチェックをOFFにします。
<img width="886" alt="Screen Shot 2018-12-27 at 1.21.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/1dd9a25b-d15a-c6bc-93dc-49b16074b307.png">
続いてgithubからビルドスクリプトをクローンして、

```
$ mkdir ~/Git/oracle
$ cd ~/Git/oracle
$ git clone https://github.com/oracle/docker-images.git
```

終わったら先ほどダウンロードしたバイナリをクローンしたビルドスクリプトの適所に配置します。
バージョン名がディレクトリ名と対応している模様(例はダウンロードしたバージョン12.2.0.1のバイナリをディレクトリ12.2.0.1にコピってる)。

```
$ cp ~/Downloads/linuxx64_12201_database.zip \
     ~/Git/oracle/docker-images/OracleDatabase/SingleInstance/dockerfiles/12.2.0.1
```

最後にビルドスクリプト「buildDockerImage.sh」を実行。
いくつかオプションがあります。
***-v***: バイナリを配置したディレクトリ名(データベースのバージョン)
***-e***: Enterprise Editionである意(他にもExpress EditionとStandard Edition 2がある)
***-i***: ignores the MD5 checksumsでよく分からないけど必要らしい

```
$ cd ~/Git/oracle/docker-images/OracleDatabase/SingleInstance/dockerfiles
$ ./buildDockerImage.sh -v 12.2.0.1 -e -i
```

実行から完了まで10分くらい掛かりました。
成功していればdockerコマンドでイメージの一覧を確認できるそうなので試してると...

```
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
oracle/database     12.2.0.1-ee         45defa0b826c        29 hours ago        5.97GB
oraclelinux         7-slim              b19454a5f17a        6 weeks ago         117MB
```

それっぽいイメージができたようです。

# コンテナ起動
イメージが手に入ったら、いよいよdockerコマンドでコンテナを起動します。
ここでもいくつかのオプションがある模様なので、とりあえず雛形のコマンドから。
ドン!

```
$ docker run --name <container name> \
-p <host port>:1521 -p <host port>:5500 \
-e ORACLE_SID=<your SID> \
-e ORACLE_PDB=<your PDB name> \
-e ORACLE_PWD=<your database passwords> \
-e ORACLE_CHARACTERSET=<your character set> \
-v <host mount point>:/opt/oracle/oradata \
REPOSITORY:TAG
```

Oracle Databaseの用語がちょいちょい出てきてるので自分なりに整理してみると...

***--name***: 実行するコンテナの名前。ここで名付ける。
***-p***: ポート番号の指定。1521がリスナー(ユーザのリクエスト受け付けプロセス)用、5500がEM Express(データベース管理ツール)用っぽい
***-e Oracle_SID***: システム識別子(インスタンス名)。デフォルトORCLCDB
***-e Oracle_PDB***: プラガブル・データベースを使う場合に必要な識別子っぽい。デフォルトORCLPDB1
***-e ORACLE_PWD***: 規定ユーザ(SYS、SYSTEM、PDB_ADMIN)のパスワード。指定しない場合はコマンド実行後に自動生成
***-e ORACLE_CHARACTERSET***: データベース内の文字コードかな。デフォルトAL32UTF8
***-v***: コンテナのマウントポジション。稼働したコンテナはホストにマウントするようです。
***REPOSITORY:TAG***: イメージのレポジトリとタグの組み合わせ

デフォルトありのオプションを割愛して実行すると...

```
$ docker run --name docker_oracle \
-p 1521:1521 -p 5500:5500 \
-v /Users/myname/Docker/oradata:/opt/oracle/oradata \
oracle/database:12.2.0.1-ee
```

```
ORACLE PASSWORD FOR SYS, SYSTEM AND PDBADMIN: AZ91SsT3SnI=1

LSNRCTL for Linux: Version 12.2.0.1.0 - Production on 25-DEC-2018 14:37:10

Copyright (c) 1991, 2016, Oracle.  All rights reserved.

Starting /opt/oracle/product/12.2.0.1/dbhome_1/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 12.2.0.1.0 - Production
System parameter file is /opt/oracle/product/12.2.0.1/dbhome_1/network/admin/listener.ora
Log messages written to /opt/oracle/diag/tnslsnr/3299af179225/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 12.2.0.1.0 - Production
Start Date                25-DEC-2018 14:37:11
Uptime                    0 days 0 hr. 0 min. 0 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Listener Parameter File   /opt/oracle/product/12.2.0.1/dbhome_1/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/3299af179225/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
The listener supports no services
The command completed successfully
[WARNING] [DBT-10102] The listener configuration is not selected for the database. EM DB Express URL will not be accessible.
   CAUSE: The database should be registered with a listener in order to access the EM DB Express URL.
   ACTION: Select a listener to be registered or created with the database.
Copying database files
1% complete
13% complete
25% complete
Creating and starting Oracle instance
26% complete
30% complete
31% complete
35% complete
38% complete
39% complete
41% complete
Completing Database Creation
42% complete
43% complete
44% complete
46% complete
47% complete
50% complete
Creating Pluggable Databases
55% complete
75% complete
Executing Post Configuration Actions
100% complete
Look at the log file "/opt/oracle/cfgtoollogs/dbca/ORCLCDB/ORCLCDB.log" for further details.

SQL*Plus: Release 12.2.0.1.0 Production on Tue Dec 25 14:42:48 2018

Copyright (c) 1982, 2016, Oracle.  All rights reserved.


Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL>
System altered.

SQL>
Pluggable database altered.

SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
The Oracle base remains unchanged with value /opt/oracle
#########################
DATABASE IS READY TO USE!
#########################
The following output is now a tail of the alert.log:
Completed: alter pluggable database ORCLPDB1 open
2018-12-25T14:42:46.815487+00:00
ORCLPDB1(3):CREATE SMALLFILE TABLESPACE "USERS" LOGGING  DATAFILE  '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT  1280K MAXSIZE UNLIMITED  EXTENT MANAGEMENT LOCAL  SEGMENT SPACE MANAGEMENT  AUTO
ORCLPDB1(3):Completed: CREATE SMALLFILE TABLESPACE "USERS" LOGGING  DATAFILE  '/opt/oracle/oradata/ORCLCDB/ORCLPDB1/users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT  1280K MAXSIZE UNLIMITED  EXTENT MANAGEMENT LOCAL  SEGMENT SPACE MANAGEMENT  AUTO
ORCLPDB1(3):ALTER DATABASE DEFAULT TABLESPACE "USERS"
ORCLPDB1(3):Completed: ALTER DATABASE DEFAULT TABLESPACE "USERS"
2018-12-25T14:42:48.053830+00:00
ALTER SYSTEM SET control_files='/opt/oracle/oradata/ORCLCDB/control01.ctl' SCOPE=SPFILE;
   ALTER PLUGGABLE DATABASE ORCLPDB1 SAVE STATE
Completed:    ALTER PLUGGABLE DATABASE ORCLPDB1 SAVE STATE
```

10分ほど待つと「DATABASE IS READY TO USE」が出力されて待機状態になりました。
dockerコマンドで起動中のコンテナが確認できるので見てみると...

```
$ docker ps -l --no-trunc
CONTAINER ID
    3299af1792259b6b6f27f2f424d54aa35423fdca0513fdd15b17ac145f0dac92
IMAGE
    oracle/database:12.2.0.1-ee
COMMAND
    "/bin/sh -c 'exec $ORACLE_BASE/$RUN_FILE'"
CREATED
    37 hours ago
STATUS
    Up 13 hours (healthy)
PORTS
    0.0.0.0:1521->1521/tcp, 0.0.0.0:5500->5500/tcp
NAMES
    docker_oracle
```

起動したっぽいです。

# コンテナにログイン
先ほどコンテナを起動した際に***-v***オプションでマウントポジションを指定していました。
ホスト側のマウントポジション(***-v***の左辺)を確認してみます。

```
$ ls /Users/myname/Docker/oradata
ORCLCDB  dbconfig
```

コンテナ側はどうなっているんでしょうか?
コンテナにログインしてみます。

```
$ docker exec -ti docker_oracle /bin/bash
[oracle@f92ebd7a1991 ~]$
```

新しいプロンプトが出てきました。
ログインできたようなので現在地とルートを確認します。

```
[oracle@f92ebd7a1991 ~]$ pwd
/home/oracle
[oracle@f92ebd7a1991 ~]$ ls /
bin  boot  dev  docker-entrypoint-initdb.d  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
```

どうやらLinuxファイルシステムの中にいるようです。
続いて***-v***オプションの右辺を確認してみます。

```
[oracle@f92ebd7a1991 ~]$ ls /opt/oracle/oradata
ORCLCDB  dbconfig
```

ありました。
というわけで、コンテナを稼動するとホスト(macOS)にLinuxのファイルシステムがマウントされて、
その中でイメージ(Oracle Database)が動くようです。
この辺を意識できればホスト側のファイルをコンテナに共有することもできますね。
でもきっとコンテナを停止か削除すれば、コンテナ内のファイルは削除されてホストがこれを復元することは出来なさそう...。
大事なファイルはホスト側で管理した方が良さそうですね。

# SQL*Plus起動
コンテナ起動時のログを良くみるとイメージの中にSQL*Plusが入っていたようです。
Oracle環境変数スクリプトでインスタンス名を設定して...

```
[oracle@f92ebd7a1991 ~]$ . oraenv
ORACLE_SID = [ORCLCDB] ? ORCLCDB
```

SQL*Plusを起動してみると...

```
[oracle@f92ebd7a1991 ~]$ sqlplus /nolog

SQL*Plus: Release 12.2.0.1.0 Production on Sat Dec 29 12:20:59 2018

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

SQL>
```

起動しました!
コンテナ起動時のログに出力されたパスワードでインスタンスに接続します。

```
SQL> connect sys/AZ91SsT3SnI=1 as sysdba
Connected.
```

やりました!

# SQL Developer起動
CUI(SQL*Plus)が動かせたので次はGUI(SQL Developer)を動かします。
イメージに同封されていたCUIに対して、GUIは[公式サイト](https://www.oracle.com/technetwork/jp/developer-tools/sql-developer/downloads/index.html)からインストールする必要がありました。
(確かJava8が無いとダメだったような...)
<img width="1265" alt="Screen Shot 2018-12-29 at 21.35.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/0eb948c2-b53e-f0fe-502a-11f2604dbc83.png">

起動したら、左サイドバーのプラスマークを押下。

<img width="951" alt="Screen Shot 2018-12-29 at 21.39.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/93c8d4dc-9dd9-c9e1-144d-165d835009c6.png">

正しい接続情報を入力して「Test」ボタン押下すると、左下に「Status:Success」が表示されます。
<img width="892" alt="Screen Shot 2018-12-29 at 21.53.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/9e7f962d-1790-4dbd-aca4-2bc99e810078.png">

# EM Express起動
EM ExpressはWebブラウザによるデータベース管理ツールだそうです。
Adobe Flashを使っているのでSafariでは使えません。
Google Chromeで[ログイン画面](https://localhost:5500/em/)を表示します。

<img width="983" alt="Screen Shot 2018-12-29 at 22.03.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/1cd2af57-2783-3e82-ce1c-16ce9c9c6f7c.png">

ユーザ名とパスワードを入力すると...

<img width="1084" alt="Screen Shot 2018-12-29 at 22.05.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/326581/511f190d-6300-0303-2416-8b5051a5e4b3.png">

ログインできました。
左上にoraenvで設定したインスタンス名が表示されているのでちゃんとモニターできてるっぽいです。
これで資格勉強のための環境が一通りセットアップできたのではないでしょうか。

# おしまい
というわけで、macOSでDockerを使うことでOracle Databaseをセットアップすることができました。
はじめてOracle DatabaseとDockerを触ったので穴だらけセットアップだったかもです。
参考にしている白本によると正規の手順ではOracle Universal Installerという製品を使用するらしく、
今回はDockerイメージのインストール手順がその代替となりました。
データベース本体はmacOS非対応なのに何故かGUIは対応してたり、
EM ExpressはAdobe Flashがないと使えなかったりと、
Oracleどういうことだってばよな場面も結構ありましたが、
とりあえずBronze取るまではOracle Databaseを使ってみようかと思います。
目指せ2019年夏までの取得!