oracle / docker-images

Official source of container configurations, images, and examples for Oracle products and projects
https://developer.oracle.com/use-cases/#containers
Universal Permissive License v1.0
6.55k stars 5.43k forks source link

Database setup scripts are not executed with latest images on container first start #2644

Open valtrig opened 1 year ago

valtrig commented 1 year ago

I have been using the latest image for Oracle Database Free Release 23c which, according to the documentation in https://container-registry.oracle.com/, utilises a pre-built database instance for speeding up startup time. However, with this new startup procedure, it seems that when starting a new container, the scripts that I bind mount in volume /opt/oracle/scripts/setup are not being executed!

From what I understand, the issue is in this part of the code: https://github.com/oracle/docker-images/blob/a5688f13ae438f210d0ad13dedd366dbcfbdc8f9/OracleDatabase/SingleInstance/dockerfiles/23.2.0/runOracle.sh#L235 where the if statement checks whether the database instance already exists and, in that case, it skips the setup scripts, which are actually sourced in the else block below: https://github.com/oracle/docker-images/blob/a5688f13ae438f210d0ad13dedd366dbcfbdc8f9/OracleDatabase/SingleInstance/dockerfiles/23.2.0/runOracle.sh#L294

Are the setup scripts run only during the building of the Docker image, when this pre-built database is instantiated and, if so, is this by design? If this is the case, I believe it should be clearly stated in the documentation in order to avoid unnecessary frustration.

valtrig commented 1 year ago

For anyone interested, as a workaround, I've actually put my database setup Bash script in /opt/oracle/scripts/startup, which is sourced every time the container starts, as it should, and in order to ensure that the setup actions in the script will execute only the first time the container runs, I just check for the existence of a dummy "database initialised" indicator file that is created by the script in the user's home directory and, if it exists, the script just exits without further actions, as shown below:

#!/usr/bin/env bash

DB_INITIALISED="/opt/oracle/oradata/dbinit"
[ -f ${DB_INITIALISED} ] && exit
touch ${DB_INITIALISED}

# Do actual database setup stuff with sqlplus from this point onwards, e.g. sourcing any additional sql scripts!
AmedeeBulle commented 1 year ago

I went through the same path not so long ago...

If you build the container image yourself (using the Dockerfile from this repo), then it should work as documented. The first time you start a container, the database will be expanded and the startup script will run.

However, the image on the Oracle Container Registry is slightly different: the database is already expanded in the image which makes that the startup scripts won't run when a container is instantiated. The benefit of that is that it starts a bit faster at the expense of a larger container image (that is: the OCR image is larger than the one you would build yourself).

WRT your workaround, I would recommend to touch a file in /opt/oracle/oradata/ for persistence. /opt/oracle/oradata/ is typically a mounted volume, while the Oracle home isn't.

@gvenzl / @IshaanDesai45, if the above is expected behavior, can we update the README on OCR to make it clear that startup scripts aren't run on the pre-built image?

valtrig commented 1 year ago

WRT your workaround, I would recommend to touch a file in /opt/oracle/oradata/ for persistence. /opt/oracle/oradata/ is typically a mounted volume, while the Oracle home isn't.

Indeed, I've updated my comment accordingly, thanks for the tip!

greyseal96 commented 4 months ago

Sorry to necrobump this thread but I wanted to add some information that I found while testing. I came across the problem with the setup scripts not running and I was really frustrated by it so I read through the runOracle.sh script to see if I could figure out what the problem was. As @valtrig mentioned, that section of the script is the root cause of the problem but I found that, depending on how the oradata volume is mounted, the setup scripts will actually run.

First, this part of the documentation on the OCR site is important:

Mounting Docker volume/host directory for database persistence: To obtain database persistence, either a named Docker volume or a host system directory can be mounted at the location /opt/oracle/oradata inside the container. The difference between these two options are as follows:

  1. If a Docker volume is mounted on the /opt/oracle/oradata location, then the volume is prepopulated with the data files already present in the image. In this case, the startup will be very fast, similar to starting the image without mount. These data files exist in the image to enable quick startup of the database. To use a Docker volume for the data volume, run the following:

    $ docker run -d --name <oracle-db> -v <OracleDBData>:/opt/oracle/oradata container-registry.oracle.com/database/express:21.3.0-xe
  2. If a host system directory is mounted on the /opt/oracle/oradata location, then the data files already present at this location will be overwritten, and a new database setup will begin. It takes a significant amount of time (approximately 15 minutes) to set up a fresh database. To use a directory on the host system for the data volume, run the following:

    $ docker run -d --name <oracle-db> -v
    <writable_directory_path>:/opt/oracle/oradata
    container-registry.oracle.com/database/express:21.3.0-xe

Also, consider this from the Docker docs for volumes:

If you start a container which creates a new volume, and the container has files or directories in the directory to be mounted such as /app/, Docker copies the directory's contents into the volume. The container then mounts and uses the volume, and other containers which use the volume also have access to the pre-populated content.

So, on first startup, Docker is copying the database files over into the volume and, to the runOracle.sh script, it seems as if the files are already there and the database is set up so it goes into the if block.

On the other hand, if you use a file system mount, the database doesn't find the files there, and the runOracle.sh script goes into the else block, creates the database, and then runs the scripts in the setup mount.

So, tl;dr:

It was really helpful to read about the workaround that @valtrig came up with. Thanks!

It would be awesome if the documentation on the OCR pages for the express and free database images could get updated to include this information. it would've saved me several hours of testing/troubleshooting/frustration.

yunus-qureshi commented 4 months ago

Thanks. We will have the ReadMe updated

greyseal96 commented 4 months ago

@yunus-qureshi Thanks for the quick response time! Also, I just saw your answer in #2590 which says the same thing but much more succinctly. I wish I'd read that sooner hahaha. If you something like what you said in #2590 could be put in the documentation for any of the container images that it applies to it would be incredibly helpful. So far I've only tried the express and free repos so I can say that those need to have this note but I'm not sure if there are others that need it as well.

Thanks again for the quick response.