Reputation: 5921
As the title says: how do I check if Oracle is up in Docker? Now my app tries to create a Hibernate session and I'm getting
ERROR :
ORA-01033: ORACLE initialization or shutdown in progress
So I would like some kind of health check having url only. Is that possible? Thank you!
Upvotes: 14
Views: 10401
Reputation: 16564
The following script worked for me for docker 24.0.2 + oracle 11g
First create this script: /opt/oracle/oracle_health_check.sh
#!/bin/bash
#change 'system/changeme' with your credentials or use env variables
query_validation_response=$(echo "select 'true' as status from dual;" | sqlplus -s system/changeme@localhost:1521/xe)
if [[ "${query_validation_response,,}" == *"error"* ]]; then
#failed
exit 1;
else
#connection was success
exit 0;
fi;
Don't forget execution permissions
chmod +x /opt/oracle/oracle_health_check.sh
Usage:
./opt/oracle/oracle_health_check.sh
Result if database is ready to use:
Result if database is offline:
Usage with docker-compose yaml:
healthcheck:
test: [ "CMD", "/opt/oracle/oracle_health_check.sh"]
interval: 2s
select 1 from dual
is used as query validationsqlplus error stdout sample
ERROR:
ORA-12514: TNS:listener does not currently know of service requested in connect
descriptor
SP2-0306: Invalid option.
Usage: CONN[ECT] [{logon|/|proxy} [AS {SYSDBA|SYSOPER|SYSASM}] [edition=value]]
where <logon> ::= <username>[/<password>][@<connect_identifier>]
<proxy> ::= <proxyuser>[<username>][/<password>][@<connect_identifier>]
sqlplus success stdout sample
STAT
----
true
Upvotes: 0
Reputation: 5365
For Windows Oracle containers, unfortunate checkDBStatus.sh isn't available so here's how I did it.
Create a file called C:\scripts\healthcheck.ps1
as follows, replaced the password and SID with your own. You should probably use a different user with less privileges and select 1 from dual
or whatever. The idea is that it should return 0 when Oracle is ready to accept a connection, otherwise it should return 1.
# Healthcheck script that returns 0 if Oracle is ready to accept connections, else returns 1
$chekdbsql = "`nselect status from v`$instance;"
$chkdb = ""
$chkdb = ($chekdbsql | cmd /c "sqlplus sys/password@localhost/ora193 as sysdba")
if ($chkdb.Contains("OPEN") -eq 'True'){
exit 0
}
else {
exit 1
}
Add this line to Oracle DB Dockerfile
:
HEALTHCHECK --interval=10s --timeout=10s --retries=20 CMD powershell C:\scripts\healthcheck.ps1
Finally, in your docker-compose.yaml
add the following to the relevant section for the service that depends on your oracle
service:
depends_on:
oracle:
condition: service_healthy
Upvotes: 2
Reputation: 8096
Using docker-compose.yml
and Official Oracle docker images you can use checkDBStatus.sh
script as a healthcheck. The script returns non-0 while db is in ORA-01033 state. Below is an example. Notice the combination of db's service healthcheck
and tomcat's depends_on
with service_healthy
condition:
tomcat:
image: "tomcat:9.0"
depends_on:
oracle-db:
condition: service_healthy
links:
- oracle-db
services:
oracle-db:
build:
context: src/main/docker/oracle_db
dockerfile: Dockerfile.xe
mem_reservation: 2g
environment:
- ORACLE_PWD=oracle
volumes:
- oracle-data:/opt/oracle/oradata
healthcheck:
test: [ "CMD", "/opt/oracle/checkDBStatus.sh"]
interval: 2s
volumes:
oracle-data:
Upvotes: 10
Reputation: 4598
If you are starting an oracle DB docker container within a jenkinsfile you may find this useful:
def waitForDbHealthy(containerName)
{
timeout(time: 4, unit: 'MINUTES')
{
def HEALTH_RESULT=""
while (! HEALTH_RESULT.toString().contains("healthy") )
{
echo "DB not yet healthy. going to sleep 10 sec."
sleep 10
HEALTH_RESULT=sh(returnStdout: true, script: "docker inspect --format='{{json .State.Health.Status}}' $containerName").trim()
echo "HEALTH_RESULT: $HEALTH_RESULT"
if ( HEALTH_RESULT.toString().contains("unhealthy") )
{
sh("docker logs $containerName")
echo "Going to throw IllegalStateException"
throw new IllegalStateException("Oracle DB switched to state unhealthy")
}
}
}
}
On my build server it tooks about 1 minute until the container is "healthy".
Be aware that oracle's TNS listener might not be ready yet. I found that an additional "sleep 60" (seconds) does the trick. Alternatively you can implement the java TNSPING as Krzysztof Kaszkowiak pointed out in his answer.
Another note: Throwing an IllegalStateException is not allowed per default in Jenkinsfile's groovy. Your Jenkins administrator must explicitely accept it (Jenkins/Manage Jenkins/In-process Script Approval).
Jenkins 2.249.2
Docker Version: 19.03.8
Oracle docker image: based on store/oracle/database-enterprise:12.2.0.1-slim
Upvotes: 2
Reputation: 14865
i'm using wnameless/oracle-xe-11g-r2 and this works for me
version: '3'
services:
db:
image: wnameless/oracle-xe-11g-r2
environment:
- ORACLE_ALLOW_REMOTE=true
ports:
- 49261:1521
volumes:
- ./0_init.sql:/docker-entrypoint-initdb.d/0_init.sql
healthcheck:
test: [ "CMD", "bash", "-c", "echo 'select 1 from dual;' | ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe /u01/app/oracle/product/11.2.0/xe/bin/sqlplus -s USERNAME/PASSWORD@localhost"]
# docker inspect --format "{{json .State.Health }}" myproject_db_1
interval: 10s
timeout: 10s
retries: 60
myservice:
image: xxx
depends_on:
db:
condition: service_healthy
Upvotes: 5
Reputation: 5921
I've finished with a simple check for APEX:
while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' db:8080/apex)" != "302" ]]; do sleep 5; done
302 is used because it redirects /apex to /apex/some_stuff. In my case db is the name of the container with Oracle:
version: '3'
services:
...
* other containers *
...
db:
image: some/image
ports:
- "8383:8080"
- "1521:1521"
Hope it helps someone!
Upvotes: 1
Reputation: 896
You can mimic tnsping in your Java app: How to do oracle TNSPING with java?
If you can't modify the app, tnsping can be called from a bash script - if you have Oracle client installed. If you don't, simply create a simple application from the link above and execute it in a script.
Upvotes: 2