Coder Social home page Coder Social logo

docker-oracle's Introduction

docker-oracle

A repository of Docker image builds for creating Oracle databases. This repo replaces the other Docker repos I maintain. There were things I didn't like about the generally available build scripts that I wanted to improve on.

Use ARG Over ENV

Assigning build-specific variables as ARG instead of ENV means only variables necessary for the runtime environment are visible. Artifacts of the build process aren't passed to the container environmnent, reducing clutter and making it less obvious that this is a container.

Limit Duplication

I was tired of tweaking and managing multiple scripts for one version and then having to copy that change everywhere else. I'd rather have one master script for each activity—install Oracle, create a database, apply a patch, etc.—and manage version-specific exceptions there, than deal with multiple, nearly identical scripts under each version's subdirectory. It reduces duplication and redundant code, and makes it easier to manage and test changes.

There is one script to handle all operations, for all editions and versions. This adds some complexity to the script (it has to accommodate peculiarities of every version and edition) but:

  • For the most part these operations are identical across the board
  • One script in the root directory does everything and only one script needs maintenance
  • Version differences are all in one place vs. hidden in multiple files in parallel directories

The /opt/scripts/manageOracle.sh script manages all Oracle/Docker operations, from build through installation:

  • Configures the environment
  • Installs RPM
  • Installs the database
  • Creates the database
  • Starts and stops the database
  • Performs health checks

Limit Version-Specific Content

There are separate Dockerfiles and subdirectories for each version. I treat the Dockerfiles as configurations and use one script to read and apply the configurations, instead of maintaining version-specific scripts.

The Dockerfiles are nearly identical; in fact, building any version or edition of an Oracle database can be handled with a single Dockerfile by passing version-specific ARGs in the build. The reason I use separate Dockerfiles (Dockerfile.${VERSION}) is because of a limitation in Docker itself.

When running a (native) build, Docker scans the directory tree for files. If there are install and patch files in each of the version subdirectories, the context grows too large. The files and directories that Docker scans can be limited by using a .dockerignore file, but... there's only one .dockerignore and there's no option for specifying the ignore file. Building different versions requires changing the ignore file.

Using a buildkit and specifying a Dockerfile with a non-default name causes Docker to look for and respect ignore files with the same name as the Dockerfile that add the .dockerignore suffix. In this way, multiple (versioned) Dockerfiles allow custom ignore files that pass only context needed by the version.

Version Directory Structure

Each version has a subdirectory tree such as:

${VERSION}
└── install
    ├── Checksum
    ├── oracle-${VERSION}-${EDITION}.conf
    ├── dbca.rsp
    ├── inst.rsp
    ├── DATABASE.zip
    ├── DATABASE.rpm
    ├── p6880880_*.zip
    └── patches
        ├── 001
        │   └── patch1.zip
        └── 002
            └── patch2.zip
  • Checksum: md5 hash and file names for the database install and/or RPM files.
  • oracle-${VERSION}-${EDITION}.conf: RPM install configuration required for 11g and 18c XE installations.
  • dbca.rsp: Template response file for DBCA.
  • inst.rsp: Template response file for runInstall.
  • DATABASE.zip and/or DATABASE.rpm: Database installers. If an .rpm file is present, the RPM installation is used.
  • p6880880_*.zip: (Optional) OPatch file applied directly to ORACLE_HOME.
  • patches/*: (Optional) Subdirectories containing patch archives to be applied during database installation, one patch per subdirectory.

Flexible Image Creation

Each Dockerfile uses a set of common ARG values. Defaults are set in each Dockerfile but can be overridden by passing --build-arg values to docker build. This allows a single Dockerfile to accommodate a wide range of build options without changes to any files, including:

  • Removing specific components (APEX, SQL Developer, help files, etc) to minimize image size without editing scripts. It's easier to build images to include components that are normally be deleted. This is particularly useful for building images for testing 19c upgrades. APEX is included in the seed database but older APEX schemas have to be removed prior to a 19c upgrade. Where's the removal script? In the APEX directory, among those commonly removed to trim image size!
  • Add programs/binaries at build time as variables, rather than in a script. Hey, sometimes you want editors or strace or git, sometimes you don't. Set the defaults to your preferred set of binaries. Override them at build time as necessary, again without having to edit/revert any files.
  • Some database versions may require special RPM. Rather than maintaining that in scripts, it's in the Dockerfile (configuration).
  • Add supplemental RPMs. Some RPM have dependencies (such as rlwrap) that require a second execution of rpm install. All builds treat this the same way.
    • The RPM list includes tools for interactive use of containers.
    • Remove git, less, strace, tree, vi, which, and bash-completion for non-interactive environments
    • sudo is used to run installations from the manageOracle.sh script
  • All builds are multi-stage with identical steps, users and operations. Differences are handled by the management script by reading configuration information from the Dockerfile, discovered in the file structure, or set in the environment.
  • Customizing the directories for ORACLE_BASE, ORACLE_HOME, oraInventory, and the oradata directory.
  • Specify Read-Only Oracle Home (ROOH). Set ROOH=ENABLE in the Dockerfile, or pass --build-arg ROOH=ENABLE during build.

Install Oracle from Archive (ZIP) or RPM

RPM builds operate a little differently. They have a dependency on root because database configuration and startup is managed through /etc/init.d. The configuration is in /etc/sysconfig. If left at their default (I have a repo for building default RPM-based Oracle installations elsewhere) they need root and pose a security risk. I experimented with workarounds (adding oracle to sudoers, changing the /etc/init.d script group to oinstall, etc) but RPM-created databases still ran differently.

I use the RPM to create the Oracle software home, then discard what's in /etc/init.d and /etc/sysconfig and create and start the database "normally" using DBCA and SQLPlus.

This allows additional options for RPM-based installations, including changing the directory structure (for non-18c XE installs—the 18c XE home does not include libraries needed to recompile) and managing configuration through the same mechanism as "traditional" installations, meaning anything that can be applied to a "normal" install can be set in a RPM-based installation, without editing a different set of files in /etc/sysconfig and ORACLE_HOME. Express Edition on 18c (18.4) can be extended to use:

  • Custom SID (not stuck with XE)
  • Container or non-container
  • Custom PDB name(s)
  • Multiple PDB

Flexible Container Creation

I wanted images capable of running highly customizable database environments out of the gate, that mimic what's seen in real deployments. This includes running non-CDB databases, multiple pluggable databases, case-sensitive SID and PDB names, and custom PDB naming (to name a few). Database creation is controlled and customized by passing environment variables to docker run via -e VARIABLE=VALUE. Notable options include:

  • PDB_COUNT: Create non-container databases by setting this value to 0, or set the number of pluggable databases to be spawned.
  • CREATE_CONTAINER: Ture/false, an alternate method for creating a non-CDB database.
  • ORACLE_PDB: This is the prefix for the PDB's (when PDB_COUNT > 1) or the PDB_NAME (when PDB_COUNT=1, the default).
  • DB_UNQNAME: Set the database Unique Name. Default is ORACLE_SID; used mainly for creating containers used for Data Guard where the database and unique names are different, and avoids generating multiple diagnostic directory trees.
  • PDB_LIST: A comma-delimited list of PDB names. When present, overrides the PDB_COUNT and ORACLE_PDB values.
  • ORACLE_CHARACTERSET and ORACLE_NLS_CHARACTERSET: Set database character sets.
  • INIT_PARAMS: A list of parameters to set in the database at creation time. The default sets the DB_CREATE_FILE_DEST, DB_CREATE_ONLINE_LOG_DEST_1, and DB_RECOVERY_FILE_DEST to $ORADATA (enabling OMF) and turns off auditing.

DEBUG mode

Debug image builds, container creation, or container operation.

  • Use --build-arg DEBUG="bash -x" to debug image builds
  • Use -e DEBUG="bash -x" to debug container creation
  • Use export DEBUG="bash -x" to turn on debugging output in a running container
  • Use unset DEBUG to turn debugging off in a running container

Examples

Create a non-container database:
docker run -d -e PDB_COUNT=0 IMG_NAME
Create a container database with custom SID and PDB name:
docker run -d -e ORACLE_SID=mysid -e ORACLE_PDB=mypdb IMG_NAME
Create a container database with a default SID and three PDB named mypdb[1,2,3]:
docker run -d -e PDB_COUNT=3 -e ORACLE_PDB=mypdb IMG_NAME
Create a container database with custom SID and named PDB:
docker run -d -e ORACLE_SID=mydb -e PDB_LIST="test,dev,prod" IMG_NAME

TODO

  • Remove sudo option for building containers. It's only used during software installation and isn't required in final images.

docker-oracle's People

Contributors

oraclesean avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.