Using wait-for-it with Oracle database docker image


Today, I was working with an application that uses Oracle as the database. We decided dockerize the application to make it easy for fellow developers to work with the beast. We found a working Oracle docker image by sath89. Oracle 12c Docker image is close to 5.7GB on disk so we are not talking about lightweight containers here :). Once image was dowloaded, running image was as easy as running the following command.

$ docker run -d -p 8080:8080 -p 1521:1521 sath89/oracle-12c

This will start the Oracle database in a container. On my machine, it takes close to 7-8 minutes for the database to become up and running. If you want to keep running container in the background then you just have to run container once and then use it.

We wanted to bootstrap the entire application with a single command using Docker Compose. Also, in the dev mode, we wanted to create database schema using Hibernate’s schema generation utilities. The problem is that Docker Compose does not wait for the Oracle container to become ready before starting application container. For example, let’s suppose we have two services — db and web. The web service depends on the db service as shown in the docker-compose.yml shown below.

version: '3'

services:
  db:
    image: sath89/oracle-12c
  web:
    image: com.example/myapp
    environment:
        SPRING_JPA_HIBERNATE_DDL-AUTO: create
        SPRING_PROFILES_ACTIVE: docker-oracle
    depends_on:
      - db

Now, when you start the application using docker-compose up then Docker compose does not ensure that db service is ready before web service is started. This means your application will fail to start. The depends_on only means that db service should be started first but compose does not ensure db service is full ready for connections. This cause issues in scenario where we need to have strict control.

wait-it-for to the rescue

wait-for-it is a simple bash utility to test and wait for the availability of TCP host and port. The need for wait-for-it arises when you want to make sure a container is up and running before another container. It took me time to figure out how to use it with Oracle so I am writing it down for fellow developers who might also need to use wait-for-it in future.

To use it, first copy the wait-for-it.sh in your project directory.

Next, you will update docker-compose.yml as shown below.

version: '3'

services:
  db:
    image: sath89/oracle-12c
  web:
    image: com.example/myapp
    environment:
        SPRING_JPA_HIBERNATE_DDL-AUTO: create
        SPRING_PROFILES_ACTIVE: docker-oracle
    entrypoint: ["./wait-for-it.sh","db:8080","--timeout=0","--strict", "--", "java", "-jar","app.jar" ]
    depends_on:
      - db

In the docker-compose.yml we added entrypoint instruction. The entrypoint instruction let you identity which executable should run when container is started from image.

As you can see in the entrypoint value, we are using wait-for-it to wait for indefinite time for port 8080 in the db container to become accessible. The Oracle docker image exposes management web console at port 8080. Once db container is available we start the application. You should read wait-for-it documentation to understand its document in case you are unclear about meaning of the options.

You will see logs like the following in compose shell.

web_1    | wait-for-it.sh: waiting for db:8080 without a timeout
db_1     | Copying database files
db_1     | 1% complete
db_1     | 3% complete
db_1     | 11% complete
db_1     | 18% complete
db_1     | 37% complete
db_1     | Creating and starting Oracle instance
db_1     | 40% complete
db_1     | 45% complete
db_1     | 50% complete
db_1     | 55% complete
db_1     | 56% complete
db_1     | 60% complete
db_1     | 62% complete
db_1     | Completing Database Creation
db_1     | 66% complete
db_1     | 70% complete
db_1     | 73% complete
db_1     | 85% complete
db_1     | 96% complete
db_1     | 100% complete
db_1     | Look at the log file "/u01/app/oracle/cfgtoollogs/dbca/xe/xe.log" for further details.
db_1     | Configuring Apex console
db_1     | Database initialized. Please visit http://#containeer:8080/em http://#containeer:8080/apex for extra configuration if needed
db_1     | Starting web management console
db_1     |
db_1     | PL/SQL procedure successfully completed.
db_1     |
db_1     | Starting import from '/docker-entrypoint-initdb.d':
db_1     | found file /docker-entrypoint-initdb.d//docker-entrypoint-initdb.d/*
db_1     | [IMPORT] /entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
db_1     |
db_1     | Import finished
db_1     |
db_1     | Database ready to use. Enjoy! 😉
web_1    | wait-for-it.sh: db:8080 is available after 432 seconds

That’s it for this blog. I hope this will be useful to you.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s