How to use Oracle Instant Client Docker images

Posted in: Oracle, Technical Track

There are two available, both Version 12.2. One is found on Docker Hub and the other on the Oracle Container Registry.

The following are instructions on obtaining both images, followed by a narrative of making one of them work in my environment.

It is assumed that you already have a Docker environment configured. If not you may wish to visit this site: Docker – Get Started

Docker Hub

Oracle Instant Client

It is necessary to first ‘Proceed to Checkout’ and accept the terms and conditions. Once that is done you will be shown the docker pull command to be used.

$  docker login
Authenticating with existing credentials...
WARNING! Your password will be stored unencrypted in /home/jkstill/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
Login Succeeded
 
$ docker pull store/oracle/database-instantclient:12.2.0.1

Oracle Container Registry

Follow the instructions here: Using the Oracle Container Registry

  • Log in to Oracle Container Registry with your Oracle Account (free if you don’t already have one).
  • Navigate to the image you wish to install.
  • Accept the Terms and Conditions.

At this time you will be shown the Docker pull command used to obtain the Docker image.

It is necessary to first log in to Oracle Container Registry in a browser or else the Docker pull command will fail.

The instant client was located here at the time of writing: Oracle Instant Client

The image was downloaded:

$  docker login container-registry.oracle.com
Username: jkstill@gmail.com
Password:
WARNING! Your password will be stored unencrypted in /home/jkstill/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
 
Login Succeeded
 
docker pull container-registry.oracle.com/database/instantclient:12.2.0.1

Now there are 2 rather large images installed

$  docker image ls | head -1 ; docker image ls | grep oracle
REPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZE
container-registry.oracle.com/database/instantclient   12.2.0.1            fda46de41de3        16 months ago       407MB
store/oracle/database-instantclient                    12.2.0.1            916033cf06bf        19 months ago       404MB

Run the images

The example command line as seen at Oracle Instant Client.

docker run -ti --rm container-registry.oracle.com/database/instantclient sqlplus hr/welcome@example.com/pdborcl

First I will log in to a database to make sure it is up

$  sqlplus jkstill/XXX@p1
 
SQL*Plus: Release 12.1.0.2.0 Production on Fri Dec 28 07:21:56 2018
 
Copyright (c) 1982, 2014, Oracle.  All rights reserved.
 
Last Successful login time: Fri Dec 28 2018 07:20:10 -08:00
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
JKSTILL@p1 $

Now try with docker

$  docker run -ti --rm container-registry.oracle.com/database/instantclient:latest sqlplus -L jkstill/XXX@p1
 
SQL*Plus: Release 12.2.0.1.0 Production on Fri Dec 28 15:23:06 2018
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
ERROR:
ORA-12154: TNS:could not resolve the connect identifier specified
 
SP2-0751: Unable to connect to Oracle.  Exiting SQL*Plus

The problem here is that the environment in the Docker image does not know how to connect to my local environment.

The instance ‘p1’ is actually defined in an LDAP database:

$  tnsping p1
 
TNS Ping Utility for Linux: Version 12.1.0.2.0 - Production on 28-DEC-2018 07:24:29
 
Copyright (c) 1997, 2014, Oracle.  All rights reserved.
 
Used parameter files:
/u01/app/oracle/product/12.1.0/c12/network/admin/sqlnet.ora
 
Used LDAP adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = ora122rac-scan.jks.com)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = js1.jks.com)))
OK (0 msec)

What needs to be done now is create the ldap.ora file.

docker run -ti --rm container-registry.oracle.com/database/instantclient:latest /bin/bash
 
bash-4.2# pwd
/usr/lib/oracle/12.2/client64
bash-4.2# mkdir -p network/admin
 
bash-4.2# cat > network/admin/ldap.ora
DIRECTORY_SERVERS=(192.168.1.2:389:636)
DEFAULT_ADMIN_CONTEXT = "dc=jks,dc=com"
DIRECTORY_SERVER_TYPE = OID
 
bash-4.2# mkdir -p /opt/sql
bash-4.2# mkdir -p /opt/sql-lib

From another session, commit the container to a new image:

$ docker container ls
CONTAINER ID        IMAGE                                                         COMMAND             CREATED             STATUS              PORTS               NAMES
be77ff794f70        container-registry.oracle.com/database/instantclient:latest   "/bin/bash"         6 minutes ago       Up 6 minutes                            loving_shaw
 
$ docker commit -m 'added ldap.ora' be77ff794f70 jkstill/oracle-12.2-instantclient:latest
sha256:45674fcb5eb82d80d86ede86e5b9789f4ee56bada32457ddbf3172bf53982be1

Connections are still failing.

docker run -ti --rm jkstill/oracle-12.2-instantclient sqlplus -L jkstill/XXX@p1

Now create a new commit of the image with TNS_ADMIN set. The location of the ldap.ora file should work in this location, but setting TNS_ADMIN will ensure that ldap.ora will be found

#  docker commit  -c 'ENV TNS_ADMIN=/usr/lib/oracle/12.2/client64/network/admin' -m 'added ldap.ora' 50ac8602f430  jkstill/oracle-12.2-instantclient:latest

Running the test again, there is still no connection being made. At this point, I suspect the issue is that this image cannot resolve names.

bash-4.2# cat resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
search jks.com
 
nameserver 8.8.8.8
nameserver 8.8.4.4

Replace the file and make it immutable. The chattr program is not installed, so the e2fsprogs.x86_64 package was first installed.

bash-4.2# yum install e2fsprogs.x86_64
...
 
bash-4.2# cat > resolv.conf
domain jks.com
search jks.com
nameserver 192.168.1.2
 
bash-4.2# chattr +i resolv.conf
chattr: Operation not permitted while setting flags on resolv.conf
 
bash-4.2# chmod -w resolv.conf

So chattr + operations are not allowed. I did not look into why, but set resolv.conf to read only (we will find out a little later why this didn’t work).

So that ping would be available…

bash-4.2# yum install iputils

Now connections to the RAC server are working.

bash-4.2# ping -c 1 ora122rac02
PING ora122rac02.jks.com (192.168.1.222) 56(84) bytes of data.
64 bytes from ora122rac02.jks.com (192.168.1.222): icmp_seq=1 ttl=63 time=0.472 ms
 
--- ora122rac02.jks.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.472/0.472/0.472/0.000 ms

Re-commit the new image and check the size.

$  docker commit  -c 'ENV TNS_ADMIN=/usr/lib/oracle/12.2/client64/network/admin' -m 'added ldap.ora and ping utilities' 50ac8602f430  jkstill/oracle-12.2-instantclient:latest
 
$  docker image ls | head -1; docker image ls | grep instant
REPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZE
jkstill/oracle-12.2-instantclient                      latest              f65f1b6a72c7        52 seconds ago      688MB
container-registry.oracle.com/database/instantclient   12.2.0.1            fda46de41de3        16 months ago       407MB
container-registry.oracle.com/database/instantclient   latest              fda46de41de3        16 months ago       407MB
store/oracle/database-instantclient                    12.2.0.1            916033cf06bf        19 months ago       404MB

The size has ballooned a bit at 688MB.

Changing the /etc/resolv.conf file and committing to the new image did not help, as the same contents are again seen in /etc/resolv.conf.

$ docker run -ti --rm jkstill/oracle-12.2-instantclient /bin/bash
bash-4.2# echo $TNS_ADMIN
/usr/lib/oracle/12.2/client64/network/admin
bash-4.2# ping ora122rac-scan.jks.com
ping: ora122rac-scan.jks.com: Name or service not known
bash-4.2# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
search jks.com
 
nameserver 8.8.8.8
nameserver 8.8.4.4
bash-4.2# exit

Now it is time to take a look at the documentation.

Configure Container DNS

Docker uses some special files to manage the /etc/hosts, /etc/hostnames and /etc/resolv.conf files – read about it the previously shown documentation link (this is why earlier attempts to use chattr failed).

The documentation also shows how to override these from the command line.

$  docker run --dns=192.168.1.2 --dns-search=jks.com -ti --rm jkstill/oracle-12.2-instantclient /bin/bash
bash-4.2# cat /etc/resolv.conf
search jks.com
nameserver 192.168.1.2

Now the container can connect to the network properly.

$  docker run --dns=192.168.1.2 --dns-search=jks.com -ti --rm jkstill/oracle-12.2-instantclient sqlplus -L jkstill/XXX@p1
 
SQL*Plus: Release 12.2.0.1.0 Production on Fri Dec 28 16:39:55 2018
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
Last Successful login time: Fri Dec 28 2018 15:21:56 +00:00
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL$ @who
SP2-0310: unable to open file "who.sql"
SQL$ Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL$

Success! Well, at least as far as connecting to the database. The container does not know about my $SQLPATH settings.

Before dealing with that, however, I will see if the size of the image can be made somewhat smaller.

Now that I know what to do to get the Docker image to work in my environment, I will remove the newly committed image and start over without installing extra packages.

$  docker image rm jkstill/oracle-12.2-instantclient
Untagged: jkstill/oracle-12.2-instantclient:latest
Deleted: sha256:f65f1b6a72c7cdaf19e279f2e8f8a6643fa966a5071eacbb0d3b3da2c0127469
Deleted: sha256:19b964c8150b24b79925a7b5ad24efe409fc2394399edeff2affd0ceab95a04d

Restart the Oracle-provided image and re-apply the changes for TNS_ADMIN and ldap.ora to the new image.

$  docker run -ti --rm container-registry.oracle.com/database/instantclient /bin/bash
bash-4.2# cd /usr/lib/oracle/12.2/client64
 
bash-4.2# mkdir -p network/admin
 
bash-4.2# cat > network/admin/ldap.ora
DIRECTORY_SERVERS=(192.168.1.2:389:636)
DEFAULT_ADMIN_CONTEXT = "dc=jks,dc=com"
DIRECTORY_SERVER_TYPE = OID
 
bash-4.2# mkdir -p /opt/sql
bash-4.2# mkdir -p /opt/sql-lib

From another session:

$  docker ps
CONTAINER ID        IMAGE                                                  COMMAND             CREATED             STATUS              PORTS               NAMES
57263fa776e3        container-registry.oracle.com/database/instantclient   "/bin/bash"         2 minutes ago       Up 2 minutes                            condescending_pasteur
 
$ docker commit  -c 'ENV TNS_ADMIN=/usr/lib/oracle/12.2/client64/network/admin' -m 'added ldap.ora' 57263fa776e3  jkstill/oracle-12.2-instantclient:latest
sha256:94ac5d2b864102388c951e9210fa5ef241aee5584a9999013ad6d34fe8ff11ba

Now the image is the same size as the original:

$  docker image ls | head -1; docker image ls | grep instant
REPOSITORY                                             TAG                 IMAGE ID            CREATED             SIZE
jkstill/oracle-12.2-instantclient                      latest              94ac5d2b8641        42 seconds ago      407MB
container-registry.oracle.com/database/instantclient   12.2.0.1            fda46de41de3        16 months ago       407MB
container-registry.oracle.com/database/instantclient   latest              fda46de41de3        16 months ago       407MB
store/oracle/database-instantclient                    12.2.0.1            916033cf06bf        19 months ago       404MB

By using the –dns and –dns-search options, the connection to the database is now working.

$  docker run --dns=192.168.1.2 --dns-search=jks.com -ti --rm jkstill/oracle-12.2-instantclient sqlplus -L jkstill/XXX@p1
 
SQL*Plus: Release 12.2.0.1.0 Production on Fri Dec 28 16:51:34 2018
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
Last Successful login time: Fri Dec 28 2018 16:49:21 +00:00
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL$ Disconnected from Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

Now to fix the SQLPATH issue.

My SQLPATH at this time: /home/jkstill/oracle/oracle-script-lib/sql:/home/jkstill/oracle/admin/sql.

There is no user ‘jkstill’ in the Docker image, and there is no need to create one. The Docker-mount option can be used to make these scripts available at runtime to the sqlplus client in the container.

The following options will do it:

–mount type=bind,source=/home/jkstill/oracle/oracle-script-lib/sql,target=/opt/sql-lib

–mount type=bind,source=/home/jkstill/oracle/admin/sql,target=/opt/sql

So the SQLPATH variable for the container will be set to /opt/sql-lib:/opt/sql

Start up the new image again, using bash will work.

$  docker run --dns=192.168.1.2 --dns-search=jks.com -ti --rm jkstill/oracle-12.2-instantclient /bin/bash
bash-4.2#

Now commit the image again, setting the SQLPATH variable.

$  docker ps
CONTAINER ID        IMAGE                               COMMAND             CREATED             STATUS              PORTS               NAMES
2b5f493b6b0f        jkstill/oracle-12.2-instantclient   "/bin/bash"         43 seconds ago      Up 42 seconds                           musing_montalcini
 
$  docker commit  -c 'ENV SQLPATH=/opt/sql-lib:/opt/sql' -m 'added SQLPATH' 2b5f493b6b0f  jkstill/oracle-12.2-instantclient:latest
sha256:58891599275e28b8385a22fefeb30a06e02d30f30ca64ebccdc2260201ce2ed5

Now exit Docker, restart with the mount commands and see if everything is as expected.

docker run --dns=192.168.1.2 --dns-search=jks.com -ti --rm \
--mount type=bind,source=/home/jkstill/oracle/oracle-script-lib/sql,target=/opt/sql-lib \
--mount type=bind,source=/home/jkstill/oracle/admin/sql,target=/opt/sql \
jkstill/oracle-12.2-instantclient /bin/bash
 
bash-4.2# cd /opt
bash-4.2# ls -l
total 92
drwxr-x--- 4 1000 1002 65536 Dec 24 19:36 sql
drwxr-xr-x 3 1000 1002 24576 Dec 14 20:29 sql-lib
 
bash-4.2# ls -l sql/*.sql | wc
1381   12983   95660
bash-4.2# ls -l sql-lib/*.sql | wc
574    5182   39430
 
bash-4.2# cat /etc/resolv.conf
search jks.com
nameserver 192.168.1.2
 
bash-4.2# sqlplus jkstill/XXX@p1
 
SQL*Plus: Release 12.2.0.1.0 Production on Fri Dec 28 17:11:31 2018
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
Last Successful login time: Fri Dec 28 2018 16:51:34 +00:00
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL$

Looks good, now to try with sqlplus directly.

$  docker run --dns=192.168.1.2 --dns-search=jks.com -ti --rm \
--mount type=bind,source=/home/jkstill/oracle/oracle-script-lib/sql,target=/opt/sql-lib \
--mount type=bind,source=/home/jkstill/oracle/admin/sql,target=/opt/sql \
jkstill/oracle-12.2-instantclient sqlplus -L jkstill/XXX@p1
 
SQL*Plus: Release 12.2.0.1.0 Production on Fri Dec 28 17:12:48 2018
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
Last Successful login time: Fri Dec 28 2018 17:11:31 +00:00
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL$ @who
 
USERS LOGGED ON   SESSIONS
--------------- ----------
JKSTILL                  1
SYS                      1
 
SQL$ @who2
 
V_OVERSION_MAJOR
--------------------------------------------------------------------------------
12
 
1 row selected.
 
PL/SQL procedure successfully completed.
 
CLIENT                                        SRVR
USERNAME      SID SERIAL# SQL ID            PID STATUS     MACHINE    OSUSER     CLIENT PROGRAM       PID                      SERVER PROGRAM       PID   LOGON TIME        IDLE TIME
---------- ------ ------- -------------- ------ ---------- ---------- ---------- -------------------- ------------------------ -------------------- ----- ----------------- -----------
JKSTILL        52   64215 chmy5m24rfhvp      82 ACTIVE     4cfdbbea9d root       sqlplus@4cfdbbea9d93 1                        oracle@ora122rac02.j 24627 12/28/18 09:12:49 00:00:00:00
93
 
SYS             6   17304                    12 ACTIVE     ora122rac0 oracle     oracle@ora122rac02.j 4308_4311                oracle@ora122rac02.j 4308  10/24/18 22:08:05 64:12:04:47
2.jks.com
 
2 rows selected.
 
SQL$

Success! It’s a good idea to create a shell script or an alias to use that rather lengthy command, as you don’t want to have to type that out.

Here is an example bash script:

#!/usr/bin/env bash
 
debug=1
 
# use this line to supply default password if desired
#password=${password:-'MYPASSWORD'}
username=${username:-'jkstill'}
instance=${instance:-'p1'}
 
if [ -n "$sysdba" ]; then
        sysdba=' as sysdba'
else
        sysdba=''
fi
 
# build the command to prompt for password if not supplied
if [[ -n "$password" ]]; then
        sqlCmd="sqlplus -L ${username}/${password}@${instance} ${sysdba}"
else
        sqlCmd="sqlplus -L ${username}@${instance} ${sysdba}"
fi
 
[[ $debug -gt 0 ]] && {
        echo Username: $username
        echo Password: $password
        echo Instance: $instance
        echo "  Sysdba: $sysdba"
        echo "     CMD:" $sqlCmd
}
 
 
docker run --dns=192.168.1.2 --dns-search=jks.com -ti --rm \
        --mount type=bind,source=/home/jkstill/oracle/oracle-script-lib/sql,target=/opt/sql-lib  \
        --mount type=bind,source=/home/jkstill/oracle/admin/sql,target=/opt/sql \
        jkstill/oracle-12.2-instantclient $sqlCmd

And now some usage examples:

Prompt for password.

>  instance=p3 12-2.sh
Username: jkstill
Password:
Instance: p3
  Sysdba:
     CMD: sqlplus -L jkstill@p3
 
SQL*Plus: Release 12.2.0.1.0 Production on Wed Jan 2 16:03:53 2019
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
Enter password:
Last Successful login time: Wed Jan 02 2019 16:00:15 +00:00
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL>

Supply the password on the command line.

>  password=XXX instance=p3 12-2.sh
Username: jkstill
Password: XXX
Instance: p3
  Sysdba:
     CMD: sqlplus -L jkstill/XXX@p3
 
SQL*Plus: Release 12.2.0.1.0 Production on Wed Jan 2 16:05:05 2019
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
Last Successful login time: Wed Jan 02 2019 16:03:55 +00:00
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL>

Logon as SYSDBA

>  sysdba=1 password=XXX instance=p3 12-2.sh
Username: jkstill
Password: XXX
Instance: p3
  Sysdba:  as sysdba
     CMD: sqlplus -L jkstill/XXX@p3 as sysdba
 
SQL*Plus: Release 12.2.0.1.0 Production on Wed Jan 2 16:06:09 2019
 
Copyright (c) 1982, 2016, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
 
SQL>

Also, if you need to save some space, the Oracle Instant client image is no longer required and can be deleted.

What’s next

A Docker image with an 18c client would sure be nice to have.

My work environment is Ubuntu Mate 16.x, with Oracle 11.2 and 12.1 full client software installed.

Due to changes in libraries with 12.2 and 18c, I found it was impossible to install either of these in the current environment. Using Docker makes is possible to use the 12.2 client, and eventually the 18c client as well.

Currently, there isn’t an 18c client Docker image that I know of, but one could be crafted for that purpose.

That will have to wait for a later blog.

email

Interested in working with Jared? Schedule a tech call.

About the Author

Oracle experience: started with Oracle 7.0.13 Programming Experience: Perl, PL/SQL, Shell, SQL Also some other odds and ends that are no longer useful Systems: Networking, Storage, OS to varying degrees. Have fond memories of DG/UX

2 Comments. Leave new

Jennifer Bradley
January 30, 2019 6:35 am

Thank you for this meticulous and well-explained guide on using Oracle Instant Client Docker Images.

Reply

You’re welcome Jennifer.

You may like this followup for 18c:

https://blog.pythian.com/how-to-create-an-oracle-18c-client-image-in-docker/

Reply

Leave a Reply

Your email address will not be published. Required fields are marked *