π³ Oracle 19c Database Deployment with Docker
Welcome to this comprehensive guide on deploying, configuring, and managing Oracle 19c Database using Docker containers. This blog will walk you through the entire process from setup to production best practices with practical code examples.
Docker provides an excellent way to run Oracle databases in isolated, portable containers, making it easy to deploy and manage Oracle 19c instances for development, testing, and production environments. This approach offers numerous benefits:
- π Isolation: Run Oracle in a containerized environment without affecting your host system
- π Portability: Easily move your database between different environments
- π Reproducibility: Quickly spin up identical database instances
- ⚡ Resource Efficiency: Use Docker's resource management capabilities to control CPU, memory, and storage
Let's dive in and see how to get Oracle 19c up and running in Docker!
π ️ 1. Prerequisites and Environment Setup
Before we start deploying Oracle 19c in Docker, let's verify that our system meets the necessary requirements. Oracle Database 19c is a resource-intensive application, so we need to ensure our Docker environment has adequate resources allocated.
Here's what you'll need:
- π Docker Installation: Docker Engine (Linux) or Docker Desktop (Windows/Mac)
- π» System Resources:
- At least 8GB RAM allocated to Docker
- Minimum 40GB free disk space
- 2 or more CPU cores
- π€ Oracle Account: For downloading the Oracle Database software
- π Internet Connection: For downloading required files and images
Let's check if Docker is properly installed and configured:
docker --version
# Check Docker system info (this will show resource limits and configuration)
docker info | grep -E 'CPUs|Memory|Docker Root Dir'
π¦ 2. Downloading and Preparing Oracle 19c Software
Oracle Database software isn't freely distributable, so we need to download it directly from Oracle's website. Follow these steps:
- Visit the Oracle Database Software Downloads page
- Navigate to the Oracle Database 19c section
- Download the "Oracle Database 19c (19.3) for Linux x86-64" ZIP file
- Accept the license agreement and sign in with your Oracle account
- Save the downloaded file (e.g., LINUX.X64_193000_db_home.zip) to your working directory
Next, we'll need the Docker build files from Oracle's GitHub repository:
git clone https://github.com/oracle/docker-images.git
# Navigate to the Oracle Database dockerfiles directory
cd docker-images/OracleDatabase/SingleInstance/dockerfiles
# List contents to verify correct structure
ls -la
π️ 3. Building the Oracle 19c Docker Image
Now that we have the Oracle Docker build files and the Oracle 19c software, we need to:
- Copy the Oracle ZIP file to the correct version directory
- Run the build script to create the Docker image
- Verify that the image was created successfully
Let's execute these steps:
mkdir -p ~/docker-images/OracleDatabase/SingleInstance/dockerfiles/19.3.0
# Copy the Oracle Database ZIP file to the version directory
# Note: Replace ~/Downloads with your actual download location
cp ~/Downloads/LINUX.X64_193000_db_home.zip ~/docker-images/OracleDatabase/SingleInstance/dockerfiles/19.3.0/
# Navigate to the dockerfiles directory
cd ~/docker-images/OracleDatabase/SingleInstance/dockerfiles/
# Run the build script with options:
# -v 19.3.0: Specifies the Oracle version
# -e: Creates an Enterprise Edition image
# -i: Ignores MD5 checksum verification
./buildContainerImage.sh -v 19.3.0 -e -i
⏱️ Note: The build process will take some time (typically 15-30 minutes depending on your system's performance). The script will:
- Create a base image using Oracle Linux
- Install required dependencies
- Set up the Oracle environment
- Configure the database software
Once the build is complete, let's verify that the image was created successfully:
docker images | grep oracle/database
# Get detailed information about the Oracle Database image
docker inspect oracle/database:19.3.0-ee | jq '.[0].Config.Env, .[0].Config.ExposedPorts'
▶️ 4. Running and Connecting to the Oracle Container
Now that we have successfully built the Oracle 19c Docker image, we can create and run a container based on it. Let's break down the process:
- Create and start the Oracle container with appropriate parameters
- Monitor the container logs to track the database creation progress
- Connect to the database using different methods
π Running the Oracle 19c Container
# Oracle container runs as user with UID 54321 (oracle user)
sudo mkdir -p /opt/oracle/oradata
sudo chown -R 54321:54321 /opt/oracle/oradata
sudo chmod -R 775 /opt/oracle/oradata
# Now run the Oracle 19c container
docker run --name oracle19c \
--shm-size=1g \
-p 1521:1521 -p 5500:5500 \
-e ORACLE_SID=ORCLCDB \
-e ORACLE_PDB=ORCLPDB1 \
-e ORACLE_PWD=Oracle_123# \
-v /opt/oracle/oradata:/opt/oracle/oradata \
-d oracle/database:19.3.0-ee
# Check that the container is running
docker ps | grep oracle19c
Let's understand the parameters we used:
- --name oracle19c: Names the container "oracle19c" for easy reference
- --shm-size=1g: Sets shared memory to 1GB (Oracle needs this for performance)
- -p 1521:1521: Maps the Oracle listener port from container to host
- -p 5500:5500: Maps the Enterprise Manager Express port
- -e ORACLE_SID=ORCLCDB: Sets the Oracle System Identifier
- -e ORACLE_PDB=ORCLPDB1: Sets the Pluggable Database name
- -e ORACLE_PWD=Oracle_123#: Sets the password for admin accounts
- -v /opt/oracle/oradata:/opt/oracle/oradata: Maps host directory for persistent storage
- -d: Runs the container in detached mode (background)
π Monitoring the Database Creation Progress
# Press Ctrl+C to stop following the logs
docker logs -f oracle19c
When the database creation is complete, you'll see the message DATABASE IS READY TO USE! in the logs. At this point, we can connect to the database using different methods.
π Connecting to the Oracle Database
Let's explore three methods to connect to the Oracle database:
π» Method 1: Using SQL*Plus inside the container
docker exec -it oracle19c sqlplus sys/Oracle_123#@ORCLCDB as sysdba
# Connect to the PDB (Pluggable Database)
docker exec -it oracle19c sqlplus system/Oracle_123#@ORCLPDB1
# Run a simple query non-interactively to test the connection
docker exec -it oracle19c sqlplus -S system/Oracle_123#@ORCLPDB1 << EOF
SELECT instance_name, status, database_status FROM v\$instance;
SELECT name, open_mode FROM v\$pdbs;
EXIT;
EOF
π₯️ Method 2: Using SQL Developer or other client tools
You can also connect to your Oracle database from outside the container using SQL Developer or any other Oracle client tool. Here are the connection details:
- Hostname: localhost (or your server IP)
- Port: 1521
- Service Name: ORCLPDB1 (for the PDB)
- Username: system (or any other Oracle user)
- Password: Oracle_123# (the password set when creating the container)
The connection string format is: localhost:1521/ORCLPDB1
π Method 3: Using Oracle Enterprise Manager Express
Oracle Enterprise Manager Express provides a web-based interface for database administration:
- URL: https://localhost:5500/em
- Username: system
- Password: Oracle_123#
- Container: ORCLPDB1
π Note: The first time you connect, your browser might show a security warning about the self-signed certificate. You can safely proceed.
π ️ 5. Managing the Oracle 19c Container
Now that we have our Oracle 19c database running in a Docker container, let's look at the common operations for managing the container:
docker ps -a | grep oracle19c
# Stop the container (graceful shutdown)
docker stop oracle19c
# Start the container (after it's been stopped)
docker start oracle19c
# Restart the container
docker restart oracle19c
# Check container logs (useful for troubleshooting)
docker logs --tail 50 oracle19c
# Check container resource utilization
docker stats oracle19c --no-stream
# Execute a command in the running container
docker exec -it oracle19c ps -ef | grep pmon
π️ Removing the Oracle Container and Image
docker stop oracle19c
# Remove the container
docker rm oracle19c
# Remove the image (optional - only if you want to completely remove)
docker rmi oracle/database:19.3.0-ee
# Verify the container and image are removed
docker ps -a | grep oracle19c
docker images | grep oracle/database
⚙️ 6. Advanced Oracle Docker Configuration
Now that we have a basic Oracle 19c database running in Docker, let's explore some advanced configuration options:
π§ Custom Database Parameters
mkdir -p ~/oracle_custom
cat > ~/oracle_custom/init.ora << EOF
# Memory parameters
memory_target=4G
memory_max_target=4G
pga_aggregate_target=1G
sga_target=3G
# Process and connection parameters
processes=300
sessions=600
open_cursors=500
# Other optimization parameters
db_writer_processes=2
job_queue_processes=10
EOF
# Run a new container with the custom init.ora file
docker run --name oracle19c_custom \
--shm-size=1g \
-p 1521:1521 -p 5500:5500 \
-e ORACLE_SID=ORCLCDB \
-e ORACLE_PDB=ORCLPDB1 \
-e ORACLE_PWD=Oracle_123# \
-v /opt/oracle/oradata:/opt/oracle/oradata \
-v ~/oracle_custom/init.ora:/opt/oracle/product/19c/dbhome_1/dbs/init.ora \
-d oracle/database:19.3.0-ee
π Running Custom Scripts on Database Creation or Startup
mkdir -p ~/oracle_scripts/setup ~/oracle_scripts/startup
# Create a setup script to create a user and tables
cat > ~/oracle_scripts/setup/01_create_user.sql << EOF
-- Create a new application user
CREATE USER app_user IDENTIFIED BY "AppPass123#";
GRANT CONNECT, RESOURCE TO app_user;
ALTER USER app_user QUOTA UNLIMITED ON USERS;
-- Create a sample table
CREATE TABLE app_user.employees (
employee_id NUMBER PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50),
email VARCHAR2(100),
hire_date DATE,
department VARCHAR2(50)
);
-- Insert sample data
INSERT INTO app_user.employees VALUES (1, 'John', 'Doe', 'john.doe@example.com', SYSDATE-365, 'IT');
INSERT INTO app_user.employees VALUES (2, 'Jane', 'Smith', 'jane.smith@example.com', SYSDATE-180, 'HR');
COMMIT;
EXIT;
EOF
# Create a startup script to check database status on each startup
cat > ~/oracle_scripts/startup/01_check_status.sql << EOF
-- Show tablespace usage on every startup
SELECT
tablespace_name,
ROUND(used_space * 8192 / 1024 / 1024, 2) AS used_mb,
ROUND(tablespace_size * 8192 / 1024 / 1024, 2) AS total_mb,
ROUND(used_percent, 2) AS used_pct
FROM dba_tablespace_usage_metrics;
-- Show any locked objects
SELECT * FROM dba_blockers;
EXIT;
EOF
# Run a new container with our custom scripts
docker run --name oracle19c_scripts \
--shm-size=1g \
-p 1522:1521 -p 5501:5500 \
-e ORACLE_SID=ORCLCDB \
-e ORACLE_PDB=ORCLPDB1 \
-e ORACLE_PWD=Oracle_123# \
-v /opt/oracle/oradata2:/opt/oracle/oradata \
-v ~/oracle_scripts/setup:/opt/oracle/scripts/setup \
-v ~/oracle_scripts/startup:/opt/oracle/scripts/startup \
-d oracle/database:19.3.0-ee
π Using Docker Compose for Oracle 19c
mkdir -p ~/oracle_compose/scripts/{setup,startup}
# Copy our scripts to the project directory
cp ~/oracle_scripts/setup/* ~/oracle_compose/scripts/setup/
cp ~/oracle_scripts/startup/* ~/oracle_compose/scripts/startup/
# Create the docker-compose.yml file
cat > ~/oracle_compose/docker-compose.yml << EOF
version: '3'
services:
oracle19c:
image: oracle/database:19.3.0-ee
container_name: oracle19c_compose
ports:
- "1521:1521"
- "5500:5500"
environment:
- ORACLE_SID=ORCLCDB
- ORACLE_PDB=ORCLPDB1
- ORACLE_PWD=Oracle_123#
- ORACLE_CHARACTERSET=AL32UTF8
volumes:
- oracle_data:/opt/oracle/oradata
- ./scripts/setup:/opt/oracle/scripts/setup
- ./scripts/startup:/opt/oracle/scripts/startup
healthcheck:
test: ["CMD", "sqlplus", "-L", "sys/Oracle_123#@//localhost:1521/ORCLCDB as sysdba", "< /dev/null"]
interval: 30s
timeout: 10s
retries: 5
start_period: 40m
restart: unless-stopped
shm_size: 1g
volumes:
oracle_data:
driver: local
EOF
# Navigate to the project directory
cd ~/oracle_compose
# Start the Oracle 19c container in the background
docker-compose up -d
# Check the status of our container
docker-compose ps
Key components of this Docker Compose file:
- πΌ️ Image: Specifies the Oracle 19c Enterprise Edition image
- π Ports: Maps container ports 1521 and 5500 to the host
- ⚙️ Environment: Sets Oracle database parameters
- πΎ Volumes: Maps persistent storage and custom scripts
- π©Ί Healthcheck: Verifies database availability
- π Restart Policy: Automatically restarts the container if it fails
- π§ Shared Memory: Allocates 1GB shared memory for performance
Docker Compose commands for managing the container:
docker-compose logs -f
# Stop the container
docker-compose stop
# Start the container
docker-compose start
# Restart the container
docker-compose restart
# Stop and remove the container (data is preserved in the named volume)
docker-compose down
# Stop and remove the container AND volumes (will delete all data)
docker-compose down -v
πΎ 7. Backup Strategies for Oracle 19c in Docker
Regardless of whether you're using Docker for development, testing, or production, backing up your Oracle database is essential. Let's explore three backup strategies:
πΌ Using RMAN for Database Backup
mkdir -p ~/oracle_backups/rman
sudo chown -R 54321:54321 ~/oracle_backups
# Create a directory in the container for backups
docker exec -it oracle19c mkdir -p /opt/oracle/backups
# Create an RMAN backup script
cat > ~/oracle_backups/backup_db.rman << EOF
CONFIGURE CONTROLFILE AUTOBACKUP ON;
CONFIGURE BACKUP OPTIMIZATION ON;
CONFIGURE DEVICE TYPE DISK BACKUP TYPE TO COMPRESSED BACKUPSET;
BACKUP AS COMPRESSED BACKUPSET DATABASE PLUS ARCHIVELOG;
BACKUP CURRENT CONTROLFILE;
EXIT;
EOF
# Copy the backup script to the container
docker cp ~/oracle_backups/backup_db.rman oracle19c:/opt/oracle/backups/
# Run RMAN backup inside the container
docker exec -it oracle19c bash -c "
export ORACLE_SID=ORCLCDB
rman target / cmdfile=/opt/oracle/backups/backup_db.rman log=/opt/oracle/backups/rman_backup.log
"
# Check the backup log
docker exec -it oracle19c cat /opt/oracle/backups/rman_backup.log
π¦ Docker Volume Backup
docker stop oracle19c_compose
# Create a backup directory if it doesn't exist
mkdir -p ~/oracle_backups/volume
# Create a backup of the Docker named volume
# This uses an Alpine Linux container that mounts the source volume and a backup directory
docker run --rm \
-v oracle_data:/source \
-v ~/oracle_backups/volume:/backup \
alpine sh -c "cd /source && tar czf /backup/oracle_volume_$(date +%Y%m%d).tar.gz ."
# Start the Oracle container again
docker start oracle19c_compose
# Verify the backup file was created
ls -lh ~/oracle_backups/volume/
π️ Oracle Data Pump Export
docker exec -it oracle19c mkdir -p /opt/oracle/dumps
# Create a directory object in the database
docker exec -it oracle19c bash -c "
echo \"
CREATE OR REPLACE DIRECTORY data_pump_dir AS '/opt/oracle/dumps';
GRANT READ, WRITE ON DIRECTORY data_pump_dir TO system;
EXIT;
\" | sqlplus sys/Oracle_123# AS SYSDBA
"
# Export the entire ORCLPDB1 database using Data Pump
docker exec -it oracle19c bash -c "
expdp system/Oracle_123#@ORCLPDB1 \
DIRECTORY=data_pump_dir \
DUMPFILE=orclpdb1_full_$(date +%Y%m%d).dmp \
LOGFILE=orclpdb1_full_$(date +%Y%m%d).log \
FULL=YES
"
# Create a directory on the host for storing the exported files
mkdir -p ~/oracle_backups/datapump
# Copy the exported files from the container to the host
docker cp oracle19c:/opt/oracle/dumps/orclpdb1_full_$(date +%Y%m%d).dmp ~/oracle_backups/datapump/
docker cp oracle19c:/opt/oracle/dumps/orclpdb1_full_$(date +%Y%m%d).log ~/oracle_backups/datapump/
# Verify the exported files
ls -lh ~/oracle_backups/datapump/
⚡ 8. Performance Tuning for Oracle 19c Docker
π Docker Resource Allocation
docker run --name oracle19c_perf \
--cpus=4 \
--memory=8g \
--memory-swap=12g \
--memory-reservation=6g \
--shm-size=2g \
--blkio-weight=800 \
--device-read-bps /dev/sda:100mb \
--device-write-bps /dev/sda:100mb \
-p 1523:1521 -p 5502:5500 \
-e ORACLE_SID=ORCLCDB \
-e ORACLE_PDB=ORCLPDB1 \
-e ORACLE_PWD=Oracle_123# \
-v /opt/oracle/oradata3:/opt/oracle/oradata \
-d oracle/database:19.3.0-ee
Let's understand these resource allocation flags:
- --cpus=4: Limits the container to use 4 CPU cores
- --memory=8g: Allocates 8GB of RAM to the container
- --memory-swap=12g: Sets swap limit to 12GB (8GB RAM + 4GB swap)
- --memory-reservation=6g: Soft limit that ensures at least 6GB is available
- --shm-size=2g: Allocates 2GB for shared memory (/dev/shm)
- --blkio-weight=800: I/O weight relative to other containers (default is 500)
- --device-read-bps, --device-write-bps: Limits disk I/O throughput
π§ Oracle Memory Parameter Tuning
docker exec -it oracle19c_perf sqlplus -S sys/Oracle_123# as sysdba << EOF
SET LINESIZE 200
COLUMN name FORMAT a40
COLUMN value FORMAT a15
COLUMN description FORMAT a60
SELECT name, value, description
FROM v\$parameter
WHERE name IN ('memory_target', 'memory_max_target', 'sga_target', 'pga_aggregate_target');
EXIT;
EOF
# Adjust memory parameters to optimal values
docker exec -it oracle19c_perf sqlplus -S sys/Oracle_123# as sysdba << EOF
-- Set memory parameters
ALTER SYSTEM SET memory_max_target=6G SCOPE=SPFILE;
ALTER SYSTEM SET memory_target=6G SCOPE=SPFILE;
ALTER SYSTEM SET sga_target=4G SCOPE=SPFILE;
ALTER SYSTEM SET pga_aggregate_target=2G SCOPE=SPFILE;
-- Set other performance parameters
ALTER SYSTEM SET db_writer_processes=2 SCOPE=SPFILE;
ALTER SYSTEM SET open_cursors=500 SCOPE=SPFILE;
ALTER SYSTEM SET processes=500 SCOPE=SPFILE;
ALTER SYSTEM SET sessions=800 SCOPE=SPFILE;
ALTER SYSTEM SET job_queue_processes=20 SCOPE=SPFILE;
-- Restart the database for changes to take effect
SHUTDOWN IMMEDIATE;
STARTUP;
-- Verify the new settings
SELECT name, value
FROM v\$parameter
WHERE name IN ('memory_target', 'memory_max_target', 'sga_target', 'pga_aggregate_target');
EXIT;
EOF
π½ Storage Configuration for Performance
docker volume create oracle_data_files
docker volume create oracle_redo_logs
docker volume create oracle_arch_logs
# Run Oracle with separate volumes for different file types
docker run --name oracle19c_storage \
--shm-size=1g \
-p 1524:1521 -p 5503:5500 \
-e ORACLE_SID=ORCLCDB \
-e ORACLE_PDB=ORCLPDB1 \
-e ORACLE_PWD=Oracle_123# \
-v oracle_data_files:/opt/oracle/oradata \
-v oracle_redo_logs:/opt/oracle/redologs \
-v oracle_arch_logs:/opt/oracle/archlogs \
-d oracle/database:19.3.0-ee
π 9. Troubleshooting Common Oracle Docker Issues
π« Permission Errors
echo "Cannot create directory \"/opt/oracle/oradata/ORCLCDB\"."
echo "mkdir: cannot create directory '/opt/oracle/oradata/dbconfig': Permission denied"
# Solution 1: Set the correct ownership and permissions
sudo mkdir -p /opt/oracle/oradata
sudo chown -R 54321:54321 /opt/oracle/oradata # Oracle container uses UID 54321
sudo chmod -R 775 /opt/oracle/oradata
# Solution 2: Use Docker named volumes instead of bind mounts
docker volume create oracle_data
docker volume inspect oracle_data
# Then run your container with the named volume
docker run --name oracle19c_named_vol \
--shm-size=1g \
-p 1525:1521 -p 5504:5500 \
-e ORACLE_SID=ORCLCDB \
-e ORACLE_PDB=ORCLPDB1 \
-e ORACLE_PWD=Oracle_123# \
-v oracle_data:/opt/oracle/oradata \
-d oracle/database:19.3.0-ee
❓ Missing Installation Files
echo 'ERROR: failed to solve: failed to compute cache key: "/LINUX.X64_193000_db_home.zip": not found'
# Solution: Copy the Oracle ZIP file to the correct location
cp ~/Downloads/LINUX.X64_193000_db_home.zip ~/docker-images/OracleDatabase/SingleInstance/dockerfiles/19.3.0/
π Database Connectivity Problems
echo 'ORA-12541: TNS:no listener'
echo 'ORA-01033: ORACLE initialization or shutdown in progress'
# Solution 1: Check if database initialization has completed
docker logs oracle19c | grep "DATABASE IS READY TO USE"
# Solution 2: Check if the Oracle listener is running
docker exec -it oracle19c bash -c "lsnrctl status"
# Solution 3: Check Oracle alert log for errors
docker exec -it oracle19c bash -c "cat /opt/oracle/diag/rdbms/orclcdb/ORCLCDB/trace/alert_ORCLCDB.log | tail -100"
# Solution 4: Check if the database is open
docker exec -it oracle19c sqlplus -S sys/Oracle_123# as sysdba << EOF
SELECT instance_name, status, database_status FROM v\$instance;
SELECT name, open_mode FROM v\$pdbs;
EXIT;
EOF
✅ 10. Verifying Oracle Database Startup and Connectivity
echo "=== Checking container status ==="
docker ps | grep oracle19c
# 2. Check Oracle processes inside the container
echo -e "\n=== Checking Oracle processes ==="
docker exec -it oracle19c bash -c "ps -ef | grep pmon"
docker exec -it oracle19c bash -c "ps -ef | grep tns"
# 3. Verify the Oracle listener status
echo -e "\n=== Checking Oracle listener status ==="
docker exec -it oracle19c bash -c "lsnrctl status"
# 4. Check instance status and open mode
echo -e "\n=== Checking database status ==="
docker exec -it oracle19c sqlplus -S sys/Oracle_123# as sysdba << EOF
SET LINESIZE 200
COLUMN name FORMAT a15
COLUMN open_mode FORMAT a15
SELECT instance_name, status, database_status FROM v\$instance;
SELECT name, open_mode FROM v\$pdbs;
EXIT;
EOF
# 5. Test database connectivity from inside the container
echo -e "\n=== Testing SQL connectivity inside container ==="
docker exec -it oracle19c sqlplus -S system/Oracle_123#@ORCLPDB1 << EOF
SELECT SYSDATE FROM dual;
EXIT;
EOF
π Conclusion
In this comprehensive guide, we've covered everything you need to know about deploying, configuring, and managing Oracle 19c Database using Docker:
- π️ Setting up the environment and building the Oracle 19c Docker image
- π Running the container with appropriate configuration
- π Connecting to the database using various methods
- ⚙️ Advanced configuration with custom parameters and scripts
- π Using Docker Compose for easier management
- πΎ Backing up the database using different strategies
- ⚡ Performance tuning for optimal operation
- π Troubleshooting common issues and verifying proper operation
Using Docker for Oracle Database deployment offers tremendous advantages in terms of:
- π Consistency: The same environment across development, testing, and production
- π Portability: Easy to move databases between different hosts
- π Isolation: No conflicts with other applications or databases
- ⚖️ Resource Control: Fine-grained allocation of CPU, memory, and I/O
- π€ Automation: Simple scripting and integration with CI/CD pipelines
π Remember that official Oracle license terms still apply to containerized deployments. For production use, ensure that you have proper Oracle licenses and follow the best practices for security, high availability, and monitoring.
π Happy containerizing!
Comments
Post a Comment