Docker Part III - Learning Docker in more practical way


Hi, I am Malathi Boggavarapu and welcome to my blog. Please do read my earlier posts on Docker to get an idea about it and in this session we do more practical work on Docker. We install the Docker, Build an image and Run it. We also look about Docker Machine and about Docker Maven Plugin which is used to "Dockerize" a web application.

So let's start with Docker for Mac and Windows


Earlier Mac and Windows are two platforms where Docker was not supported natively because Docker is essentially a Linux technology. It is based on Linux containers, C groups and namespaces as we are saying earlier. But NOW we have it supported for Mac and Windows.

So now we are going to see what is Docker for Mac and Windows.

Native application and UI

It is a native application with a native UI. So you literally go to docker.com/getdocker. It's a public BETA. You can download the application by giving the docker hub id.

Auto update capability
It has a capability to auto-update itself because it is native docker application.

No additional software required, e.g. VirtualBox

Earlier if you were to run Docker on Mac or windows you were required to have an additional software such as Type 2 Hypervisor for example VirtualBox. So with Docker for Mac and Windows, we don't need that. you just download the native app and app is that will make you started. So how is it possible?

- OSX: xhyve VM using Hypervisor.framework. On OSX (Mac) we have Hypervisor framework particularly from 10.10 version onwards. It's a basic requirement for Docker for Mac. Hypervisor.framework creates xhyve VM and it is managed by Docker itself. So there is no dependency on third party tool if we are using Docker for Mac.
- Windows: Hyper-V VM - Similarly in windows they created Hyper-V VM and again that is managed by Docker.

Better Networking and filesystem mounting /notification.

We will talk more about this in later sections

Public Beta - docker.com/getdocker

This is the easy way to get started with Docker. Typical way the Docker started is, they did a restricted availability but now it's a public BETA so anybody can go and get Docker for Mac and windows. The download of Docker includes HOST and a Client. Registry could be a Saas(It's a hub.docker.com.) The HOST is pre-configured to talk to that Registry and do whatever needs to be done. You can certainly setup private Docker registry also very easily. Docker has a concept of Project and Product. So for example there is a Docker Registry Project which is a GitHub project and Docker has Product called DTR (Docker trusted registry) which has Security, Authentication, LDAP integration and all other concepts built-in. So you can either clone the Registry GitHub repo and setup your private registry or you can get commercial version and get commercial support on it. In addition there are other options like JFROG artifactory which can be setup as private Registry where you can push your Docker images.



Installing Docker, Building an Image and Running Containers

Install Docker Community Edition by navigating to the url docker.com/getdocker. Choose Docker CE for Windows and install the exe file.

After installing Docker for Windows, it starts running. Now open the Command prompt or Windows powershell. I just used Windows command prompt.

First let's try with a basic command.

docker --version. It shows the docker version that is installed. See the output below.
Docker version 18.03.0-ce, build 0520e24

Now create a directory and create a simple text file and name it as Dockerfile and add some commands to it. You can name it however you want.

Example

FROM openjdk:8
CMD java -version

Save the Dockerfile and navigate to that particular directory in command prompt and execute the below command to build an image.

>docker build -t docker-java .

build is used to build an image with name docker-java and we pass context as Dot (.)
But after executing the command we get an error. Please note, i am discussing also the problems i faced when i installed Docker and try to build some images.


In the above picture when i tried with the command docker build -t docker-java . Docker throws an error saying 'The system cannot find the file specified'. This is because i created Dockerfile in Notepad, it automatically appends .txt to the file name. So i need to explicitly add the file name by using the flag -f . So inorder to correct the above error i used the below command. You can use any file name but make sure that you specify the file name with the flag -f

docker build -t docker-java -f ./Dockerfile.txt .

But this command fails again for some other reason. It is asking for the authentication details to login to the website hub.docker.com inorder to pull the dependencies required.

So do docker login --username=myUser --password=mypassword https://index.docker.io/v1

This will allow you to login to the Docker hub and allow you to pull out the required dependencies from the Registry. So in our Dockerfile we are trying to pull out the dependency Java 8 from Registry inorder to execute the command using CMD.

So now we have logged in to the Registry and let's go back to our build command again and execute it. This time we are adding one more flag --platform linux

docker build --platform linux -t docker-java -f ./Dockerfile.txt .
If we do not --platform linux to the command, it throws error because some of the images are not supported to download in Windows. So we need to switch to Linux and execute the command. So in our example we are switching to Linux platform inorder to download the base image openjdk:8 image.

This time the command will be executed successfully. It pulls out the dependencies that are required from the Registry, in our case it is openjdk:8 and execute the command using CMD.  See the below picture.



In the above picture you can see that whatever instructions Dockerfile is having, Docker will execute all of them in sequential order. First it execute FROM openjdk:8 from the Dockerfile to pull it out from the Registry. It will do that only if you don't have jdk installed on your machine. Installation of jdk will be skipped when it is already exists.

Now we should know how to run the image. But before that we should know what images exists in our Registry. To know that use command docker images. See the below picture.



It shows all the images that were created by us. As i have build docker-java multiple times, it has created those many images. The recently created docker-java image will be tagged as latest. So whenever someone pull docker-java image without specifying Tag name, latest will be pulled out always. We can also give the Tag names for the older versions of image. We will see about that later.



How to run the image


To run the image we use the below command. Inorder to start run command in interactive mode, we use flag -it. See the below command and picture for clear illustration

docker run -it docker-java

As you can see in the below picture, it prints openjdk version as 1.8.0_162. That's what we are expecting the result of the CMD defined in Dockerfile.



docker ps -> Shows all the images that were currently running.
docker ps -a -> Shows all the images that are actively running and also the images that were executed at some point of time and exited.

Docker Options and --help


So far we have run containers in an interactive way but there are other ways to run the containers.
Now let's play with jboss/wildfly server. It is an Redhat's open source application server.
docker run -it -p 8080:8080 jboss/wildfly.

Container residing on a port but that port is not exposed on the Host yet. So to expose that port we use -p and add 8080:8080. the first one is the port on the host and the second one is the port on the container. So i am taking port 8080 in the container and mapping it to the Host,

Now it will run the container and the 8080 port is exposed on the host.
If you execute the command, Jboss wildfly will be started on the port 8080. Now if we go to the browser and say localhost:8080, it will open the home page of the JBoss wildfly application server.

If you want to run the same command in the background mode then use -d (detached) option,
docker run -d -p 8080:8080 jboss/wildfly.

It starts the jboss/wildfly container in the background. Now you can use docker ps to see that the container is running in the background mode.

docker --help -> It will provide help about various docker commands. It is just phenomenal.
docker -run --help -> It shows all the help about docker part of run
docker -build --help -> It shows all the switches that are available for build.



Docker Machine and Docker ToolBox


If you are running Docker for Mac and Docker for windows, they do have stricter requirements. Because of the fact that OSX version depends on Hypervisor version 10.10. The way it runs on windows is you do need Windows 10 64-bit. So Docker is restricted to those platforms. But to run on older versions of Windows of Mac, we use Docker Machine

Docker Machine is the CLI that allows to create Docker Host on Computer or cloud provider.
docker-machine create --driver=virtualbox myhost

driver in this case is virtualbox. So i am likely to create VM's on my local windows. So the command is used to  provision a virtual machine on my computer or cloud and install Docker Host in it. This is basically a tiny Linux VM that fires up on the appropriate operating system and configure your Docker Host over there. Once the Docker Host is provisioned, you need to configure the Docker client to talk to the HOST and you can create and pull images, Start, Stop and restart containers and you can Upgrade docker as well. Unlike Docker for Mac and Windows which will do auto-update, we should manually update the Docker machine.

The easiest way to start with Docker Machine is to use Docker Toolbox. See the below picture what the Docker Toolbox provides. Download Docker Toolbox for windows or Mac before going further.














It comes with Docker CLI, Docker Machine, Docker Compose - It is used to run multiple containers. We will talk about it bit later. Kitematic, ISO and Type 2 Hypervisor Vitualbox.

Quit Docker in your computer and go to the command prompt to create a docker machine
>docker-machine create -d=virtualbox docker4java



So here we created a docker machine called docker4java.

>docker-machine ls
It shows all the docker machines that are available on your computer. See the below picture.



In the last picture where we created docker machine, you can see last few lines, there it says 'Docker is up and running'. And also it says, how to connect Docker client to the Docker engine running on this virtual machine.

>docker-machine env docker4java



It says you need to export the environment variables and later you copy the last line from the output and run it. See below

>eval $(docker-machine env docker4java)

And now if i look at Docker environment variables, those are all set for me. Now you can run the command docker images to see the images that are available in the Docker host of this Docker machine. Now you can create an image, build and run it on the Docker machine that we created, as we did earlier.



Docker Maven plugin


You are a java developer, you build a Maven project and want to Dockerize it. To do that we have a Maven plugin. We can configure phases, so let's say you not only copy jar files or war files to local repo but also make a Docker image and push it to registry. The important part is, the earlier we introduce it into the cycle, the easier it is. It should not be like 'OK i am done with the application and how should i dockerize now'. That's the wrong way of thinking.

Let me show you an example and how we really do that using Maven plugin. Take a look at the below part of pom.xml file. We use docker profile where i am using docker-maven-plugin. We are using fabric8 plugin here. Using this plugin we are building an image. The image name is hellojava, base image is openjdk:latest  and the command is java which executes jar file. Coming down, we see run block which run the image and highlights the "Hello World!" string in the output.

If you look at executions part of the pom.xml, you see the goal build. During the package phase, build goal should be called. If we build the package, it will automatically build the image for you. And when you install the package, it run the image and starting printing out the log for you.

<profile>
            <id>docker</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.fabric8</groupId>
                        <artifactId>docker-maven-plugin</artifactId>
                        <version>0.20.1</version>
                        <configuration>
                            <images>
                                <image>
                                    <name>hellojava</name>
                                    <build>
                                        <from>openjdk:latest</from>
                                        <assembly>
                                            <descriptorRef>artifact</descriptorRef>
                                        </assembly>
                                        <cmd>java -jar maven/${project.name}-${project.version}.jar</cmd>
                                    </build>
                                    <run>
                                        <wait>
                                            <log>Hello World!</log>
                                        </wait>
                                    </run>
                                </image>
                            </images>
                        </configuration>
                        <executions>
                            <execution>
                                <id>docker:build</id>
                                <phase>package</phase>
                                <goals>
                                    <goal>build</goal>
                                </goals>
                            </execution>
                            <execution>
                                <id>docker:start</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>run</goal>
                                    <goal>logs</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>

        </profile>

This actually explains the base concept of Dockerizing Maven project using the docker-maven-plugin.

So that's all about this session. I think we reached long way in learning Docker when combined with my previous posts about Docker. Hope you enjoyed this session.

Please make the session interactive because the more the session is interactive, the more we learn.

Happy Learning!!

Comments

Post a Comment

Popular posts from this blog

Bash - Execute Pl/Sql script from Shell script

Gradle Fundamentals

Load Balancing using Spring Cloud Netflix Ribbon