Here is a procedure for running an Oracle Database, preparing a baseline in objects (tables, stored procedures) and data, creating an image of that baseline and subsequently running containers based on that baseline image. Each container starts with a fresh setup. For running automated tests that require test data to be available in a known state, this is a nice way of working.
The initial Docker container was created using an Oracle Database 11gR2 XE image: https://github.com/wnameless/docker-oracle-xe-11g.
Execute this statement on the Docker host:
docker run -d -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true --name oracle-xe wnameless/oracle-xe-11g
This will spin up a container called oracle-xe. After 5-20 seconds, the database is created and started and can be accessed from an external database client.
From the database client, prepare the database baseline, for example:
create user newuser identified by newuser; create table my_data (data varchar2(200)); insert into my_data values ('Some new data '||to_char(sysdate,'DD-MM HH24:MI:SS')); commit;
These actions represent the complete database installation of your application – that may consists of hundreds or thousands of objects and MBs of data. The steps and the principles remain exactly the same.
At this point, create an image of the baseline – that consists of the vanilla database with the current application release’s DDL and DML applied to it:
docker commit --pause=true oracle-xe
This command returns an id, the identifier of the Docker image that is now created for the current state of the container – our base line. The original container can now be stopped and even removed.
docker stop oracle-xe
Spinning up a container from the base line image is now done with:
docker run -d -p 49160:22 -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true --name oracle-xe-testbed <image identifier>
After a few seconds, the database has started up and remote database clients can start interacting with the database. They will find the database objects and data that was part of the baseline image. To perform a test, no additional set up nor any tear down is required.
Perform the tests that require performing. The tear down after the test consists of killing and removing the testbed container:
docker kill oracle-xe-testbed && docker rm oracle-xe-testbed
Now return to the step “Spinning up a container”
Spinning up the container takes a few seconds – 5 to 10. The time is mainly taken up by the database processes that have to be started from scratch.
It should be possible to create a snapshot of a running container (using Docker Checkpoints) and restore the testbed container from that snapshot. This create-start from checkpoint –kill-rm should happen even faster than the run-kill-rm cycle that we have now got going. A challenge is the fact that opening the database does not just start processes and manipulate memory, but also handles files. That means that we need to commit the running container and associate the restored checkpoint with that image. I have been working on this at length – but I have not been successful yet – running into various issues (ORA-21561 OID Generation failed, ora 27101 shared-memory-realm-does-not-exist, Redo Log File not found,…).I continue to look into this.
Use Oracle Database 12c Image
Note: instead of the Oracle Database XE image used before, we can go through the same steps based for example on image sath89/oracle-12c (see https://hub.docker.com/r/sath89/oracle-12c/ ) .
The commands and steps are now:
docker pull sath89/oracle-12c docker run -d -p 8080:8080 -p 1521:1521 --name oracle-db-12c sath89/oracle-12c
connect from a client – create baseline.
When the baseline database and database contents has been set up, create the container image of that state:
docker commit --pause=true oracle-db-12c
Returns an image identifier.
docker stop oracle-db-12c
Now to run a test iteration, run a container from the base line image:
docker run -d -p 1521:1521 --name oracle-db-12c-testbed <image identifier>
Connect to the database at port 1521 or have the web application or API that is being tested make the connection.
The Docker Create Command: https://docs.docker.com/engine/reference/commandline/create/#parent-command
Nifty Docker commands in Everyday hacks for Docker: https://codefresh.io/docker-tutorial/everyday-hacks-docker/
Circle CI Blog – Checkpoint and restore Docker container with CRIU – https://circleci.com/blog/checkpoint-and-restore-docker-container-with-criu/