Docker, Oracle 12c and Persistent Storage


If you have read my previous posts on Docker you may have already installed Docker and have an Oracle 12c database running in a Docker container, if not you may want to read my first post on Docker – Running Oracle 12.2.01 on Docker

However, since I wrote the above post Oracle have published Docker images for many of their products, these can be found at the Docker Store. The Oracle images on the Docker Store are not just a great resource and help accelerate adoption, but are also certified and supported by Oracle.

Before continuing with this post you need to check-out my posts on using the new Oracle 12c Docker images and the Pure Storage Docker plugin as this post can be considered the ‘Return of the Jedi’  in the series.

Oracle 12c with Persistent Storage

In this post I will create a Docker container running an Oracle 12c database called PSTG using 4 mount points /u01, /u02, /u03 & /u04 mounted from a Pure Storage FlashArray.

Database environment Layout

/u01 – OraInventory and Oracle 12c product directories
/u02 – Oracle Datafile
/u03 – Fast Recovery Area
/u04 – RedoLog files.

The 4 mount points will all be using persistent All Flash Storage providing low latency performance, space efficient crash consistent snapshots and requiring no local storage.

First, confirm that you have installed the Oracle 12c image using the the following:

$ docker images list

docker_imagesYou should be able see the store/oracle/database-enterprise Docker Image, if missing you need to read my previous post.

Ok, copy the db_env.dat file created in the previous post to a new environment file $ORACLE_SID_env.dat and update database name and password e.g.

## Copyright(c) Oracle Corporation 1998,2016. All rights reserved.##
##                                                                ##
##                   Docker OL7 db12c dat file                    ##
##                                                                ##
## Specify the basic DB parameters
## db sid (name)
## default : ORCL
## cannot be longer than 8 characters
## db passwd
## default : Oracle
## db domain
## default : localdomain
## db bundle
## default : basic
## valid : basic / high / extreme 
## (high and extreme are only available for enterprise edition)
## end

We will now create the 4 volumes using the docker volume create command and Pure Storage Docker plug-in providing name, size and label.

 docker volume create --driver=pure --opt size=20GB --name=PSTG-u01 --label=product
 docker volume create --driver=pure --opt size=100GB --name=PSTG-u02 --label=oradata
 docker volume create --driver=pure --opt size=200GB --name=PSTG-u03 --label=fast_recovery_area
 docker volume create --driver=pure --opt size=10GB --name=PSTG-u04 --label=redo

We can use the docker volume ls command with a filter to list the 4 database volumes we are interested in using the following syntax

$ docker volume ls -f name=environment


The Pure Storage Docker Plugin also supports docker volume inspect, from here we can see the labels which we defined earlier, great way to see where and what the mount is being used for.

$ docker volume inspect volume name


Now that we have installed the Oracle 12c Docker image and created the 4 volumes we are ready to create our Oracle 12c container using the docker run command with -v to present our newly volumes to our container.

docker run -d –env-file ./PSTG_env.dat -p 1527:1521 -p 5507:5500 -it –name PSTG -v PSTG-u01:/u01 -v PSTG-u02:/u02 -v PSTG-u03:/u03 -v PSTG-u04:/u04 –shm-size=”8g” store/oracle/database-enterprise:

Progress can be monitored using the docker logs command.

docker logs -f PSTG

Once the container has started we can now connect to it and check out our Oracle 12c environment using the docker exec command and container name

docker exec -it PSTG /bin/bash

From within our Oracle 12c ‘PSTG’ container we can see our Pure Storage volumes (/u01, /u02, /u03 & /u04) and the sizes we specified.


Now we are in our Docker container we can use SQLPlus to see data file locations, instance name, docker assigned hostname etc…




Docker Volume plugin for Pure Storage

You may have noticed that you can now download a Docker Volume Plugin for Pure Storage from the Docker Store. The Pure Storage Docker Volume plugin provides seamless integration with Docker containers, enabling persistent storage which is a must for many enterprise and database applications

Pure Docker Plug-in Installation

If you have not already installed docker you need to do this first, see my previous Blog Docker installation on Linux for details.

Ok, lest install the Pure Docker plug-in.

# docker plugin install store/purestorage/docker-plugin:2.0 –alias pure –grant-all-permissions
2.0: Pulling from store/purestorage/docker-plugin
313f5ed5ee16: Download complete
Digest: sha256:607837553036107dfccf14870e500fa3b3bdab343f111d0ac58af1b8351d7f31
Status: Downloaded newer image for store/purestorage/docker-plugin:2.0
Installed plugin store/purestorage/docker-plugin:2.0

Docker Plugin Management

We can manage Docker plugins with the docker plugin command e.g.

# docker plugin
Usage: docker plugin COMMAND
Manage plugins
create         Create a plugin from a rootfs and configuration. Plugin data directory must contain config.json and rootfs directory.
disable       Disable a plugin
enable        Enable a plugin
inspect       Display detailed information on one or more plugins
install         Install a plugin
ls                  List plugins
push            Push a plugin to a registry
rm               Remove one or more plugins
set               Change settings for a plugin
upgrade     Upgrade an existing plugin

Run ‘docker plugin COMMAND –help’ for more information on a command.

Let’s check out the status of our Pure Docker plugin with

# docker plugin ls
ID                          NAME                DESCRIPTION                                  ENABLED
0b4ab7efeb3f      pure:latest        Pure Storage plugin for Docker   true

Once installed the first thing you must do is to let the Volume plugin know about your Pure FlashArray, update /etc/pure-docker-plugin/pure.json to use your FlashArray’s management (not iSCSI) IP address and API Token.

Example pure.json file for FlashArray

Substitute values for the MgmtEndPoint and APIToken fields with values specific to your FlashArray.


Create a Volume

You can create a Pure Storage FlashArray volume from your Linux server using the docker volume create command.

# docker volume create –driver=pure -o size=100GB –name=ron101 –label=ron

You should now be able to see the newly created volume within the Pure Storage FlashArray.docke_FA

List a Volume

You can also use the docker volume ls command and filters to show available volumes.

# docker volume ls -f name=ron
pure                ron100
pure                ron101

Inspect a Volume

You can use the docker volume inspect command to get a bit more info and to also see where it’s being used.

[root@z-oracle pure-docker-plugin]#  docker volume inspect ron101
        "Driver": "pure:latest",
        "Labels": {
            "ron": ""
        "Mountpoint": "/var/lib/docker/plugins/55d3765fafd49e915dc95f791c6f06a0d4207e50c453c4b175a6f18e9f23ed12/rootfs",
        "Name": "ron101",
        "Options": {
            "size": "100GB"
        "Scope": "global"

Delete a Volume

The Pure Storage Volume plugin also supports volume delete.

# docker volume rm ron101
# docker volume ls -f name=ron

In this Blog I have shared how we can create, inspect and delete Docker Volumes using the Pure Storage Docker Volume plug-in, in my next post I will share you you can use these volumes for persistent database storage.

Check-out the Pure Storage Developer Community for more examples.

Automate to avoid database cloning disasters.

“Accidentally destroyed production database on first day of a job”

Wow, that headline grabbed my attention.

Earlier this week you may have seen an article reported by The Register about a post in  reddit from a junior software developer going by the name of  “cscareerthrowaway567”, who on his/her first day destroyed a Production database and lost their job.

I was basically given a document detailing how to setup my local development environment. Which involves run a small script to create my own personal DB instance from some test data. After running the command i was supposed to copy the database url/password/username outputted by the command and configure my dev environment to point to that database. Unfortunately instead of copying the values outputted by the tool, i instead for whatever reason used the values the document had.

Unfortunately apparently those values were actually for the production database (why they are documented in the dev setup guide i have no idea). Then from my understanding that the tests add fake data, and clear existing data between test runs which basically cleared all the data from the production database. Honestly i had no idea what i did and it wasn’t about 30 or so minutes after did someone actually figure out/realize what i did.

Now, we can not be sure if the story by “cscareerthrowaway567” is true or not but it does provide an great example of the potential dangers of manual database cloning.

The story raises many issues around process, security, change management, training and not least why someone thought it was a good idea to include Production account details in a database cloning document ?

However, this could have easily been avoided through the use of Automation or a CDM (Copy Data Management) tools e.g. Catalogic, Actifio, Delphix etc..

Many modern All-Flash Arrays (AFA) provide powerful REST API’s which can be called from various programming and scripting languages e.g. Python, Java, Perl, PowerShell etc… to create custom solutions.

AFA Storage API’s can also be consumed by DevOPS Automation and Provisioning software e.g. Ansible, Chef, Puppet etc.. to provide full-stack or end-to-end Automation of Database Cloning, improving security and also removing the chance of human error.

Check out the Pure Storage Developer Community area for code examples.

Oracle 12c on Docker

Getting the Image

Great news, during DockerCon 2017 Oracle announced support for Oracle 12.1 Database Docker images. Press release: Oracle Brings Oracle’s Flagship Databases and Developer Tools to the Docker Store

Previously to run an Oracle Database in a Docker container you needed to create your own Docker image, I actually Blogged on this earlier in the year, if you interested you can read about it here.

However, you can now obtain an official Oracle 12.1 Database Docker images from the Docker Store

Before you can ‘pull’ the new Docker image you will need to login to the Docker Store and click on the ‘Get Content’ button and then complete the form, providing your name, company, phone number and then accepting the Oracle license agreement.


The ‘Setup’ button provides details on how ‘pull’ the image and also how to set-up the your Oracle database within Docker.

docker pull store/oracle/database-enterprise:

The Docker image includes all the required Oracle files so is pretty large coming in at ~4.87GB, so it may take a while to download.

Running the Container

The environment file allows for customisation of the Database name, password, domain and feature bundle.

The command for creating a database container is:

$ docker run -d –env-file -p :1521 -p :5500 -it –name –shm-size=”4g”

<path_to_env_file> is the path to the environment file you created using above example.
<listener_port> is the port on host machine to map the container’s 1521 port (listener port).
<http_port> is the port on host machine to map the container’s 5500 port (http service port).
<container_name> is the container name you want to create.
<shared_memory_size> is the memory size for the container to run. The minimum requirement is 4GB (–shm-size=”4g”).
<image_name> is the image that you use to create a container.

In this example our environment file is called db_env.dat and our container is going to be called dockerDB

docker run -d –env-file ./db_env.dat -p 1527:1521 -p 5507:5500 -it –name dockerDB –shm-size=”8g” store/oracle/database-enterprise:

We should now be able to see our new Oracle 12.1 image and running container using:

docker image ls
docker container ls


From my MacBook Pro we check the progress of the build using the Docker logs option e.g.

docker logs -f dockerDB


We can also connect to the running container using the Docker exec command e.g.

docker exec -it dockerDB /bin/bash

From here we can see the Oracle Docker is using Oracle Linux 7.3 and the database is called ‘OraDoc’ as per our environment file.

As you can see from the above we are connected as root, if you want to use the oracle account then type ‘su – oracle’ and from there try out sqlplus inside your container.


Oracle 12c on an MBP Done!

Running Oracle on Docker

Docker Installation

Before you can consider creating an Oracle Database docker container you need to install Docker. If you yet to install Docker you can visit one of my previous posts Docker installation on Oracle Linux 7.2  to get started.

Oracle on Docker

Since last year Oracle have provided build files to assist in the creation of Oracle Database Docker images. Gerald Venzl produced an excellent Blog post Creating an Oracle Database Docker Image for Oracle, however now that Oracle is available for on-premises I thought I would try and and create an Oracle container.

Please note, before you start deploying Oracle on Docker it’s probably advisable to check the latest Oracle support position for running Oracle on Docker (see below)
Oracle Support Document 2216342.1 (Oracle Support for Database Running on Docker)

Applies To:
Oracle Database – Enterprise Edition – Version and later
Oracle Database – Standard Edition – Version and later
Linux OS – Version Oracle Linux 7.3 to Oracle Linux 7.3 [Release OL7U3]
Linux x86-64
Oracle will support customers running Oracle Database (single instance) in Docker containers. Oracle will only provide support when running the database in Docker containers running on Oracle Linux and Red Hat RHEL.  Supported versions of these Linux distributions are

  • Oracle Linux 7
  • Red Hat Enterprise Linux 7 (RHEL)

Oracle does not support Oracle Database running in a Real Application Clusters (RAC) configuration in Docker containers.

If your satisfied with your support position you will need the following:

The Oracle Database zip file, which you can get from Oracle Technology Network and the Oracle Docker build files which you can download or clone from GitHub

For this Blog I am using my Vagrant managed Oracle Linux 7.3 Server

[vagrant@localhost ~]$ uname -r

[vagrant@localhost ~]$ cat /etc/oracle-release
Oracle Linux Server release 7.3

[vagrant@localhost ~]$ docker –version
Docker version 1.12.6, build ac13b2b


If you plan to run the docker container out of an Oracle OS account you can use the oracle-database-server-12cR2-preinstall package to create your OS accounts and groups if missing.

I then edited the /etc/sysconfig/docker-storage file adding the following entry to increase the storage space available to my container.

DOCKER_STORAGE_OPTIONS=–storage-opt dm.basesize=20G

As my Vagrant VirtualBox OL73 server had a small root file system I added another 40G disk via VirtualBox for my Docker image via the loopback storage mounting at /var/lib/docker as this is where Docker will create the container file systems.

service docker stop
fdisk /dev/sdb
mkfs.xfs /dev/sdb1
cd /var/lib
rm -Rf docker
mkdir docker
mount /dev/sdb1 /var/lib/docker
service docker start

To allow to Oracle to sudo and run docker commands I then added oracle to the /etc/sudoers file.


You can now switch user to oracle (su – oracle) and download the Oracle build files and database zip file if you have not already obtained them

[oracle@localhost ~]$ wget
[oracle@localhost ~]$ unzip
[oracle@localhost ~]$ cd docker-images-master/OracleDatabase/dockerfiles/

Now copy from its download location to the directory.

Oracle Docker image creation

Usage: -v [version] [-e | -s | -x] [-i]
Builds a Docker Image for Oracle Database.

-v: version to build
Choose one of:
-e: creates image based on ‘Enterprise Edition’
-s: creates image based on ‘Standard Edition 2’
-x: creates image based on ‘Express Edition’
-i: ignores the MD5 checksums

* select one edition only: -e, -s, or -x

[oracle@localhost]$ cd ..
[oracle@localhost dockerfiles]$ sudo ./ -v -e
Checking if required packages are present and valid… OK
DOCKER info:
Containers: 1
Running: 0
Paused: 0
Stopped: 1
Images: 6
Server Version: 1.12.6
Storage Driver: devicemapper
Pool Name: docker-8:17-134299776-pool
Pool Blocksize: 65.54 kB
Base Device Size: 21.47 GB
Backing Filesystem: xfs
Data file: /dev/loop0
Metadata file: /dev/loop1
Data Space Used: 3.62 GB
Data Space Total: 107.4 GB
Data Space Available: 35.81 GB
Metadata Space Used: 2.535 MB
Metadata Space Total: 2.147 GB
Metadata Space Available: 2.145 GB
Thin Pool Minimum Free Space: 10.74 GB
Udev Sync Supported: true
Deferred Removal Enabled: false
Deferred Deletion Enabled: false
Deferred Deleted Device Count: 0
Data loop file: /var/lib/docker/devicemapper/devicemapper/data
WARNING: Usage of loopback devices is strongly discouraged for production use. Use `–storage-opt dm.thinpooldev` to specify a custom block storage device.
Metadata loop file: /var/lib/docker/devicemapper/devicemapper/metadata
Library Version: 1.02.135-RHEL7 (2016-09-28)
Logging Driver: json-file

Building image ‘oracle/database:’ …
Sending build context to Docker daemon 3.454 GB
Step 1 : FROM oraclelinux:7-slim
7-slim: Pulling from library/oraclelinux
33a3a5e469a8: Pull complete
Digest: sha256:f3a78afd456061bb897b9f2b54b568dec3973efccf2b086d602fabb94069fb6d
Status: Downloaded newer image for oraclelinux:7-slim
—> f005b5220b05
Step 2 : MAINTAINER Gerald Venzl <>
—> Running in 64041116d1b3
—> 7cf919c3ab70
Removing intermediate container 64041116d1b3
—> Running in 25142567c49e
—> 35ff7ea319fa
Removing intermediate container 25142567c49e
—> Running in 2b0c17414781
—> 1eb28b0769f2
Removing intermediate container 2b0c17414781
—> aff425e9295c
Removing intermediate container 8f310fa167cf
—> 30a46bcfb092
Removing intermediate container 392cda966aaf
—> Running in ce2d69a6fc72
Loaded plugins: ovl
Resolving Dependencies

Loaded plugins: ovl
Cleaning repos: ol7_UEKR4 ol7_latest
Cleaning up everything
—> 4cc34d72a3be
Removing intermediate container ce2d69a6fc72
Step 8 : USER oracle
—> Running in 012bc240b15c
—> 90c7fd83f732
Removing intermediate container 012bc240b15c
—> Running in a669bd56a701
creating: database/

inflating: database/runInstaller
Starting Oracle Universal Installer…

Checking Temp space: must be greater than 500 MB. Actual 16493 MB Passed
Checking swap space: must be greater than 150 MB. Actual 4095 MB Passed
Preparing to launch Oracle Universal Installer from /tmp/OraInstall2017-03-27_03-55-03PM. Please wait …[WARNING] [INS-32055] The Central Inventory is located in the Oracle base.
ACTION: Oracle recommends placing this Central Inventory in a location outside the Oracle base directory.
You can find the log of this install session at:
The installation of Oracle Database 12c was successful.
Please check ‘/opt/oracle/oraInventory/logs/silentInstall2017-03-27_03-55-03PM.log’ for more details.

As a root user, execute the following script(s):
1. /opt/oracle/oraInventory/
2. /opt/oracle/product/

Successfully Setup Software.

This is perl 5, version 22, subversion 0 (v5.22.0) built for x86_64-linux-thread-multi

Copyright 1987-2015, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using “man perl” or “perldoc perl”. If you have access to the
Internet, point your browser at, the Perl Home Page.

—> 0902cfc62543
Removing intermediate container a669bd56a701
Step 10 : USER root
—> Running in 29796c72580a
—> 09b24f80b740
Removing intermediate container 29796c72580a
Step 11 : RUN $ORACLE_BASE/oraInventory/ && $ORACLE_HOME/ && rm -rf $INSTALL_DIR
—> Running in b4e812ee2e1b
Changing permissions of /opt/oracle/oraInventory.
Adding read,write permissions for group.
Removing read,write,execute permissions for world.

Changing groupname of /opt/oracle/oraInventory to dba.
The execution of the script is complete.
Check /opt/oracle/product/ for the output of root script
—> afc8f9ef0a10
Removing intermediate container b4e812ee2e1b
Step 12 : USER oracle
—> Running in 6244a9a22dec
—> 8a41f54d71ae
Removing intermediate container 6244a9a22dec
Step 13 : WORKDIR /home/oracle
—> Running in c52fa2e4164f
—> b9daa3897d15
Removing intermediate container c52fa2e4164f
Step 14 : VOLUME $ORACLE_BASE/oradata
—> Running in 847ca5208e7f
—> 2f897f1adbda
Removing intermediate container 847ca5208e7f
Step 15 : EXPOSE 1521 5500
—> Running in d73768c39961
—> 9fd63d1fd413
Removing intermediate container d73768c39961
—> Running in 34d6f31bb5b7
—> efa2e9d7cc87
Removing intermediate container 34d6f31bb5b7
Successfully built efa2e9d7cc87

Oracle Database Docker Image for ‘ee’ version is ready to be extended:

–> oracle/database:

Build completed in 840 seconds.

Starting Oracle Docker instance

We are now ready to start the Oracle databases inside a Docker container. To do this we use the docker run command passing the required parameters.

-p Port
–name Docker container name, note this is not the database name.

[oracle@localhost dockerfiles]$ sudo docker run -p 1521:1521 –name pure oracle/database:

LSNRCTL for Linux: Version – Production on 27-MAR-2017 16:10:45

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

Starting /opt/oracle/product/ please wait…

TNSLSNR for Linux: Version – Production
System parameter file is /opt/oracle/product/
Log messages written to /opt/oracle/diag/tnslsnr/f4c614207382/listener/alert/log.xml
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version – Production
Start Date                27-MAR-2017 16:10:45
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/
Listener Log File         /opt/oracle/diag/tnslsnr/f4c614207382/listener/alert/log.xml
Listening Endpoints Summary…
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 Production on Mon Mar 27 16:17:18 2017

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

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

System altered.

Pluggable database altered.

SQL> Disconnected from Oracle Database 12c Enterprise Edition Release – 64bit Production
Completed: alter pluggable database ORCLPDB1 open
ALTER SYSTEM SET control_files=’/opt/oracle/oradata/ORCLCDB/control01.ctl’ SCOPE=SPFILE;
ORCLPDB1(3):Resize operation completed for file# 10, old size 337920K, new size 358400K

Resetting the Oracle Database passwords

During the build a default password was allocated, however it’s a good idea to update the passwords now, fortunately the build includes a utility to update the Oracle SYS, SYSYEM & PDBADMIN.

[oracle@localhost dockerfiles]$ sudo docker exec pure ./ Docker
The Oracle base remains unchanged with value /opt/oracle

SQL*Plus: Release Production on Tue Mar 28 14:56:13 2017

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

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

User altered.

User altered.

Session altered.

User altered.

SQL> Disconnected from Oracle Database 12c Enterprise Edition Release – 64bit Production

Stopping the Oracle Database Docker

[oracle@localhost dockerfiles]$ sudo docker stop pure

[oracle@localhost dockerfiles]$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

Restarting the Oracle Database Docker

[oracle@localhost dockerfiles]$ sudo docker ps
CONTAINER ID        IMAGE                         COMMAND                  CREATED             STATUS              PORTS                              NAMES

f4c614207382        oracle/database:   “/bin/sh -c ‘exec $OR”   22 hours ago        Up 2 seconds>1521/tcp, 5500/tcp   pure

[oracle@localhost bin]$ ./sql system/Docker@//localhost:1521/ORCLPDB1

SQLcl: Release 4.2.0 Production on Tue Mar 28 15:20:02 2017

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

Last Successful login time: Tue Mar 28 2017 15:20:03 +00:00

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

SQL> select name from v$database;



Using the Docker Log

The docker logs command will perform a tail -f of /opt/oracle/diag/rdbms/orclcdb/ORCLCDB/trace/alert_ORCLCDB.log which can be useful to diagnose problems or just to review status.

[oracle@localhost ~]$ sudo docker logs -f pure

LSNRCTL for Linux: Version – Production on 27-MAR-2017 16:10:45

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

Starting /opt/oracle/product/ please wait…

TNSLSNR for Linux: Version – Production
System parameter file is /opt/oracle/product/
Log messages written to /opt/oracle/diag/tnslsnr/f4c614207382/listener/alert/log.xml

Version TNSLSNR for Linux: Version – Production
Start Date 27-MAR-2017 16:10:45
Uptime 0 days 0 hr. 0 min. 0 sec
Trace Level off
Security ON: Local OS Authentication
Listener Parameter File /opt/oracle/product/
Listener Log File /opt/oracle/diag/tnslsnr/f4c614207382/listener/alert/log.xml
Listening Endpoints Summary…
The listener supports no services
The command completed successfully
The docker start command runs the container automatically into the background.

Getting started with Ansible and Oracle


In my previous post An introduction to Ansible I shared some reasons why companies are adopting Ansible and described some of the advantages of using Ansible over other configuration management tools.

Now we know what Ansible is, let’s start using it.

Setting up an Ansible Control Machine

The simplest and quickest way to get up and running with Ansible is to use Vagrant to create a virtual machine. Vagrant ships with out of the box support for VirtualBox, Hyper-V and Docker. Vagrant supports other providers e.g. VMware but these are licenceable

So even though I mainly use VMware Fusion on my MacBook I used the links above to install Vagrant and the excellent Oracle VirtualBox to avoid any licensing requirements.

Using Vagrant

Run the following commands to create a Vagrantfile for an Ubuntu Vagrant machine.
$ mkdir ansible_oracle
$ cd ansible_oracle
$ vagrant init ubuntu/trusty64

A `Vagrantfile` has been placed in this directory. You are now ready to `vagrant up` your first virtual environment! Please read the comments in the Vagrantfile as well as documentation on `` for more information on using Vagrant.

$ vagrant up
You should now be able to SSH into your Ubuntu VM using ‘vagrant ssh’, however before we try and connect to our new VM let’s check the status of all the local Vagrant machines using the following:
$ vagrant global-status

id       name    provider   state    directory
a1995ac  default virtualbox running  /Users/ronekins/ansible_oracle

The above shows information about all known Vagrant environments
on this machine. This data is cached and may not be completely
up-to-date. To interact with any of the machines, you can go to
that directory and run Vagrant, or you can use the ID directly
with Vagrant commands from any directory. For example:
“vagrant destroy 1a2b3c4d”

$ vagrant status a1995ac
Current machine states:

default running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

$ vagrant ssh
If all has gone well you should be presented with your Ubuntu virtual machine.

Useful vagrant machine (vm) commands

destroy       : stops and deletes all traces of the vm 
global-status : outputs status Vagrant env's for this user 
halt          : stops the vm 
init          : initialises a new Vagrant environment 
provision     : provisions the vm 
reload        : restarts vm, loads new Vagrantfile config 
resume        : resume a suspended vm 
snapshot      : manages snapshots, saving, restoring, etc. 
ssh           : connects to vm via SSH 
status        : outputs status of the vm 
suspend       : suspends the vm 
up            : starts and provisions the vm

Ansible Installation

$ sudo apt-get install software-properties-common
$ sudo apt-add-repository ppa:ansible/ansible
$ sudo apt-get update
$ sudo apt-get install ansible

Update local host file

Add the IP address and database server names to your local host file.
$ sudo vi /etc/hosts

Getting Started

Create Ansible configuration file

$ vi ansible.cfg
hostfile = hosts

Create Ansible host file

In the host file we can specify that we want ansible to default to the ‘oracle’ user, the first entry is a server alias, in the example below I have kept it the same as the server name but it can be useful if you have cryptic host names or want to refer to the server by it’s database or application name.
$ vi hosts
z-oracle         ansible_host=z-oracle        ansible_user=oracle
z-oracle-dr  ansible_host=z-oracle-dr  ansible_user=oracle

Ansible Ping Test

Now let’s try using the Ansible ping module to try to connect to our database server and verify a usable version of python, the ping module will return ‘pong’ on success.
$ ansible all -m ping

Both servers will fail returning UNREACHABLE! as the ssh connection failed, to fix this add a public key to the database servers ‘authorized_keys’file.

Generating RSA Keys

Before we can use password-less SSH we need to create a pair of private and public RSA keys for our Ansible control machine.

$ cd ~/.ssh
$ ssh-keygen -t rsa
$ cat

‘Copy’ the into your client buffer and ssh onto the database servers as the ‘oracle’, cd to the .ssh directory and ‘paste’ the public key into the ‘authorized_keys’ file.

$ cd ~/.ssh
$ vi authorised_keys

Now return to your Ansible control machine to repeat the Ansible Ping Tests.

Ansible Ping Part II

Ok, now we are ready to check connectivity, first lets trying using the database server names individually.
That was great, but as we defined a group ‘dbservers’ we can also perform a ‘ping’ test using the group name as we may want to perform an ansible play against a group of servers e.g. Production, Development, Test etc..

Very cool, if required you can use the ‘all’ option to run against all entries in the host file.

In my next blog post we will start to use our Ubuntu Ansible control machine to interact with our database servers.

An introduction to Ansible

Why this Blog

Over the last couple of years I have found myself increasingly working with DevOps teams and being exposed to the tools and techniques being adopted. However speaking to other DBA’s and Architects it appears that for many it’s still a bit of a ‘Dark Art’, so I thought it was about time I shared some the knowledge over a series of DevOps focused Blogs posts.

Why is Ansible, Ansible ?

The term Ansible is a Science Fiction reference for a ficitonal communications device that can transfer information faster than the speed of light.

The author Ursula LeGuin invented the concept in her 1966 book ‘Rocannon’s World’, subsequently other SciFi authors have borrowed the term.

Only for a moment, when he had located the control room and found the ansible and sat down before it, did he permit his mind-sense to drift over to the ship that sat east of this one. There he picked up a vivid sensation of a dubious hand hovering over a white Bishop. …

As his fingers (left hand only, awkwardly) struck each key, the letter appeared simultaneously on a small black screen in a room in a city on a planet eight lightyears distant:

From Rocannon’s World, by Ursula LeGuin.

Michael DeHaan the creator of Ansible took inspiration for the name Ansible from the book ‘Enders Game’ by Orson Scott Card (note to self must read book / watch the film) in the book Ansible is used to control a large number of remote ships at once, over large distances.  From now on whenever I mention Ansible it will be to control remote servers not ships, however it would be useful to be able to control my Elite Dangerous craft remotely.

What is Ansible ?

Ansible is often lumped into the DevOps tool category of ‘Configuration Management’ and compared to Puppet, Chef & Salt. The term ‘Configuration Management’ is generally used to describe the management of the state of IT infrastructure, which can include servers, storage arrays and databases etc…

When you need to deploy configuration change across multiple platforms ‘Orchestration’ is often required to ensure the correct sequence of events, e.g. you may need to configure storage volumes, Unix mount points all before you can start a database service. Ansible is pretty good a conductor, orchestrating actions across multiple servers.

Why use Ansible

Ansible and Salt both use a ‘Push’ method of communication that does not not require any agents to be installed on remote servers. Ansible’s only requirements are SSH connectivity to the remote servers and for the servers to have Python 2.5 installed. I have not yet had the opportunity to take Salt for a test ride, so I can’t comment on it’s requirements.

Puppet and Chef have taken a ‘Pull-based’ approach, where agents installed on the remote servers periodically check in with a central server and pull down configuration information.

The ‘Push-based’ approach has a significant advantage over ‘Pull-based’ solutions as you can control when a configuration change is implemented rather than having to wait for a timer to expire in a ‘Pull-based’ solution.

My next Blog Post will be ‘Getting Started with Ansible and Oracle’.

Hope to get it out very soon, if you want to know when it’s ready use the below to follow me.