The more I use and learn about Docker and the more I feel like I can’t live without it.This blog is about Docker amazing feature Volume Containers.I wanted to write the Spring Boot app and deploy it to the Docker Container with MongoDB as my document store.
I read through the Docker documentation and figured out it was very easy to mount the volume and start MongoDB so the data could be persisted locally on the host after the container shuts down. Everything went well as expected when running on ubuntu linux machine and then I was stuck and it was not working on Macintosh.
The purpose of the POC was to make developers life easier to quickly start the local environment on their desktop computers.I encountered an issues when using boot2docker and had to make it work on Macintosh because most of the developers are using Mac Book Pro.The issue was when mounting the volume MongoDB always failed to start.Here is the reason why because the boot2docker on Macintosh runs a small light weight virtual machine inside the Virtual Box which does not support fsync() operation on mounted directories and it seems MongoDB requires it.
To deal with the above issue I ended learning volume/data only container concept.You can read more details at docker website here https://docs.docker.com/userguide/dockervolumes/
Step 1 : Create Data only Container
docker run -v /data/db --name mongodata busybox true
The above command will create the data only container named mongodata.
Step 2: Build the docker image for deploying and running springboot app .
git clone https://github.com/alvinhenrick/springboot-docker
It contains the Dockerfile to build the image .Its very easy to read the file and understand it. All it does it to install Java , MongoDB and copy the springboot sample application executable jar.
docker build -t alvinhenrick/springboot .
I have already build the jar file and added to the docker build so you don’t have to build it.The jar file is inside springboot-docker project we cloned in the above step. Look inside springboot-example folder.The application (MongoDB , Spring Data, Spock, Groovy Rest Client ) can be downloaded from here.
git clone https://github.com/alvinhenrick/springboot-example cd /springboot-example #Make sure you have gradle installed. gradle clean build
Step 3: Start the docker container with the image we built above.
docker run -d -p 27017:27017 -p 8080:8080 --volumes-from mongodata --name sboot alvinhenrick/springboot
Notice how the volume only container is mounted (–volumes-from mongodata) and now there will be no issues starting the app on Macintosh and yes this is better way of dealing with data storage in docker.
NOTE: Mac user can do local port forwarding via boot2docker to access the spring boot web app.
boot2docker ssh -L 8000:localhost:8000
We can test the app is working and deployed successfully via the unit test inside the springboot-example project by making the http request to spring controller REST endpoint.
Step4: Run the spock test to confirm that container is running and responding.
RestClientTest.groovy
Step 5: Run Docker Inspect
docker ps -a # capture the container id docker inspect {#yourcontainerid}
You should see the similar output with volume mounted.
"Volumes": { "/data/db": "/mnt/sda1/var/lib/docker/vfs/dir/b5e73af364ef8ad708f4b3a881a3690458935727cc4d0777c71ca8ab7744d560" }, "VolumesRW": { "/data/db": true }
Step 6: Check the Logs
docker logs {#yourcontainerid} /usr/lib/python2.7/dist-packages/supervisor/options.py:295: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security. 'Supervisord is running as root and it is searching ' 2015-01-17 05:25:49,490 CRIT Supervisor running as root (no user in config file) 2015-01-17 05:25:49,490 WARN Included extra file "/etc/supervisor/conf.d/supervisord.conf" during parsing 2015-01-17 05:25:49,505 INFO RPC interface 'supervisor' initialized 2015-01-17 05:25:49,505 CRIT Server 'unix_http_server' running without any HTTP authentication checking 2015-01-17 05:25:49,505 INFO supervisord started with pid 1 2015-01-17 05:25:50,509 INFO spawned: 'springbootapp' with pid 9 2015-01-17 05:25:50,510 INFO spawned: 'mongod' with pid 10 2015-01-17 05:25:51,902 INFO success: springbootapp entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) 2015-01-17 05:25:51,902 INFO success: mongod entered RUNNING state, process has stayed up for > than 1 seconds (startsecs) ➜ springboot git:(master) ✗
Step 7: List the /data/db directory
docker run --volumes-from mongodata busybox ls -al /data/db total 458768 drwxrwxrwx 3 root root 4096 Nov 8 14:38 . drwxr-xr-x 3 root root 4096 Jan 17 05:32 .. -rw------- 1 501 root 67108864 Oct 22 02:27 OLETV.0 -rw------- 1 501 root 134217728 Oct 22 14:15 OLETV.1 -rw------- 1 501 root 16777216 Oct 22 14:15 OLETV.ns -rw------- 1 501 root 67108864 Nov 4 17:46 RRFDB.0 -rw------- 1 501 root 16777216 Nov 4 17:46 RRFDB.ns -rw------- 1 501 root 67108864 Nov 8 14:40 TEST_DB.0 -rw------- 1 501 root 16777216 Nov 8 14:40 TEST_DB.ns drwxr-xr-x 2 501 root 4096 Jan 17 05:25 journal -rw------- 1 501 root 67108864 Jan 17 05:25 local.0 -rw------- 1 501 root 16777216 Jan 17 05:25 local.ns -rwxr-xr-x 1 501 root 3 Jan 17 05:25 mongod.lock
The good thing about springboot app is that we don’t have to install separate web container etc.It is a self contained app which is running in the embedded tomcat web container and supervised via supervisor daemon inside docker container.
In the next post I will explain how to take the backup and restore the data from volume container.
Happy Reading !!!