One of the things that kept me busy lately was experimenting with how much an Oracle XE database setup could be streamlined inside a Docker image for things like CI/CD consumption. Pretty much ever since I put together the first official build scripts for Oracle Database, people have asked for faster image pull and startup times to speed up their continuous integration tests. A lot of things have changed since then, and I’m happy that my engineering colleagues at Oracle have taken on the maintenance and further enhancements of Oracle’s official Docker build files and images, and integrated them into the internal processes.
However, my own needs for some of my private projects such as #csv2db have also caused me to think about how to better streamline and integrate Oracle XE into my own pipelines. I too needed a quick and easy XE Docker image, yet Oracle’s Container Registry did not host an XE image yet (it does now, since about two weeks ago), and all images on Docker Hub that I could find were old 11g R2 XE ones. So, on some Saturday, I sat down to “quickly” put together some new build files for XE, applying some of the lessons learned in the process. And about five months later, the outcome is yet another Docker Hub repository: https://hub.docker.com/r/gvenzl/oracle-xe
Why a repository?
While I was at it, I thought of the many conversations that I had about the trade-off between image size and additional functionality. Sure, sometimes I want to be able to just quickly pull a small image to test a bunch of INSERT
s, but I also want to be able to use, e.g., Oracle’s Spatial functionality. More functionality means more libraries and files in the $ORACLE_HOME
and that, in turn, means a bigger image. The only way I saw to provide the best of both worlds was to offer them; by providing a small, stripped-down image and a big one with all the great bells and whistles of Oracle XE. So I ventured off on a journey of stripping down the XE installation and quickly realized that I needed to document those steps for when a new version of XE will come out. A git
repository was obviously the way to go, and so I did: https://github.com/gvenzl/oci-oracle-xe.
Next, I needed to put the images into some repository from where I could pull them. Luckily, Docker (still) provides free repositories. At first, I thought of a private one that would only be visible to me. But soon I realized that this would require a docker login
from anywhere I want to pull the image (including GitHub Actions), so I thought: “well, why not share it (the repository) with the world then? Perhaps others can use these images as well.” And as I thought about that, it came to my mind that then there should at least be also an image that was not amended to my purposes at all, an image “as is”, meaning with just all the bits and pieces as they come from the regular Oracle XE installation. So I ended up with three images: a small one, a big one, and an “unchanged” one. Although, I did not quite name them that way, but instead a SLIM
, [NOTHING]
and a FULL
image:
[gvenzl@localhost ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/gvenzl/oracle-xe 18-slim f23caf0d8123 4 weeks ago 2.45 GB
docker.io/gvenzl/oracle-xe 18 b0afdca7c19f 4 weeks ago 3.37 GB
docker.io/gvenzl/oracle-xe 18-full e415e9b70b63 5 weeks ago 6.38 GB
docker.io/gvenzl/oracle-xe 11-slim 044e6381c4c5 5 weeks ago 612 MB
docker.io/gvenzl/oracle-xe 11 4e27255d6f37 5 weeks ago 701 MB
docker.io/gvenzl/oracle-xe 11-full ddbea6f88946 5 weeks ago 849 MB
You can see above that I also put together some 11g R2 images, although I mentioned that there were already so many on Docker Hub. The reason for that was that I wanted to provide users that are fond of the 11g R2 images, for whatever the reasons may be, with the same end-user experience that my 18c images have, which brings me to the next point.
Image != image
There are many images for Oracle XE on Docker Hub provided by many different people all with their own needs and ideas of how the image should work. When I put together my images, I sat back and researched what common functionalities users would expect these days. Many images allow passing on some environment variables that further customize the running container. I found a couple of those variables that one could consider “standard”, such as variables to set the password for the database or generate a random one. I also found the need for myself to allow for the creation of an application user, so that not, e.g., all integration test scripts would test as one of the superusers (SYS
, SYSTEM
) but also so that I don’t always have to mess around with additional setup steps. And, of course, I made sure that the mechanism for initialization scripts will also be present, as that has already come in handy so many times for myself.
Another difference that these images have is that they all include a database ready to go. Because the $ORACLE_SID
for XE is anyway hard-coded to XE
, one has not to worry about users wanting to create databases with a different SID
. That, in turn, helps the startup times, because the database does not need to be created any longer. However, it also does increase the image size itself. That’s why the database files inside the image are all compressed and will be uncompressed first at the container startup. The trade-off still plays in favor of including the database images: the additional image size is not that much but the image startup time is much, much faster that way (below 30 seconds usually altogether).
GitHub Actions
Another nice extra that I made sure to document on the repository page, is how to use the image(s) with GitHub Actions for CI/CD tests. GitHub Actions provide a mechanism known as service containers, but the documentation says little about Oracle XE. So, if you want to use any of these images inside your GitHub Actions, just use a script similar to this one here:
services:
# Oracle service
oracle:
# Docker Hub image (feel free to change the tag "latest" to any other available one)
image: gvenzl/oracle-xe:latest
# Provide passwords and other environment variables to container
env:
ORACLE_RANDOM_PASSWORD: true
APP_USER: my_user
APP_USER_PASSWORD: my_password_which_I_really_should_change
# Forward Oracle port
ports:
- 1521:1521
# Provide healthcheck script options for startup
options: >-
--health-cmd healthcheck.sh
--health-interval 10s
--health-timeout 5s
--health-retries 10
Putting it all together
So here is the cool part, if you want to just spin up an Oracle 18c XE image, all you have to do is to, for example, execute: docker run --name oracle-xe-slim -p 1521:1521 -e ORACLE_RANDOM_PASSWORD=true gvenzl/oracle-xe:18-slim
[gvenzl@localhost ~]$ docker run --name oracle-xe-slim -p 1521:1521 -e ORACLE_RANDOM_PASSWORD=true gvenzl/oracle-xe:18-slim
Unable to find image 'gvenzl/oracle-xe:18-slim' locally
Trying to pull repository docker.io/gvenzl/oracle-xe ...
18-slim: Pulling from docker.io/gvenzl/oracle-xe
9a62c8a45386: Pull complete
9b0d4886444a: Pull complete
Digest: sha256:6777d42c5fe2bea135fe24155174a9742b6a56efaa146b7e969a9969881b89a2
Status: Downloaded newer image for gvenzl/oracle-xe:18-slim
CONTAINER: starting up...
CONTAINER: first database startup, initializing...
CONTAINER: uncompressing database data files, please wait...
CONTAINER: done uncompressing database data files, duration: 18 seconds.
CONTAINER: starting up Oracle Database...
LSNRCTL for Linux: Version 18.0.0.0.0 - Production on 15-AUG-2021 02:25:28
Copyright (c) 1991, 2018, Oracle. All rights reserved.
Starting /opt/oracle/product/18c/dbhomeXE/bin/tnslsnr: please wait...
TNSLSNR for Linux: Version 18.0.0.0.0 - Production
System parameter file is /opt/oracle/product/18c/dbhomeXE/network/admin/listener.ora
Log messages written to /opt/oracle/diag/tnslsnr/3a0d8b311e67/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 18.0.0.0.0 - Production
Start Date 15-AUG-2021 02:25:28
Uptime 0 days 0 hr. 0 min. 0 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Default Service XE
Listener Parameter File /opt/oracle/product/18c/dbhomeXE/network/admin/listener.ora
Listener Log File /opt/oracle/diag/tnslsnr/3a0d8b311e67/listener/alert/log.xml
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
The listener supports no services
The command completed successfully
ORACLE instance started.
Total System Global Area 1241512896 bytes
Fixed Size 8895424 bytes
Variable Size 452984832 bytes
Database Buffers 771751936 bytes
Redo Buffers 7880704 bytes
Database mounted.
Database opened.
CONTAINER: Resetting SYS and SYSTEM passwords.
User altered.
User altered.
############################################
ORACLE PASSWORD FOR SYS AND SYSTEM: NzJlNzMz
############################################
#########################
DATABASE IS READY TO USE!
#########################
I myself actually already moved on to Linux 8 and Podman, which means that you can use these images with podman
too (they are actually built with Buildah). All you have to do is to type podman
instead of docker
(or install the docker
alias for Podman): podman run --name oracle-xe-slim -p 1521:1521 -e ORACLE_RANDOM_PASSWORD=true gvenzl/oracle-xe:18-slim
[gvenzl@localhost ~]$ podman run --name oracle-xe-slim -p 1521:1521 -e ORACLE_RANDOM_PASSWORD=true gvenzl/oracle-xe:18-slim
Trying to pull docker.io/gvenzl/oracle-xe:18-slim...
Getting image source signatures
Copying blob 9b0d4886444a done
Copying blob 9a62c8a45386 done
Copying config f23caf0d81 done
Writing manifest to image destination
Storing signatures
CONTAINER: starting up...
CONTAINER: first database startup, initializing...
CONTAINER: uncompressing database data files, please wait...
CONTAINER: done uncompressing database data files, duration: 21 seconds.
CONTAINER: starting up Oracle Database...
LSNRCTL for Linux: Version 18.0.0.0.0 - Production on 15-AUG-2021 02:32:40
Copyright (c) 1991, 2018, Oracle. All rights reserved.
Starting /opt/oracle/product/18c/dbhomeXE/bin/tnslsnr: please wait...
TNSLSNR for Linux: Version 18.0.0.0.0 - Production
System parameter file is /opt/oracle/product/18c/dbhomeXE/network/admin/listener.ora
Log messages written to /opt/oracle/diag/tnslsnr/655d0d492d4b/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_XE)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 18.0.0.0.0 - Production
Start Date 15-AUG-2021 02:32:40
Uptime 0 days 0 hr. 0 min. 0 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Default Service XE
Listener Parameter File /opt/oracle/product/18c/dbhomeXE/network/admin/listener.ora
Listener Log File /opt/oracle/diag/tnslsnr/655d0d492d4b/listener/alert/log.xml
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_XE)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
The listener supports no services
The command completed successfully
ORACLE instance started.
Total System Global Area 1241512896 bytes
Fixed Size 8895424 bytes
Variable Size 452984832 bytes
Database Buffers 771751936 bytes
Redo Buffers 7880704 bytes
Database mounted.
Database opened.
CONTAINER: Resetting SYS and SYSTEM passwords.
User altered.
User altered.
############################################
ORACLE PASSWORD FOR SYS AND SYSTEM: Y2Y3ZTZm
############################################
#########################
DATABASE IS READY TO USE!
#########################
What’s next?
Well, this blog post was long overdue. The images exist for a while now but other things occupied me before I managed to put this blog post together. Technically, I’m not even quite done yet with the images either but they are in a great working state and everything that is left is “icing on the cake”. Although the 18c images can never be as small as the 11g ones, too much great functionality has been added into the kernel in those 11 years in between to be able to strip it all out (easily), there are still some optimizations that I’m planning on to further reduce the 18
and 18-slim
image sizes. Of course, there will be a new XE version coming soon, which I’m planning on adding to the repository as well in the same fashion. For everything else, the images serve me quite well, and I know that some other projects also already are using them successfully. However, there is always the possibility to raise enhancement requests on https://github.com/gvenzl/oci-oracle-xe/issues as well, so we shall see what’s still to come.
Hi Gerald!
Thanks a lot for your xe images!
Some questions about that:
– Is there any plan for a slim version of v21?
– could you please mention prominently the trick about setting DISABLE_OOB=ON in sqlnet.ora to avoid TNS errors from the docker host?
Regards, Nicolas
LikeLike
Hi Nicholas!
Thanks a lot, I’m glad you like them!
1) Yes, there are plans and it is, alongside with the regular one, in the making! Will just take a tiny bit longer to get it done. 🙂
2) I most certainly can, but would you mind also filing that as an ER alongside the error and reason over on https://github.com/gvenzl/oci-oracle-xe/issues so that this is also documented and traceable?
Thanks,
LikeLike
Hi Gerald
Thanks a lot for your quick reply. I filed a bug https://github.com/gvenzl/oci-oracle-xe/issues/38 with the solution.
LikeLike
Hi Nicolas,
Great, thanks a lot!
LikeLike
Thanks a lot for providing the slim version of Oracle 21 XE!
LikeLike
Thanks a lot for using these images, Nicolas! 🙂
LikeLike
how can I install additional programs into that container? For education purpose I require some additional shell programs like: ps, grep.
I couldn’t figure out what package manaeger is in user here.
LikeLike
Hey Robert,
Thanks for your interest in these images.
The package manager used inside is
microdnf
, basicallydnf
but a slimmed-down version of it.Thanks,
LikeLike
Hey, man! First of all, thanks for the great image! It helped me a lot. But there is something that I can’t do: change the timezone. I can’t perform “sudo dnf install systemd” on Oracle Linux.
Can you help me to do that?
(sorry about my english too hehehe)
LikeLike
Hei Cácio,
Thanks for using these images.
You need to run
microdnf
instead and login as root (docker exec … -u=0 …)Hope this helps!
LikeLike