Oracle 19c on Docker: Install Oracle via RPM (Part I)
This is the first in a multi-part series on building Docker images for Oracle 19c. In this first part I show how to create a Dockerfile to build images that use the Oracle 19c RPM instead of the “traditional” method where the Oracle Home is unzipped into a target directory. I’ll also demonstrate how to apply a Release Update (RU) to the Oracle Home during the image build to produce a native Oracle 19.7 or 19.8 database.
In the next installment I cover some of the other unique requirements for running Docker images that use the RPM-based installation. In the third part I describe a method to merge multiple images together, creating containers with a low-version Oracle home and database (11g, 12c, 18c) running alongside a preconfigured 19c database home, ready for testing and practicing upgrades to Oracle 19c!
Building images that take advantage of the RPM installer requires a departure from the builds offered in Oracle’s Docker repository. Installing and creating a database is handled differently. Database creation, for example, is addressed in an init script installed as part of the RPM itself, so there’s no need for createDB.sh
. The installation response files and template response file aren’t needed, nor is a script to install the database binaries (at least the way I do it).
Let’s dig in, shall we?
For my builds I manage the environment in the Dockerfile a little differently. I prefer a clean environment for containers so I take advantage of Docker’s ARG
to set values within the build instead of persisting them in the container’s environment. Using ARG
also allows users to pass values when running a container to provide more flexibility and customization in the resulting environment.
FROM oraclelinux:7-slim as base MAINTAINER Sean Scott <sean.scott@viscosityna.com> # Set ARGs, keep the environment clean ARG ORACLE_BASE=/opt/oracle ARG ORACLE_HOME=/opt/oracle/product/19c/dbhome_1 ARG INSTALL_DIR=/opt/install ARG ORACLE_SID=ORCLCDB # ORACLE_DOCKER_INSTALL=true is required for the 19c RPM on Docker ENV ORACLE_BASE=$ORACLE_BASE \ ORACLE_HOME=$ORACLE_HOME \ ORACLE_SID=$ORACLE_SID \ ORACLE_VERSION=19c \ PDB_NAME=ORCLPDB \ PDB_COUNT=1 \ ORACLE_DOCKER_INSTALL=true \ SQLPATH=/home/oracle \ SETUP_DB=setupDB.sh \ RUN_FILE=runOracle.sh \ CONFIG_FILE=oracledb_ORCLCDB-19c.conf \ INIT_FILE=oracledb_ORCLCDB-19c \ CHECK_DB_STATUS=checkDBStatus.sh ENV PATH=$ORACLE_HOME/bin:$ORACLE_HOME/OPatch/:/usr/sbin:$PATH \ CLASSPATH=$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib \ LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib \ TNS_ADMIN=$ORACLE_HOME/network/admin
If you’re not already familiar with multi-stage builds, the FROM
/ as
syntax tells Docker to create an intermediate image called base
that will be used in subsequent steps. Creating a base image provides greater freedom to manipulate things later and also helps reduce image size. (An Oracle 19.7 image, built without multiple stages, is around 13GB. Using multiple stages it’s 9.3GB. Oracle 19.8 is 16.3GB and 9.5GB respectively.)
Note that I’m using ARG
to set a default value for ORACLE_BASE
, ORACLE_HOME
and ORACLE_SID
, then using these in the ENV
setup. When running a container I can pass a custom value for any of these variables using the -e
option.
The RPM installation expects some values including ORACLE_VERSION
and ORACLE_DOCKER_INSTALL
. Customizing the database means I also need to manipulate the configuration and initialization files set in CONFIG_FILE
and INIT_FILE
.
For those worried that all these extra lines will add layers to the image, don’t fret. They do create steps but not layers and add nothing to the size of the image itself.
Next I’m copying files to the ORACLE_BASE
:
COPY $CHECK_DB_STATUS $SETUP_DB $RUN_FILE $ORACLE_BASE/
There’s nothing remarkable happening here, besides a much smaller file count!
The next step does nearly all of the OS configuration. I also add some packages I like:
# Build base image with 19c preinstall and Things I Like To Have (epel, git, less, rlwrap, strace, vi), all optional. # file-5.11, openssl, sudo are necessary (file-5.11 = prereq for 19c RPM, sudo for startup via init.d) RUN yum -y update; yum -y install oracle-database-preinstall-19c oracle-epel-release-el7 file-5.11-36.el7.x86_64 git less openssl strace sudo vi which && \ # Create directories, replace OPatch, own things, permissions mkdir -p && \ chown -R oracle:oinstall $ORACLE_BASE $INSTALL_DIR && \ chmod ug+x $ORACLE_BASE/*.sh && \ sync && \ yum -y install rlwrap && \ # Create the entrypoint: ln -s $ORACLE_BASE/scripts /docker-entrypoint-initdb.d && \ # Manage the oracle user: echo oracle:oracle | chpasswd && \ # Let oracle run rpm config: echo "oracle ALL=(root) NOPASSWD:ALL" > /etc/sudoers.d/oracle && \ chmod 0440 /etc/sudoers.d/oracle && \ yum clean all && \ rm -fr $INSTALL_DIR /tmp/* /var/cache/yum
The 19c preinstallation RPM adds the oracle
user and groups, after which I create directories and set ownership.
The most interesting thing is probably adding oracle
to the sudoers
list. With an RPM installation the configuration and initialization is performed by the root
user. Giving oracle
unlimited sudo privileges is simpler than narrowing things to specific commands and it’s convenient for containers I use in my personal environment.
The preceding stage in this multi-stage build created the base image. The next stage installs Oracle, updates OPatch, and applies a Release Update. As before, it begins with a FROM
and sets some ARG
values:
FROM base as builder ARG DBRPM=oracle-database-ee-19c-1.0-1.x86_64.rpm ARG DBRU=p31281355_190000_Linux-x86-64.zip ARG DBRU_ID=31281355 ARG OPATCH=p6880880_190000_Linux-x86-64.zip ARG INSTALL_DIR=/opt/install
The RPM and patch files are copied to the image:
COPY --chown=oracle:oinstall $DBRPM $DBRU $OPATCH $INSTALL_DIR/
Next, root
installs Oracle from the RPM and sets ownership and permissions for two files:
USER root RUN yum -y localinstall $INSTALL_DIR/oracle-database-ee-19c-1.0-1.x86_64.rpm && \ # Make the config file editable by oracle: chown root:oinstall /etc/sysconfig/$CONFIG_FILE /etc/init.d/$INIT_FILE && \ chmod 664 /etc/sysconfig/$CONFIG_FILE
As noted above, the configuration and initialization files are special files needed for this installation method. The configuration file is just that—configuration information used during database creation. The initialization file is used by the Linux init
process to start the database and listener.
With the database software installed we can proceed to update OPatch and apply the Release Update:
USER oracle RUN unzip -oq -d $ORACLE_HOME $INSTALL_DIR/$OPATCH && \ unzip -oq -d $INSTALL_DIR $INSTALL_DIR/$DBRU && \ # Apply the RU $ORACLE_HOME/OPatch/opatch apply -silent $INSTALL_DIR/$DBRU_ID && \ rm -fr $INSTALL_DIR/*
It’s not technically necessary to remove the contents of the installation directory but old habits, as they say!
This concludes the second stage. At this point the build has created two images, base and builder, that will be combined to create the final image. As you might expect, this begins by starting with the base image and setting some environment variables:
FROM base ENV ORACLE_BASE=$ORACLE_BASE \ ORACLE_HOME=$ORACLE_HOME \ ORACLE_SID=$ORACLE_SID \ ORACLE_VERSION=19c \ PDB_NAME=ORCLPDB \ PDB_COUNT=1 \ ORACLE_DOCKER_INSTALL=true \ INSTALL_TMP=Docker_Database.dbc \ SETUP_DB=setupDB.sh \ RUN_FILE=runOracle.sh \ CONFIG_FILE=oracledb_ORCLCDB-19c.conf \ INIT_FILE=oracledb_ORCLCDB-19c \ CHECK_DB_STATUS=checkDBStatus.sh ENV PATH=$ORACLE_HOME/bin:$ORACLE_HOME/OPatch/:/usr/sbin:$PATH \ CLASSPATH=$ORACLE_HOME/jlib:$ORACLE_HOME/rdbms/jlib \ LD_LIBRARY_PATH=$ORACLE_HOME/lib:/usr/lib \ TNS_ADMIN=$ORACLE_HOME/network/admin
This is followed by copying the ORACLE_BASE
directory from the builder image and setting its ownership to oracle:oinstall
, the /etc
directory that includes the init and config files added by the RPM installation, and copying a database configuration template into the DBCA template directory under the ORACLE_HOME
:
USER oracle COPY --chown=oracle:oinstall --from=builder $ORACLE_BASE $ORACLE_BASE COPY --from=builder /etc /etc COPY --chown=oracle:oinstall $INSTALL_TMP $ORACLE_HOME/assistants/dbca/templates/
This template replaces the response file you may be familiar with from running DBCA “normally.” More on that in the second part of this blog.
The final section should be familiar and remains effectively the same as the builds provided in the Oracle Docker repo:
WORKDIR /home/oracle VOLUME ["$ORACLE_BASE/oradata"] EXPOSE 1521 5500 HEALTHCHECK --interval=1m --start-period=5m \ CMD "$ORACLE_BASE/$CHECK_DB_STATUS" >/dev/null || exit 1 # Define default command to start Oracle Database. CMD exec $ORACLE_BASE/$RUN_FILE
This sets the working directory, exposes container resources (ports and mount point), initiates the health check, and executes the run file.
In the next installment I cover the remaining files and tweaks needed to run an RPM build. All files for this build are available in my GitHub repository.
All files for this build are available in my GitHub repository.
This sets the working directory, exposes container resources (ports and mount point), initiates the health check, and executes the run file.
In the next installment I cover the remaining files and tweaks needed to run an RPM build. All files for this build are available in my GitHub repository.
Comments