メンチカツには醤油でしょ!!

ITエンジニア徒然 (AWS/Java/Node.js/Google Apps Script/Spreadsheets/Docker/Jenkins/コミュニティ・勉強会レポ)

DockerでOracleデータベース11g XEを構築

以前にも似た記事を書きましたが、最近はOracleのDockerfileもちゃんとしてきた(?)と聞いており機会があったので使ってみました。

以前の記事とOracleの公式docker-images

Docker上にOracle 11g XEを立てた - メンチカツには醤油でしょ!!
Docker上のOracleで初期化処理したい - メンチカツには醤油でしょ!!
github.com

手順

公式のoracle-docker-imagesをcloneします。

> git clone git@github.com:oracle/docker-images.git oracle-docker-images
> cd oracle-docker-images/OracleDatabase/SingleInstance/dockerfiles/

シェルしか入っていないのでgit bashで実行します。

$ ./buildDockerImage.sh -v 11.2.0.2
Checking if required packages are present and valid...
md5sum: oracle-xe-11.2.0-1.0.x86_64.rpm.zip: No such file or directory
oracle-xe-11.2.0-1.0.x86_64.rpm.zip: FAILED open or read
md5sum: WARNING: 1 listed file could not be read
MD5 for required packages to build this image did not match!
Make sure to download missing files in folder 11.2.0.2.

最近のバージョンだとこんな感じ?

$ ./buildDockerImage.sh -v 11.2.0.2
Ignored MD5 sum, 'md5sum' command not available.
==========================
(略)
==========================
Building image 'oracle/database:11.2.0.2-xe' ...
Sending build context to Docker daemon  19.97kB
Step 1/10 : FROM oraclelinux:7-slim
7-slim: Pulling from library/oraclelinux
4040fe120662: Pull complete 
Digest: sha256:fc684f5bbd1e46cfa28f56a0340026bca640d6188ee79ef36ab2d58d41636131
Status: Downloaded newer image for oraclelinux:7-slim
 ---> 9870bebfb1d5
Step 2/10 : MAINTAINER Gerald Venzl >gerald.venzl@oracle.com<
 ---> Running in a71d7d09ec46
Removing intermediate container a71d7d09ec46
 ---> 8fbfe858e6a4
Step 3/10 : ENV ORACLE_BASE=/u01/app/oracle     ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe     ORACLE_SID=XE     INSTALL_FILE_1="oracle-xe-11.2.0-1.0.x86_64.rpm.zip"     INSTALL_DIR="$HOME/install"     CONFIG_RSP="xe.rsp"     RUN_FILE="runOracle.sh"     PWD_FILE="setPassword.sh"     CHECK_DB_FILE="checkDBStatus.sh"
 ---> Running in 89c3b8b9903a
Removing intermediate container 89c3b8b9903a
 ---> 9eee281e0381
Step 4/10 : ENV PATH=$ORACLE_HOME/bin:$PATH
 ---> Running in e54a5c7a3b7e
Removing intermediate container e54a5c7a3b7e
 ---> 4fc9ca630118
Step 5/10 : COPY $INSTALL_FILE_1 $CONFIG_RSP $RUN_FILE $PWD_FILE $CHECK_DB_FILE $INSTALL_DIR/
COPY failed: stat /var/lib/docker/tmp/docker-builder439774754/oracle-xe-11.2.0-1.0.x86_64.rpm.zip: no such file or directory

ERROR: Oracle Database Docker Image was NOT successfully created.
ERROR: Check the output and correct any reported problems with the docker build operation.

oracle-xe-11.2.0-1.0.x86_64.rpm.zip がないと言っていますね。
そうなんです、インストールイメージはOTNからライセンス条項に同意のうえダウンロードする必要があるんですね。下記のリンクより Oracle Database Express Edition 11g Release 2 for Linux x64 をダウンロードして、シェルが参照しているディレクトdocker-images/OracleDatabase/dockerfiles/11.2.0.2/に配置します。

Oracle Database Express Edition 11g Release 2のダウンロード

Windows環境でも、Docker上にOracleを構築するので、Linux版をダウンロードします。

$ ./buildDockerImage.sh -v 11.2.0.2
Checking if required packages are present and valid...
oracle-xe-11.2.0-1.0.x86_64.rpm.zip: OK
==========================
DOCKER info:
(かなり長いので中略)
Successfully built 78db1a697c0e
Successfully tagged oracle/database:11.2.0.2-xe
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
Oracle Database Docker Image for 'xe' version 11.2.0.2 is ready to be extended:
--> oracle/database:11.2.0.2-xe
Build completed in 117 seconds.

はい、無事に成功しました。

確認

> docker images
REPOSITORY        TAG           IMAGE ID       CREATED       SIZE
oracle/database   11.2.0.2-xe   78db1a697c0e   2 hours ago   1.13GB
oraclelinux       7-slim        9870bebfb1d5   2 weeks ago   118MB
・・・

さて実行みましょう

> docker run oracle/database:11.2.0.2-xe
Error: The container doesn't have enough memory allocated.
A database XE container needs at least 1 GB of shared memory (/dev/shm).
You currently only have 64 MB allocated to the container.

これはコンテナのメモリが1GB無いから出るエラーですので、メモリ1GBを指定してあげましょう。(--shm-size=1gを追加します)

> docker run -d --name my-oracle-database --shm-size=1g -p 1521:1521 -p 8080:8080 -e ORACLE_PWD=MyOraclePassword oracle/database:11.2.0.2-xe

これで立ち上がったと思います。
試しに接続してみるには、ホストPCのsqlplusを使ってもいいですし、コンテナ内のsqlplusを呼び出す方法もあります。

> sqlplus sys/MyOraclePassword@localhost:1521/XE as sysdba

> docker exec -it my-oracle sqlplus sys/MyOraclePassword@XE as sysdba

初期化SQLや初期データの投入

初期化スクリプト・初期化SQL・初期データなどの入ったディレクトリをボリュームマウントします。
ディレクトリ内の拡張子 .sh または .sql については自動で実行されます。実行順をより明示的にするために 01_alter_user.sql など頭に数値を付ける命名が推奨されています。

また、shやsqlファイルは、utf-8のLFで保存しておくとより安心でしょう。

> docker run -d --name my-oracle --shm-size=1g -p 1521:1521 -p 8080:8080 -e ORACLE_PWD=MyOraclePassword -e TZ="Asia/Tokyo" -v C:\my-docker\oracle\startup:/docker-entrypoint-initdb.d/startup -v C:\my-docker\oracle\oradata:/u01/app/oracle/oradata oracle/database:11.2.0.2-xe

相対パス指定だとうまくいかないことがあります。
こんなメッセージが出ますので絶対パスで指定することが推奨されています。

docker: Error response from daemon: create 【ファイルパス】: "【ファイルパス】" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.
See 'docker run --help'.

ファイルだけ指定するのもダメです

> docker run -d --name my-oracle --shm-size=1g -v C:\my-docker\oracle\startup\01_alter_user.sql:/docker-entrypoint-initdb.d/startup oracle/database:11.2.0.2-xe
0e735b3b58b3d9067560fa9fec41f67d2411c3fea7a481f2e8eafc41cbae3c27
docker: Error response from daemon: oci runtime error: container_linux.go:265: starting container process caused "process_linux.go:368: container init caused \"rootfs_linux.go:57: mounting \\\"/C/my-docker/oracle\startup/01_alter_user.sql\\\" to rootfs \\\"/var/lib/docker/aufs/mnt/d898bc13bb479bbcb411fb45c242fbfcac0bbeaeacafaa3054cb1025e87c1af8\\\" at \\\"/var/lib/docker/aufs/mnt/d898bc13bb479bbcb411fb45c242fbfcac0bbeaeacafaa3054cb1025e87c1af8/u01/app/oracle/scripts/startup\\\" caused \\\"not a directory\\\"\""
: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type.

startupディレクトリ配下には 01_alter_user.sql などのようなファイルに下記のようにsqlを記述しておけば、コンテナ始動時に実行されます。

-- ユーザー作成
CREATE USER MY_ORACLE_USER IDENTIFIED BY "MyUserPassword" DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;

また、下記のようにimpを実行するシェルを 03_imp.sh のように同じディレクトリにおいておけばdocker runするだけでDB/ユーザー/データが手に入って便利かと思います。

#!/bin/bash

imp MY_ORACLE_USER/MyUserPassword@XE file=/docker-entrypoint-initdb.d/startup/02_my_data.dmp full=y

参考

Oracle Database on Docker · docker-images/README.md at master · oracle/docker-images · GitHub

Error: The container doesn't have enough memory allocated. A database XE container needs at least 1 GB of shared memory (/dev/shm). · docker-images/FAQ.md · oracle/docker-images · GitHub