Developing apps with docker
One of the most common questions when we are learning docker is how I can develop my apps with it? Since building and compiling every time we made a change is not practical? Is there a way to easily change our code and reflect those changes straight forward without rebuilding? The answer is yes, it is possible and usually not covered by many tutorials.
In this post you will find different ways to do it and how to implement them using the core docker commands until reaching docker compose
Bind mounts / Volume
We know that each container is based on an image and that container if destroyed all the content on it will be gone. There are 3 ways of preserving / sharing files between containers and those are: Bind mount, Volume and tmpfs mount.
The bind mount: is similar like doing an NFS / CIFS in our linux / windows servers, in which we share a whole directory to the container. This means that the container has full visibility of that part of the disk, which is practical in some scenarios when we want to share files quickly with our container, BUT this presents a high security risk in our systems and should never be deployed in production. The way of binding a mount is by using the -v argument followed by the path of your directory a semicolon and the remote path, i.e docker run -d — name db -v /users/jcarvajal/test:/opt/mnt mongo
In the other hand, we have the Volume: Here is docker that builds a volume in the file system, this means that it is secure and can be accessed between the containers without giving the whole disk access. This is the recommended way of sharing the resources. You can use docker volume help to see all the available commands for the core docker CLI.
The TMPFS mount, is a temporary save point in which we save the data in the memory of the container, therefore if the container dies that data dies aswell.
Now that we know this, we are going to use the Volume as a good practice to follow while developing with containers. For this we are going to use docker-composer and our example app is based in a nodejs application and also uses a mongo DB that is shared in another location.
Here is how our docker-compose.yaml looks like. In order to create a volume in our docker compose we need to (nested in our service app) to add the volumes entry and we are explaining to take all the content from our current location and share that in the /usr/src path of the container and also avoid to override the /usr/src/node_modules. One important part here is to use the command entry, in which we are specifying to monitor the index.js for any change, making this easily to change that file and reflect the changes
If we compile with docker-compose up -d we can see it took the changes and it is recreating it, at this point our app is accessible from the UI!
When sharing the files, and modifying it probably you will be not able to see it, here is what I’ve changed “We are connected to the DB!”
And this is how it looks when you edit and save your app, it recompile again the specific changes and we are able to see it in the UI.
This is awesome when we are working in our own project, but when the docker-compose file is in git or placed in another repository we do not want to mess up the git history and the other folks work. In order to achieve this, we may want to use the Override which is explained in a different post.