8i | 9i | 10g | 11g | 12c | 13c | 18c | 19c | 21c | 23ai | Misc | PL/SQL | SQL | RAC | WebLogic | Linux

Home » Articles » Linux » Here

Docker : Upgrade an Oracle Database on Docker

This article discusses the issues related to upgrading an Oracle Database running on a Docker container.

Related articles.


Before we start it's worth saying there is nothing to stop you using any method you like to upgrade an Oracle database, since you can choose to use Docker as lightweight virtualization and make the container as bloated as you like. The point of this article is to discuss how to perform an upgrade, whilst trying to stay close to the Docker approach to container upgrades.

The next section discusses an application upgrade, to give you a little context about how upgrades will typically happen when using Docker.

Typical Application Server Upgrade

Imagine we have an application running on Tomcat in a Docker container, with the container based on an image called "mytomcat:1.0". Our application files are on a persistent volume, which could be a named volume, a data volume container or a host directory, which is mounted to "/u01/tomcat/webapps" inside the container. In this example we will use a host directory to keep things simple. If we want to do OS updates or if a new version of Tomcat and/or Java is released how do we reflect that in our container? We could do the following.

Assuming the build has been done, that could be as simple as the following.

$ docker rm -vf mytomcat_con
$ docker run -dit --name mytomcat_con -p 8443:8443 -v /host/volumes/mytomcat_con_webapps:/u01/tomcat/webapps" mytomcat:1.1

This throw-away and replace approach is typical of upgrades for Docker containers. Persistent information and config is kept outside the container, so the container can be replaced quickly and easily. Notice there has been no manual intervention to initiate an upgrade.

The Problem with Oracle Upgrades and Docker

This approach presents a problem for an Oracle database. Why? Because an Oracle upgrade requires some operations to be performed with the database running on the original software and some operations running on the new version of the software. As a result, we can't just throw away the old container and start a new one, pointing to all the same datafiles.

At first thought, a pluggable database (PDB) seems to be the obvious solution, since we can unplug the PDB for an upgrade, then plug the PDB into a CDB running at the new upgraded version. This approach to upgrading is explained here.

So the pseudocode for our container startup process might be something like this right?

On startup check for the datafiles on persistent storage. 
IF they exist THEN
  # The instance is already there so use it.
  Start the instance in the normal way.
  Create a new CDB with no PDBs.
  Check for unplugged PDB in specific location on persistent storage.
  IF it exists THEN
    # This is the first time the container has been started,
    # so plug in the PDB.
    Plug it in.
    Delete the source files.
    # This must be a request for a new CDB and PDB.
    Build a new PDB.

Wrong! We need to prepare the PDB for an upgrade before we unplug it, and we do that by running a script from the ORACLE_HOME containing the new software, or preferably using the "preupgrade.jar" file downloaded from MOS 884522.1. We also have to copy the "postupgrade_fixups.sql" script between containers.

If we are happy to have manual intervention in the process, we can do that, but if we want to take the approach that all we ever do with a container is turn it on and off, we need a way to automate this. This what is discussed below.

Performing an Upgrade

This is just an example of what you might do, not a recommendation. The upgrade process described here is intentionally simplistic. I wouldn't dream of using this for something real.

What are our options?

Regarding the last option, how might we do this? Imagine we have the following three images, built using the linked Dockerfiles.

We can build each of the three images as follows.

$ cd /u01/dockerfiles/database/ol7_121
$ docker build --squash -t ol7_121:latest .

$ cd /u01/dockerfiles/database/ol7_121_122
$ docker build --squash -t ol7_121_122:latest .

$ cd /u01/dockerfiles/database/ol7_122
$ docker build --squash -t ol7_122:latest .

Our starting point is an Oracle 12.1 database running in a container based on the "ol7_121:latest" image, with the persistent storage mounted in the container as "/u02". We can create this starting container and database using the following commands.

# Actions performed as root.

# # Create persistent storage, or clear it down if already present.
# mkdir -p /u01/volumes/upgrade_db_u02
# rm -Rf /u01/volumes/upgrade_db_u02/*
# groupadd -g 1042 docker_fg
# chown -R :docker_fg /u01/volumes
# chmod -R 775 /u01/volumes
# chmod -R g+s /u01/volumes
# usermod -aG docker_fg docker_user

# Actions performed as docker_user

$ # Create a container based on the 12.1 image using defaults (cdb1 & pdb1). This creates the database.
$ # Mount persistent storage.
$ docker run -dit --name upgrade_db_con -p 1521:1521 --shm-size="1G" -v /u01/volumes/upgrade_db_u02/:/u02 ol7_121:latest
$ docker logs --follow upgrade_db_con

Wait for the 12.1 database to be created. This should be obvious from the output of the docker logs command.

To perform the upgrade we might do the following.

Here is how we would do this using the images built previously.

Gracefully shutdown the container and remove it. This doesn't affect the persistent storage.

$ docker stop --time=60 upgrade_db_con
$ docker rm -vf upgrade_db_con

Create a container based on the dual image using defaults (cdb1 & pdb1). Mount the same persistent storage. This actually performs the upgrade, leaving you with the PDB running in a 12.2 instance.

$ docker run -dit --name upgrade_db_con -p 1521:1521 --shm-size="1G" -v /u01/volumes/upgrade_db_u02/:/u02 ol7_121_122:latest
$ docker logs --follow upgrade_db_con

You will need to wait for the upgrade to complete. This should be obvious from the output of the docker logs command.

Gracefully shutdown the container and remove it. This doesn't affect the persistent storage.

$ docker stop --time=60 upgrade_db_con
$ docker rm -vf upgrade_db_con

Create a container based on the 12.2 image using defaults (cdb1 & pdb1). Mount persistent storage.

$ docker run -dit --name upgrade_db_con -p 1521:1521 --shm-size="1G" -v /u01/volumes/upgrade_db_u02/:/u02 ol7_122:latest
$ docker logs --follow upgrade_db_con

We now have an upgraded database, running on a clean image with only the latest software.

For more information see:

Hope this helps. Regards Tim...

Back to the Top.