Search This Blog

Thursday, November 22, 2018

Docker - an open-source engine that automates the deployment of any application as a lightweight, portable, self-sufficient container that will run virtually anywhere

Docker is the hottest new idea in the world of cloud computing, a technology embraced by Silicon Valley’s elite engineers and backed the industry’s biggest names, including Google, Amazon, and Microsoft. Based on technologies that have long powered Google’s own online empire, it promises to overhaul software development across the net, providing a simpler and more efficient means of building and operating websites and other massive online applications.

Docker containers can encapsulate any payload, and will run consistently on and between virtually any server. The same container that a developer builds and tests on a laptop will run at scale, in production*, on VMs, bare-metal servers, OpenStack clusters, public instances, or combinations of the above.

Common use cases for Docker include:
  • Automating the packaging and deployment of applications 
  • Creation of lightweight, private PAAS environments 
  • Automated testing and continuous integration/deployment 
  • Deploying and scaling web apps, databases and backend services 
Docker is targeted at automating the build, deployment and run of applications inside software containers. It is built on top of the well known LXC (Linux Container), which is another software which on its turn uses Linux kernels’ cgroups and namespace support to provide an isolated environment for applications. Seen from a developer perspective, using Docker you can package an application and all of its dependencies in a virtual container that can run on any Linux server, and on other OSes as well. This gives you a huge amount of flexibility and portability on where the application can run, starting from your own laptop up to the public cloud.

Docker has an index of community runtimes so that you can browse and find Docker container images.

The open-source Docker container technology has been one of the most hyped and talked about virtualization technologies of the past year. Docker finally reached the 1.0 milestone, marking the first stable release and the debut of commercial enterprise support. 

Deployment artifact of Docker on Openshift
                                      | Symlinks        |  Deployment Layer
                                      | Built WAR       |
                                      | Startup Scripts |
                   +--------------+   +-----------------+
                   | Maven        |   | Maven (unused)  |  Cartridge Layer
                   | JBoss        |   | JBoss           |
+--------------+   +--------------+   +-----------------+
| Libc / Bash  |   | Libc / Bash  |   | Libc / Bash     |  Base Layer
+--------------+   +--------------+   +-----------------+

+--------------+   +--------------+   +-----------------+
| Kernel       |   | Kernel       |   | Kernel          |
+--------------+   +--------------+   +-----------------+

1. Base from CDN   2. Generic         3. Deployment
                      Docker             Artifact

Docker provides a clear advantage when it comes to application portability over other approaches offered by PaaS and IaaS providers: the ability to place applications into a self-contained unit that can move freely from platform to platform. Docker's solution to the portability problem (in concept, for now) is so compelling that it’s shifting many cloud migration strategies.

Docker Hub and the community

The Docker Hub is an amazing registry where you can store and find public images of all sorts of services and applications. You can compare this GitHub, where people can make and share their source code. In this case, the Docker Hub lets you make and share Docker images in a very user friendly way. When you've build a Docker image, you can push it to the Docker Hub and other people can download it to get started with it.

Almost any application you can think of will probably be already be in there for your to (re)use if wanted. There are also a lot of official images, these are images which are verified by Docker, like for CentOS, Debian, MySQL, Java, Jenkins and so on.

You can also upload private images to the Docker Hub, you can get one private repository and if you want more you'll have to pay. If you decide to use Docker, you should really think about hosting your own Docker registry. This is a trivial task since you can download and run a Docker Registry as… a docker image!

How to get started with Docker

First you'll have to install Docker. Docker currently only works directly on Linux systems, but for Windows and OSX users there is a wrapper boot2docker that installs a mini Linux Virtual Machine which doesn't give too much overhead.
How to build your own Docker image

Now you've seen how to get images from the Docker Hub, what about if you want to build your own image. Everything starts with a Dockerfile, a simple text based file you will create which describe what you want your environment will look like.

To get started with Java application Docker, you add a file called Dockerfile into the root of your maven project. This will be the only file you need to maintain to instruct Docker how to build and run your application. This file will contain a set of simple commands to construct an environment with your application.

You can chose to base your image on the public dockerfile/java which has several versions, called tags, available. The tag available has the Oracle JDK 8 installed in a Ubuntu environment. This is done by using the the FROM keyword and referring to the Docker image name:tag you want to use. The tag version is optional, but if you don't specify it will just take the latest available version which can lead to an unreproducible build.


FROM dockerfile/java:oracle-java8


ADD target/your-app-1.0.0-SNAPSHOT.jar /app/yourApp.jar

CMD ["java", "-jar", "/app/yourApp.jar"]

This Dockerfile does not contain much logic, since setting up the environment is already done in the image you are building upon. The only thing we are doing is added our your-app-1.0.0-SNAPSHOT.jar from our host machine, which is created by running a maven build (mvn package), and copy it to inside our Docker environment. This is done by using the ADD keyword.

The final part is defining the command that has to be executed when we run this image. We can do this by using the CMD keyword, which can be defined as an array. The first parameter is the program we want to executed, followed by all the arguments we want to pass to it.

There is also an entry MAINTAINER to define some metadata about the docker file, about who is maintaining the file, this is completely optional of course.

This is all you need to do to define the container for your application. From this Dockerfile we have to build an actual Docker image that can be run and transferred between our different environments (development, test, production). This is done by executing the following command:

docker build -t i88ca/yourApp:1.0 .

We are telling docker we want to build an image calledd i88ca/yourApp, which is the recommended approach of naming your Docker container. We are setting a prefix which can refer to a company or user name and then giving a name for the actual application. We are giving a specific tag name to this build, which is version 1.0. As a last step, we are telling Docker where it can find its Dockerfile by passing it the current directory using the . notation.

When you are executing this command for the first time, it will take some time since it has to build all layers defined in the Dockerfile, but also the ones we are building upon by basing it on the dockerfile/java:oracle-java8 Docker image. Next time we execute this command, it will be much faster since it is caching all its intermediate layers and only rebuilding the ones that actually changed since the last build.

bash-3.2$ docker build -t i88ca/yourApp:1.0 .
Sending build context to Docker daemon 28.88 MB
Sending build context to Docker daemon
Step 0 : FROM dockerfile/java:oracle-java8
---> 3cd60ec88fa7
---> Using cache
---> f5b8588f06af
Step 2 : ADD target/yourApp-1.0.0-SNAPSHOT.jar /app/yourApp.jar
---> Using cache
---> ce88c01e1764
Step 3 : CMD java -jar /app/yourApp.jar
---> Using cache
---> 9298fee88e4e
Successfully built 9298fee88e4e

Once this is done, we have a local Docker image with the specified name. We could upload this image to the Docker Hub or another Docker repository to share it with other people. This process is very easy. Now we have our container, let’s actually start up the web application.

docker run -p 8080:8080 i88ca/yourApp:1.0

This is all you have to do to start up your own container and expose port 8080 from the docker container and map it to port 8080 of your host. If you are running Docker on Linux you can access the applicationhttp://localhost:8080/your-application-context-root. If you are using boot2docker you’ll have to check what IP it is using, you can find it out by running boot2docker ip.

This is one way to get your application up and running inside a Docker container.

Continuous Delivery

If you are already doing Continuous Integration, you could easily plug Docker in to that process. Your Jenkins, Bamboo or whatever you are using is building an executable .jar or .war file. The next step would be to build a Docker image based on your application deployable. When you've created the Docker image you could then upload this to the Docker Hub or your private Docker repository.

Your deployment plans for each environments can simply download the Docker image and transfer it to the target environment and start the image. The environment specific configuration like database URL and credentials could be passed a startup arguments.