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.
- Introduction
- Typical Application Server Upgrade
- The Problem with Oracle Upgrades and Docker
- Performing an Upgrade
Related articles.
Introduction
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.
- Build a new image called "mytomcat:1.1" with the latest versions of the OS packages, Java and Tomcat.
- Remove the current container.
- Run a new container based on the latest image, mounting the persistent storage to the correct location.
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. ELSE 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. ELSE # This must be a request for a new CDB and PDB. Build a new PDB. END IF END IF
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?
- Conventional Upgrade : This involves installing the new Oracle software, then running the Database Upgrade Assistant (DBUA). That is going to add a lot of weight to the container. You could do this to get the database to the correct version, then throw the container away and replace it with a clean container at the correct version.
- PDB Upgrade : This involves installing the new Oracle software, preparing the PDB for upgrade, unplugging it, plugging it into the new container. As with the previous option, this is going to add a lot of weight to the container. You could do this to get the database to the correct version, then throw the container away and replace it with a clean container at the correct version.
- Export/Import : That could work small databases, but it's generally going to be slower than other upgrade alternatives.
- Transportable Database : This is a possibility, although I'm not sure I understand all the pitfalls of this approach.
- PDB Upgrade using intermediate container : This is what I'm going to discuss here.
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.
- Stop and remove the current container, which is based on the "ol7_121:latest" image.
- Startup the intermediate container based on the "ol7_121_122:latest" image, which detects the database in the persistent storage, starts it with the old version of the Oracle software and initiates a scripted upgrade using the new version of the software.
- Stop and remove the intermediate container, which is based on the "ol7_121_122:latest" image.
- Start the container with the destination image "ol7_122:latest".
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...