With the container ecosystem evolving of the past years, developers start to become aware of a solution that can enhance their productivity and deployment time. I will be keeping the instructions as simple and detailed as possible. For people completely new to Docker, I recommend this video:
For more in depth understanding and commands available, you can take a look a the official documentation. I also recommend this short read to understand the differences between containers and VMs.
Let’s say you’re developing feature X that requires data from a relational database to be kept up to date for you to perform your development and manual testing. This might mean that you probably need some kind of mechanism to refresh the data, e.g. some kind of synch job where you can get your most up-to-date data from.
Depending on the size of your data, it can range from a few seconds to several minutes. What if you add new columns or you want to change column types?
For this tutorial you will need:
Grails 3 (you can easily install it via http://sdkman.io/)
Docker (follow the steps at https://docs.docker.com/v1.8/installation/ for your OS)
Tutorial Project: DockerTutorial
I am performing this tutorial on a Macbook with OS X Yosemite. When the steps differ from Linux installations, I will mention steps for both.
Start Docker Quickstart Terminal and make sure docker works properly:
You should see something along the lines of
An IDE is not necessary but if you want to use one, you can just import it as a Gradle project.
Now, we need to download the MySQL docker image for MacOS. Due to a current bug in the official image, we have to use a different image. The issue is only for MacOS and can be followed here.
docker pull dgraziotin/mysql – For MacOS
docker pull mysql:5.6 – For Linux
Before we can do anything with our image, make sure that (if we have any instance of mysql server running locally) we shutdown our running mysql server.
Now, we can start our mysql image.
The above commands starts our container with name docker-db in the terminal window, where we can monitor the container logs. This creates an admin user with a random generated password, outputted in the logs. You should see a message similar to the following:
To verify that our container is working properly, let’s try connecting to it via our mysql client:
Where host should be 0.0.0.0 for Linux.
For MacOS, it is slightly different. Docker in MacOS makes use of a virtual machine. When you start docker with the Quickstart Terminal, this is actually creating a virtual machine with the Docker daemon running inside it. We need to run the following command to get our desired IP by running docker-machine ls. This results in an output similar to the following:
Let’s create our database:
Let’s keep the mysql window open as we’ll come back to it later on.
For our Grails application, we will need to change the database driver for it to connect properly to our MySQL container. Navigate to the grails-app/conf folder and open application.yml. Change host, port and password to the values you used above.
Ok, now that our app is configured properly and our container is running, let’s take it for a spin. Navigate to the root folder where you extracted the project files and run grails run-app.
When the application starts, let’s open it via http://localhost:8080 and we will presented with the Grails scaffolding with a couple of controllers.
When refreshing your local environment, you need to have a mechanism that will populate your database with the new data. This can be a set of scripts and/or database dumps. Insert and update statements can take quite a bit of time depending on the database size and the amount of data required. One alternative, could be to simply get the dump we need and then sync that dump with a database container.
One could argue: “What would be the different from simply using a local MySQL instance?”
What if you’d need to keep your current database state? Let’s say you found a bug or some other kind of issue that can be replicated with that specific set of data. With Docker, you can just spin another container and mount another folder while keeping the one you need.
Or if you have non-developers in team, e.g. designers. Wouldn’t it make their life easier if they just add to run a simple script that starts the container, so they can do their work on an up-to-date database?
Another bonus point is that you do not need to have anything at all related to MySQL server installed on your machine.
How do we achieve this behaviour? We can achieve it through a data volume. The approach that I am going to show will involve mounting a volume in our machine with one inside the container. First, let’s create our data folder, e.g. /tmp/docker-data
Next, let’s add our data files into that folder. I’ve populated a small sample database for the purpose of the tutorial:
Now, we will execute the container again, but this time with a data volume.
docker run -t -i -p 3306:3306 -v /tmp/docker-db-data:/mysql –name docker-db dgraziotin/mysql
The v flag specifies the mapping from our host to the container. When running that container with those flags, we are saying I want to run a MySQL container named docker-db that will store the database data in my /tmp/docker-db-data folder.
Let’s jump back to our application folder and execute grails run-app. If you navigate to one of the two scaffolding pages, you will see some Accounts and Transactions.
This concludes the introduction to this series where we demonstrated how to incorporate a sample application with a container containing a RDS database.
Author: Nuno Santos
Passionate developer at the beginning of his career. I am an enthusiast about all things that are trending on the software ecosystem.
Currently, I am a Grails developer at Secret Escapes, providing luxury travel deals one metaClass at a time.