Enable True Cache using Oracle Database 23ai Free container images

Oracle True Cache is one of the many exciting features available with Oracle Database 23ai. If you’d like to see how it looks and feels, you can use Oracle Database 23ai Free to give it a go.

This post describes how to do exactly that using the following stack (updated 250402)

Let’s get started

The Oracle Database 23ai container image is used to set up a working True Cache system. In the end, there will be 2 instances

  • pri-db-free
  • tru-cc-free

The True Cache setup will happen automagically for you. The primary database instance will be stored on a podman volume. The True Cache instance however requires you to use host volumes.

You will undoubtedly notice the use of rootless Podman. Rootless Podman requires a few extra steps you would not normally need to perform if you used Docker. The rootless nature should add some extra security however and makes it worth your while. A more robust, secure setup is rarely bad.

The --userns=keep-id flag is passed to the podman run command . This way the container inherits the local user’s settings for its volumes (more information).

The container expects the volume to be owned by oracle, with a uid of 54321 and a gid of 54321. This is exactly how the host user is configured for this article. Here are the steps I used to create the oracle account:

[vagrant@devbox ~]$ sudo groupadd -g 54321 dba
[vagrant@devbox ~]$ sudo useradd -c "owner of the True Cache setup" -g dba -m -s $(which bash) -u 54321 oracle
[vagrant@devbox ~]$ sudo passwd oracle

SELinux is enabled, again, with the intent of improving the overall security posture. Make sure you are logged in as oracle for the next steps.

Auxiliary structures

Before you can start you need to create meet a few additional prerequisites. These include

  • a Podman volume for the database instance
  • a host directory to store the True Cache instance’s data
  • a network to allow database and True Cache instances to communicate

Note that if you run into trouble, it’s best to start from scratch. At the very least you should consider rename the volume and host directory for a clean start

The following bash variables have been defined to keep things consistent throughout the article:

DB_DATA_VOL=db-pri-vol
TC_DATA_DIR=$(pwd)/data/tc
SECRETS_DIR=$(pwd)/data/secrets
TC_NETWORK=tc-network
TAG=23.7.0.0

Creating the podman resources is as simple as executing these commands (you are logged in as oracle, aren’t you?)

mkdir -vp "${TC_DATA_DIR}"
podman network create "${TC_NETWORK}"
podman volume create "${DB_DATA_VOL}"

Later on you will need to provide IP addresses to the podman run command, one for the database instance and another one for the True Cache instance.

Once the network is created you can grab its details using podman inspect ${TC_NETWORK}. It’s easiest to store the IP addresses in shell variables, too. The database container’s IP address available as ${DB_IP} whereas the True Cache instance’s IP address is available as ${TC_IP}. The following snippet extracts the network’s subnet and adds a couple of IP addresses.

export DB_IP=$(\
    podman network inspect "${TC_NETWORK}" | \
    jq -r '.[].subnets[0].subnet' | \
    awk -F. '{ $4=100; OFS="."; print $1, $2, $3, $4 }'
)
export TC_IP=$(\
    podman network inspect "${TC_NETWORK}" | \
    jq -r '.[].subnets[0].subnet' | \
    awk -F. '{ $4=200; OFS="."; print $1, $2, $3, $4 }'
)

Next up you need to create the encrypted podman secrets as follows. Please don’t change the secret names, the containers expect them to be named oracle_pwd and oracle_pwd_privkey. Unlike for regular database operations, these encrypted secrets are mandatory for True Cache to work.

mkdir -vp "${SECRETS_DIR}" && cd "${SECRETS_DIR}"
openssl genrsa -out key.pem
openssl rsa -in key.pem -out key.pub -pubout
read -s -p "enter the password: " pwd
echo -n $pwd > pwdfile.txt
openssl pkeyutl -in ./pwdfile.txt -out ./pwdfile.enc -pubin -inkey ./key.pub -encrypt

podman secret create oracle_pwd  ./pwdfile.enc
podman secret create oracle_pwd_privkey ./key.pem

Both of these secrets will later be used by the containers /opt/oracle/decryptPassword.sh to extract the unencrypted password.

Starting the database instance

With the passwords, network, and volume in place it’s time to start the database instance:

# optionally `set -u` to make sure no variables are undefined
podman run --rm -d --name pri-db-free \
--hostname pri-db-free \
--net="${TC_NETWORK}" \
--ip "${DB_IP}" \
-p :1521 \
--secret=oracle_pwd \
--secret=oracle_pwd_privkey \
--add-host="tru-cc-free:${TC_IP}" \
-e ENABLE_ARCHIVELOG=true \
-e ENABLE_FORCE_LOGGING=true \
-v "${DB_DATA_VOL}":/opt/oracle/oradata \
container-registry.oracle.com/database/free:"${TAG}"

After the download completes, it takes about 5-10 seconds to start the primary database. You can use podman logs pri-db-free to tail the database’s alert.log. Once you see DATABASE OPEN you can proceed with the next step.

Starting the True Cache instance

Start the True Cache instance as follows, adjust PDB_TC_SVCS as needed. The values you provide in PDB_TC_SVCS map to the service names that will be generated automatically. In this example, there will be 4, all of them in FREEPDB1. You can read more about the network configuration required for True Cache in the True Cache User’s Guide.

podman run --rm -d --name tru-cc-free \
--hostname tru-cc-free \
--net="${TC_NETWORK}" \
--ip "${TC_IP}" \
-p :1521 \
--secret=oracle_pwd \
--secret=oracle_pwd_privkey \
--add-host="pri-db-free:${DB_IP}" \
-e TRUE_CACHE=true \
-e PRIMARY_DB_CONN_STR=${DB_IP}:1521/FREE \
-e PDB_TC_SVCS="FREEPDB1:sales1:sales1_tc;FREEPDB1:sales2:sales2_tc;FREEPDB1:sales3:sales3_tc;FREEPDB1:sales4:sales4_tc" \
-v ${TC_DATA_DIR}:/opt/oracle/oradata:Z --userns=keep-id \
container-registry.oracle.com/database/free:"${TAG}"

This command stars the True Cache instance, performing the necessary configuration steps automagically.

Wait a bit until you see both containers started and healthy:

[oracle@devobx ~]$ podman ps
CONTAINER ID  IMAGE                                                 COMMAND               CREATED        STATUS                  PORTS                              NAMES
920ebfc8ef66  container-registry.oracle.com/database/free:23.7.0.0  /bin/bash -c $ORA...  7 minutes ago  Up 7 minutes (healthy)  0.0.0.0:35213->1521/tcp, 1521/tcp  pri-db-free
de61c8cfcc8b  container-registry.oracle.com/database/free:23.7.0.0  /bin/bash -c $ORA...  7 minutes ago  Up 2 minutes (healthy)  0.0.0.0:38113->1521/tcp, 1521/tcp  tru-cc-free

Verification

If you tail the containers’ alert.logs, you’ll see that True Cache is initialised.

A quick check against the dictionary reveals the working True Cache configuration. Connecting against the True Cache instance you can see that for yourself:

select
  name,
  open_mode,
  database_role,
  controlfile_type
from
  v$database
/

NAME      OPEN_MODE            DATABASE_ROLE    CONTROLFIL
--------- -------------------- ---------------- ----------
FREE      READ ONLY WITH APPLY TRUE CACHE       TRUE CACHE

select
  true_cache_name,
  primary_name,
  status,
  remote_version
from
  v$true_cache
/

TRUE_CACHE_NAME                PRIMARY_NAME    STATUS               REMOTE_VERSION
------------------------------ --------------- -------------------- ------------------
FREE                           FREE            HEALTHY              23.0.0.0.0

Summary

This post describes how to set up True Cache using rootless Podman on Oracle Linux 9.4 x86-64. You can find out more about True Cache here:

Standard disclaimer: always make sure you’re correctly licensed to use Database features!