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
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.
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.