We at APTLY have the demand for many small and medium solutions to meet special requirements. This often results in Microservices which must be maintainable in an easy and stable way. We found our prefered environment in Docker.
We at APTLY have the demand for many small and medium solutions to meet special requirements e.g. around Marketing Automation. This often results in Microservices which must be maintainable in an easy and stable way. We found our prefered environment in Docker – an “open platform for distributed applications for developers and sysadmins”.
What is Docker?
Docker manages software containers. But what are containers then?
My favorite view on Docker containers is that they wrap a single process. They can also be seen as extremely lightweight virtual machines.
There are two major use cases for containers to show how powerful they are:
“But it works on my machine…”
Maybe you have already heard a colleague saying this or something similar, when they are sad that something does not work on the client’s machine. And sure, they were right. But after an extensive set up on the developer’s machine and its comprehensive documentation, does it really always work the same way on all other machines, especially on the targeted server?
There is always uncertainty. You need to take a few things into consideration: Are you using the exact same database version or is there a different, previously installed one? Are all connections targeting the proper machines (which might require editing the hosts file…)?
The whole error prone setup process gets repeated with each deployment to a server.
“How about packaging the whole product, shipping it ‘as is’ without further adjustments to any machine where it will be executed in an identical environment?”
That’s a bold wish. Or isn’t it?
Let’s have a look on three main types of deployment environments.
The following covers the development and single-host environment. It does not cover multi-host deployments or their orchestration.
A “Bare Metal” Server can host many software installations, security setups and management tools. But this variety can also lead to conflicting versions or configurations. If you try to update one installation like the database, how many other processes will be affected by the update and will they continue to work smoothly? How many people or departments are involved during this process? What about an urgent hotfix?
Plus: development does not happen on the server, so there always will be differences.
2. Virtual Machine
A Virtual Machine (VM) runs on a host. It runs completely independently with its own OS Kernel, software installations, configuration, etc. and can be shipped to a server as an image.
An image is a reproducible and deployable artefact. But there will be only one instance per image, so it needs to be duplicated each time you want to add one for scaling.
And this instance will boot like a normal server, taking its time, acquiring the same amount of resources again—within the host. So, you might need to upgrade your host’s RAM.
A VM is in a way sufficient for development, but it requires repeating a (bulky) virtual deployment process each time there is a new build.
Containers ideally wrap one single process. Containers require very little extra resources since they run on the host’s Kernel, but in a separate, private and secured space. This is why they start up within milliseconds. From an image you can create as many containers as you like. As a developer you might think in an object-oriented manner of a class and its objects.
And the best of all: the development process takes place against the identical image!
This makes the whole development and deployment process repeatable in a safe and simple way. Hotfixes or even rollbacks are no big deal.
One process only? But…
Since containers use only a minimum of additional resources it is best to have an extra container for each individual process. Containers can have names and therefore can be linked.
For example a container named web runs the web application which requires a database server named db. So a second container named db will be linked to the container web. From the web application’s view there is another host with the name db—and that’s the whole magic! This will always work the same on any development machine as well as on every server/host. You do not even have to care about the databases TCP port since the connection between the web and db containers is completely private.
Note: How to manage and run a multi-container application with Docker Compose will be covered in a follow-up post.
A container by example
Let’s have a closer look to the following command line…
$ docker run -d -v /path-to/myapp.jar:/myapp.jar java:8 java -jar myapp.jar
So, what’s going on here?
- The command docker run tells the Docker Daemon to create and run a container.
It will be executed in the background due to the option -d.
- The container is based on the image java:8 which is available on the official Docker Hub.
If it’s not accessible locally it will be downloaded for you automatically, no need to setup the hub.
The image’s name is java and the tag 8 stands for the latest version of Java 1.8.
- Since the required myapp.jar is not contained in the java:8 image it is simply mounted into the container via the option -v /path-to/myapp.jar:/myapp.jar
- The actual command, executed as a foreground process, is java -jar myapp.jar
If the process ends the container ends.
What really pays off in the following is, that the whole installation process is simplified by just running a container using an image. This works the same on your laptop as well as on any other machine.
Let’s demonstrate this with a simple example where you need a database for just for a moment:
$ docker run --rm --name mongodb -it -p 27017:27017 mongo:3.2
This command is all it takes!
Now every local client may communicate with the database via localhost:27017.
Of course in the Docker world the client would in another, linked container connecting via mongodb:27017. Exposing the databases port via -p can be omitted then.
Or you may locally hack into the running container like this:
$ docker exec -it mongodb mongo
Here the MongoDB client command named mongo is executed within the container named mongodb to provide a terminal interface to the database.
There are many base images available on the official Docker Hub – especially these official images cover many Linux distros, runtime environments as well as complete products ready to use. Time consuming and costly setups are not needed anymore.
Since the official images are build automatically they are always up-to-date. Just call:
$ docker pull <name>:<tag>
to receive the latest version.
For development you can use any 64 Bit version of Windows, Mac OS X or Linux. It is recommended to use Linux for operations, but Windows as an execution environment will catch up soon.
A follow-up post will demonstrate how to manage and run a multi-container application with Docker Compose. If you have any questions, feel free to leave a comment.