Docker is one of the latest hot technologies out there right now.
Basically it's a lightweight virtualization utility. Docker is available on Windows, Linux, and Mac OSX. These can be used to setup "hosts" which can then be used to run almost ANY Linux and Windows "guest" applications.
However, unlike a true virtual machine which setups the ENTIRE OS, docker setups up "JUST ENOUGH" of an operating system to run a particular application. It will also not grab a large portion of the host machines resources (memory, disk ,etc) for exclusive use. As a result, docker apps are much less memory intensive and much more portable.
Once you get an application up and running on Docker, it can be exported and "plugged" into another system without any setup and configuration issues.
For more information, click here.
In this tutorial, let's go through setting up a docker container running Oracle.
Please note that this is very technical article, and you will need to know a fair bit of Linux and Oracle commands.
Before we start, you will also need to the following:
This tutorial was setup on a 2009 MacBook Pro running Docker-Toolbar. However these steps should also work on Windows and Linux platforms as well.
Step 1: Create the docker machine:
After you install docker, you will need to create the docker virtual machine. In this step, you will also specify the size of the virtual disk. Be sure to create the disk with enough space to run hold $ORACLE_HOME AND your database data files. Also note that in the current release of docker, you cannot resize your virtual disk so if you find out later that your disk isn't large enough, you will need to redo the whole thing. In the example below, we are creating a docker machine called "default" with a virtual disk of 100G
In a terminal or command prompt shell, type the following:
$ docker-machine create -d virtualbox --virtualbox-disk-size "100000" default
Step 2: Start the docker machine.
$ docker-machine start default
Step 3: Start docker container for CentOS Linux and map port 1521 for the Oracle Listener (change this if you want to run listener on a different port. The first time you type this command, the system will download the image so be patient.
$ docker run -d -it -p 1521:1521 centos:latest
Step 4: Find your container ID. In our example, our ID is 69f76b125f64
Outworld2:~ jchung$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 69f76b125f64 centos:latest "/bin/bash" 3 hours ago Up 3 hours 0.0.0.0:1521->1521/tcp agitated_mayer Outworld2:~ jchung$
Step 5: Start up a bash shell.. This starts a root shell in your CentOS container. As we mentioned earlier, this is a BARE-BONES install of Linux; it's just enough to get a bash shell up with networking. Afterward, we will customize it by setting up everything we need in order to run Oracle.
$ docker exec -it 69f76b125f64 /bin/bash Outworld2:~ jchung$ docker exec -it 69f76b125f64 /bin/bash [root@69f76b125f64 /]#
Step 6: Create the dba group and oracle user. Locate the GID and UID of the dba group and oracle software owner, respectively, on your existing oracle installation and re-create this in your container. In our example, the dba is GID 500 and UID 1000.
[root@69f76b125f64 /]# groupadd -g 500 dba [root@69f76b125f64 /]# useradd -g dba -u 1000 oracle
Step 7: Install some required packages. You actually don't need all these patches, but they will make your life SO MUCH easier!
[root@69f76b125f64 /] yum install -y libaio-0.3.109-13.el7 [root@69f76b125f64 /] yum install -y openssh-clients-7.4p1-13.el7_4 [root@69f76b125f64 /] yum install -y openssh-server-7.4p1-13.el7_4 [root@69f76b125f64 /] yum install -y net-tools-2.0-0.22.20131004git.el7
Step 8: Create top level directories for the $ORACLE_HOME and Oracle Datafile directories, then change ownerships to "oracle:dba". In our example, these are /d01/oracle/product/11.2.0 and /oradata, respectively.
[root@69f76b125f64 /] mkdir -p /d01/oracle/product/11.2.0 ; chown oracle:dba /d01/oracle/product/11.2.0 [root@69f76b125f64 /] mkdir -p /oradata ; chown oracle:dba /oradata
Step 9: Create the /etc/sysctl.conf file. In the container, create the file /etc/sysctl.conf, then add the following lines. After you are done, type "sysctl -a" to load the parameters.
# System default settings live in /usr/lib/sysctl.d/00-system.conf. # To override those settings, enter new settings here, or in an /etc/sysctl.d/.conf file # # For more information, see sysctl.conf(5) and sysctl.d(5). fs.file-max = 6815744 ## ORACLE PARAMETERS kernel.shmall = 2097152 kernel.shmall = 4194304 kernel.shmmax = 2147483648 ########################### ## Changed shmmax to 16gb ## ########################### kernel.shmmax = 17179869184 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 fs.file-max = 6815744 net.ipv4.ip_local_port_range = 1024 65000 net.core.rmem_default = 4194304 net.core.wmem_default = 262144 net.core.rmem_max = 4194304 net.core.wmem_max = 1048536
Step 10: Copy the $ORACLE_HOME and ORACLE data files from your existing home to the docker container.
Change to the oracle user, then use scp (which we installed earlier), and copy the files into the container. In this example our 11g files are on a host called "raven.nyquest.com".
Please note that you need to keep the same path for the $ORACLE_HOME and oradata directories in the container as you have in the original, preexisting installation. Otherwise you run into issues with relinking and/or recreating the control files.
[root@69f76b125f64 /] su - oracle Last login: Mon Nov 6 01:40:00 UTC 2017 on pts/1 [oracle@69f76b125f64 oradata]$ cd /oradata [oracle@69f76b125f64 oradata]$ scp -r firstname.lastname@example.org:/oradata/SEED . The authenticity of host 'raven.nyquest.com (xx.xx.xx.xx)' can't be established. ECDSA key fingerprint is SHA256:NUew/8tPKeoVAEX7tXJaPTsxjxL3EJtyKD/B2w8HN9U. ECDSA key fingerprint is xxxxx. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'xx.xx.xx.xx' (ECDSA) to the list of known hosts. email@example.com's password: users01.dbf 100% 5128KB 14.8MB/s 00:00 redo02.log 100% 50MB 20.6MB/s 00:02 undotbs01.dbf 100% 820MB 20.1MB/s 00:40 [oracle@69f76b125f64 oradata]$ cd /d01/oracle/product/11.2.0 [oracle@69f76b125f64 oradata]$ scp -r firstname.lastname@example.org:/d01/oracle/product/11.2.0 .
Step 11: Exit back the root shell and then rerun the $ORACLE_HOME/root.sh script.
[oracle@69f76b125f64 ~]$ exit
[root@69f76b125f64 /]# cd /d01/oracle/product/11.2.0/dbhome_1
[root@69f76b125f64 dbhome_1]# ./root.sh
Performing root user operation for Oracle 11g
The following environment variables are set as:
Enter the full pathname of the local bin directory: [/usr/local/bin]:
Step 12: Start up oracle in the container. After you run the root.sh script. Change back to the oracle user and start the instance.
[root@69f76b125f64 dbhome_1]# su - oracle Last login: Mon Nov 6 04:34:17 UTC 2017 on pts/1 [oracle@69f76b125f64 ~]$ . oraenv ORACLE_SID = [oracle] ? SEED The Oracle base for ORACLE_HOME=/d01/oracle/product/11.2.0/dbhome_1 is /d01/oracle [oracle@69f76b125f64 ~]$ sqlplus / as sysdba SQL*Plus: Release 126.96.36.199.0 Production on Mon Nov 6 04:36:55 2017 Copyright (c) 1982, 2013, Oracle. All rights reserved. Connected to an idle instance. SQL> startup ORACLE instance started. Total System Global Area 350736384 bytes Fixed Size 2253184 bytes Variable Size 222301824 bytes Database Buffers 121634816 bytes Redo Buffers 4546560 bytes Database mounted. Database opened. SQL> exit Disconnected from Oracle Database 11g Enterprise Edition Release 188.8.131.52.0 - 64bit Production With the Partitioning, OLAP, Data Mining and Real Application Testing options [oracle@69f76b125f64 ~]$
Step 13: Start up the Oracle listener. If order to do this, we first need to determine the internal IP address of the container. Exit back to the root shell and type "ifconfig -a". Note the IP address of eth0, which in this case is 172.17.0.2. Add this address into the $ORACLE_HOME/network/admin/listener.ora file
[root@69f76b125f64 dbhome_1]# ifconfig -a eth0: flags=4163 mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0 ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 1413868 bytes 14946101292 (13.9 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 849805 bytes 53659192 (51.1 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1 (Local Loopback) RX packets 321 bytes 43944 (42.9 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 321 bytes 43944 (42.9 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@69f76b125f64 dbhome_1]# cat /d01/oracle/product/11.2.0/dbhome_1/network/admin/listener.ora LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 172.17.0.2)(PORT = 1521)) ) ) ) SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (ORACLE_HOME = /d01/oracle/product/11.2.0/dbhome_1) (SID_NAME = SEED) ) ) [root@69f76b125f64 dbhome_1]# su - oracle Last login: Mon Nov 6 04:36:51 UTC 2017 on pts/1 [oracle@69f76b125f64 ~]$ . oraenv ORACLE_SID = [oracle] ? SEED The Oracle base for ORACLE_HOME=/d01/oracle/product/11.2.0/dbhome_1 is /d01/oracle [oracle@69f76b125f64 ~]$ lsnrctl start LSNRCTL for Linux: Version 184.108.40.206.0 - Production on 06-NOV-2017 05:02:01 Copyright (c) 1991, 2013, Oracle. All rights reserved. Starting /d01/oracle/product/11.2.0/dbhome_1/bin/tnslsnr: please wait... TNSLSNR for Linux: Version 220.127.116.11.0 - Production System parameter file is /d01/oracle/product/11.2.0/dbhome_1/network/admin/listener.ora Log messages written to /d01/oracle/diag/tnslsnr/69f76b125f64/listener/alert/log.xml Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.17.0.2)(PORT=1521))) Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.17.0.2)(PORT=1521))) STATUS of the LISTENER ------------------------ Alias LISTENER Version TNSLSNR for Linux: Version 18.104.22.168.0 - Production Start Date 06-NOV-2017 05:02:01 Uptime 0 days 0 hr. 0 min. 0 sec Trace Level off Security ON: Local OS Authentication SNMP OFF Listener Parameter File /d01/oracle/product/11.2.0/dbhome_1/network/admin/listener.ora Listener Log File /d01/oracle/diag/tnslsnr/69f76b125f64/listener/alert/log.xml Listening Endpoints Summary... (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=172.17.0.2)(PORT=1521))) Services Summary... Service "SEED" has 1 instance(s). Instance "SEED", status UNKNOWN, has 1 handler(s) for this service... The command completed successfully [oracle@69f76b125f64 ~]$
Step 14: Connect to the container from the host. Once you've gotten Oracle running in the container, the final step is to connect to this database externally. But in order to do this, we will need to find the external IP address. From the host, type the following command. In this example, the container's external address is 192.168.99.100.
[oracle@69f76b125f64 ~]$ exit logout [root@69f76b125f64 dbhome_1]# exit # # At this point we are back in the host OS # Outworld2:~ jchung$ docker-machine ip default 192.168.99.100 Outworld2:~ jchung$
Remember, that when we started the container, we mapped port 1521, so externally the TNS extry should be the following:
DOCKER= (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = 192.168.99.100) (PORT = 1521) ) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = SEED) ) )
Step 15: Finally, commit your changes. Docker containers, by default, do not record changes. In order to do so, we need to commit to another image:
From the host system, type the following:
# get container ID Outworld2:~ jchung$ docker container ls CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 69f76b125f64 centos:latest "/bin/bash" 5 hours ago Up 4 hours 0.0.0.0:1521->1521/tcp agitated_mayer # commit changes to a new image centos-oracle Outworld2:~ jchung$ docker container commit 69f76b125f64 centos-oracle # you should be able to see a new image now Outworld2:~ jchung$ docker image ls REPOSITORY TAG IMAGE ID CREATED SIZE centos-oracle latest 6d359b2657fb 4 hours ago 15.1GB centos latest d123f4e55e12 2 days ago 197MB
Ok, so at this point, you've setup a docker container running Oracle. So what? Well, for starters, anytime you need a copy of this database to be running, you can simply deploy the container. No need to go thru the whole cloning process each time.
To move your image to another machine, simply save the image to a tar file.
# we can get the image id from the command above. # this will save the contents of the image in a tgz file called /tmp/centos-oracle.tgz Outworld2:~ jchung$ docker image save 6d359b2657fb -o /tmp/centos-oracle.tgz
You can then take this tar file to another server, and import it into a new image which you can then run in another container.
# in this command we will load the centos-oracle.tgz file into a new docker image # presumably you will be doing this on a different machine # once the load is done it will create a new image on your system InnerWorld:~ jchung$ docker load -i /tmp/centos-oracle.tgz
Setting up a database on a new server becomes trivial; instead of downloading Oracle, running the installer, and doing all that configuration (you DBA's know what I mean, /etc/sysctl.conf, tnsnames.ora, root,sh, listener.ora, etc), you can just deploy the container and have a working database environment running in minutes!
Finally, one thing that Banner® Users always want is a clean training environment. Well with docker setting up a clean training PPRD, TRNG, DEVL database also becomes trivial. Each time you need this, simply deploy the container. Also note that changes within the container are NOT saved when the container is restarted, so each time you need to refresh, simply restart everything.
For people that want to go further, you can also setup Docker environments for other Banner® components such as Weblogic, Tomcat, Oracle Forms.