JavaRush /Java Blog /Random EN /First acquaintance with Docker
Viacheslav
Level 3

First acquaintance with Docker

Published in the Random EN group
Containerization is a mechanism often used in practice. For example, when you search on headhunter, you will find 477 vacancies as of today that mention Docker. Therefore, it would not be a bad idea to familiarize yourself with what it is. I hope this short review will help form a first idea. Well, he’ll back it up with additional materials, like courses on Udemy. First introduction to Docker - 1

Introduction

In this short review I would like to touch on a topic such as containerization. And you need to start by understanding what containerization actually is. According to Wikipedia, “ Containerization ” is operating system-level (i.e. NOT hardware) virtualization in which the operating system kernel maintains multiple isolated user space instances instead of just one. " User space " is the operating system's virtual memory address space reserved for user programs. User space instances (commonly called containers) are completely identical to a single operating system instance from the user's point of view. The kernel ensures complete container isolation, so programs from different containers cannot affect each other. It turns out that containerization is software virtualization, that is, virtualization at the operating system level, for which the operating system kernel is responsible. One of the characteristic features of this approach is that all containers use a common kernel, the same as the host operating system (that is, the one on which the containers are located). This allows you to get rid of the overhead of emulating virtual hardware and launching a full-fledged instance of the operating system. We can say that this is “lightweight” virtualization. The kernel is the central part of the OS that provides applications with coordinated access to computer resources, such as processor time, memory, external hardware, and external input and output devices. The kernel also typically provides file system and network protocol services. In general, this is the heart of the entire system. For additional information, it may be useful to review the material " General information about containers ". And a few more words to make the introduction complete. We now have an understanding that an operating system has a kernel. It provides isolation for user space instances. In this context, you may come across the term " cgroups ". This is the name of the very Linux kernel mechanism that allows you to achieve this. Therefore, we can say that the path of containerization began with Linux systems. However, starting with Windows 10, support for containerization also appeared. To work with virtualization, you need to configure virtualization support in your computer's BIOS. How to do this depends on the computer. For example, it might look like this:
First introduction to Docker - 2
On Windows you can check this in different ways. For example, you can download a special utility from the Microsoft website: Hardware-Assisted Virtualization Detection Tool . Well, it’s worth mentioning another important concept - Hypervisor. Hypervisor is a virtual machine monitor, a program for ensuring parallel execution of several operating systems on the same computer. The hypervisor ensures that operating systems are isolated from each other and shares resources between running OSes. One such hypervisor is Oracle VirtualBox .
First introduction to Docker - 3

Docker

So, what virtualization is is clear. But how to use it? And here Docker comes to our aid. Docker is software for automating the deployment and management of applications in containerized environments. It’s worth starting with the fact that Docker is represented by such a concept as Docker Enginge. And you should start with the official Docker website and the “ Docker Overview ” section.
First introduction to Docker - 4
The documentation says that docker consists of:
  • Docker server called Docker Daemon process (dockerd).
  • Command line interface, also known as CLI (docker).
  • A REST API that describes how programs can "talk" to deamon and tell it what to do.
Before we dive in further, let's install docker, that is, install the docker daemon. The Docker website has instructions for installing " Docker for Windows ". Interestingly, Docker has its own system requirements. And if you, like me, have an old Windows, for example Windows 7, then you need to use Docker Toolbox.
First introduction to Docker - 5

Docker Toolbox

To install Docker on old machines that do not meet the system requirements. The website says so, “Legacy Desktop Solution”. Let's go to the " Docker Toolbox " page and download it. This set weighs about 211 megabytes. We will install it as a default, that is, we will simply meekly agree with everything without rearranging the flags. After installation, we will check that everything is fine. In the future, our battlefield will be the command line. I recommend not using the Windows command line, because there may be unobvious problems with it. It's better to use bash shell. On Windows, the most recommended way to get it is to install the git version control system , it will still come in handy. Because “bundled” with it will be the bash we need. For this review I will use git bash. You can also install bash with CYGWIN . Let's launch bash or git bash. Let's make sure that we have installed the Docker Machine, also known as Docker Machine: docker-machine -version What is this Docker Machine? Docker Machine is a utility for managing dockerized hosts (these are hosts on which Docker Engine is installed). If we immediately after installing Docket Toolbox view docker machines using the command docker-machine ls, we will see an empty list:
First introduction to Docker - 6
Let's create a new machine. To do this, we need to run the create command : docker-machine create -- driver virtualbox javarush: We will see the docker machine creation log:
First introduction to Docker - 7
What interests us here is the following. What is Boot2Docker? This is a minimalistic Linux distribution for running the Docker Engine (we understand that Docker works thanks to Linux virtualization tools, and in Windows the necessary mechanism appeared only starting with Windows 10). This distribution is based on the " Tiny Core Linux " distribution. Also mentioned about VirtualBox VM. This is because we specified --driver virtualbox. A new virtual machine was created in VirtualBox from the Boot2Docker image. After creation, we can launch VirtualBox (since VirtualBox is installed with Docker Toolbox) and see the created virtual machine for the docker machine:
First introduction to Docker - 8
After creation, we will be prompted to run the command “ docker-machine env ” to get the environment variables that need to be configured to connect to the docker machine:
First introduction to Docker - 9
After executing this command using docker-machine, we connect to a remote dockerized host (in this case, a virtual one hosted on Virtual Box) and can execute docker commands locally as if we were executing them on a remote host. To check, we can run the " docker info " command. If the connection to the docker machine is not established, we will receive an error. And if all is well, information about the docker on the docker machine. Now is the time to understand how Docker generally works and how to use it.
First introduction to Docker - 10

Docker Containers

So we have docker. What is this docker anyway? The Docker documentation and the “ Get started ” section will help us understand this . The introductory part of this section introduces Docker Concepts . It states that Docker is a platform for developing, debugging and running applications in containers. Therefore, the main thing for Docker is containers. Even if you look at the docker logo, it is a whale that holds containers on its back. But what is a container? Next in the " Images and Containers " section it says that a container is a running instance of Image. And Image is a “package” that contains everything necessary for the application (code, environment, libraries, settings, etc.). Now let's try it ourselves. The Docker website has a section called " Docker samples " which includes " Docker for Beginners ". The examples from here seem more interesting to me. So, we suddenly wanted to get acquainted with Alpine Linux and we can do this using Docker containers. To get an image, we must "pull" or "pull" it out. Therefore, we execute the docker pull command :docker pull apline
First introduction to Docker - 11
As we can see, we are downloading from somewhere. By default, Docker looks at its repository on the network https://hub.docker.com . After successfully retrieving the image, we can check the list of available images by running the docker images command :
First introduction to Docker - 12
Now we have an apline image. Since the container is a running instance of image, let’s launch this very image. Let's launch the container using the command docker run alpine. As we see, nothing happened. If we execute the command docker psto display all active containers, we will also get nothing. But if we execute, docker ps -awe will see all the containers:
First acquaintance with Docker - 13
The thing is that we did not launch Docker in interactive mode. Therefore, he executed the command and stopped. The command was to open the terminal. Let's do the same thing, but in interactive mode (with the -it flag ):
First introduction to Docker - 14
As you can see, having overcome one mistake and using the hint, we got to the container and can work in it! To exit the container without stopping its operation, you can press Ctrl + p + q. If we run now docker ps, we will see one active container. To enter an already running container, run the docker exec command :
First acquaintance with Docker - 15
I recommend reading the description of the Docker sample for an excellent description of how this all happens: “ 1.0 Running your first container ”. I like it because everything is written there in a very accessible and understandable way. To briefly rephrase, we are connected using docker-machine to a virtual machine running Docker Daemon. Using the CLI over the REST API, we ask to launch the alpine image. Docker finds it and therefore does not download it. Docker creates a new container and runs the command we specified in this container. And all this, of course, is good. But why do we need all this? And here we need to figure out how docker creates an image. And he creates them based on the dockerfile.
First introduction to Docker - 16

Dockerfile

As stated in the Dockerfile reference , a dockerfile is a text file that contains all the commands for obtaining an image. In fact, all the images we receive (even Alpine, from the example above) were created from a dockerfile. Let's build our image with a Java application. And first we need this Java application. I suggest using the Gradle build system, which you can read more about in this short review: “ A Brief Introduction to Gradle ”. Will help us in creating the project " Gradle Build init plugin ". Let's create a new Java application using Gradle: gradle init --type java-application This command creates a template Java project. This is a standalone application, but we would like to create a web application. Let's remove the App and AppTest classes (they were generated automatically by Gradle Build Init Plugin). To quickly create a web application, we will use the tutorial from Gradle: “ Building Java Web Applications ”. According to the tutorial, let's do: You have to be careful here. As always, there may be errors in the examples. Here it is:
First introduction to Docker - 17
Now, to test it, let's add the gretty plugin to build.gradle, as indicated in the " Add the gretty plugin and run the app " section:
plugins {
    id 'war'
    id 'org.gretty' version '2.2.0'
}
It's interesting that Gretty doesn't see the error in HelloServlet, which is described above. This proves that an application can behave differently in different environments. Gretty can work where a regular standalone server would throw an error. All that remains is to check that the application is working correctly. Let's do:gradle appRun
First acquaintance with Docker - 18
If all is well, then use the command gradle warto collect an archive with the extension war (web archive). By default, gradle builds it in the \build\libs. Now, we are ready to write our dockerfile. Using the " Dockerfile reference " we will create a Dockerfile. Let's create a file called "Dockerfile" in the root of our Java project (in the same place as the build script). Let's open it for editing. This file has its own format, described in the " Dockerfile reference: Format " section. Any dockerfile begins with a FROM statement, indicating the "base image". We can say that this is the parent image on the basis of which we make our image. It’s very easy for us to choose a parent image. A web application needs a web server. For example, we can use the Tomcat web server. We go to the official Docker repository, which is called docker hub . We look there to see if the image we need is there:
First acquaintance with Docker - 19
It is also worth understanding that the tomcat image is called. But besides the name it has a tag. A tag is like a version. Tomcat images of different versions differ in which version of Tomcat is used, which version of jre and which base image. For example, we can get an image docker pull tomcat:9-jre8-alpine It uses version 9 of tomcat, jre version 8 and the alpine image as a base. This can be important to reduce the size of our image:
First introduction to Docker - 20
As we can see, the difference is huge. If we build our image based on tomcata alpine, we will start with only 100 megabytes, and not with 600. Accordingly, we will add the following content to the previously created dockerfile:
# Базовый образ, "наследуемся" от него
FROM tomcat:9-jre8-alpine
# Копируем из Build Context'а собранный web archive в каталог томката
COPY build/libs/docker.war /usr/local/tomcat/webapps/docker.war
# Меняем рабочий каталог на томкатовский
WORKDIR /usr/local/tomcat
# Открываем порт 8080 для контейнера, т.к. его слушает томкат
EXPOSE 8080
And now let’s execute the command to build the image: docker build -t jrdocker ..
First acquaintance with Docker - 21
-t- this is a tag, that is, what to call the assembled image. The dot at the end means that we add the current directory (the directory where the dockerfile is located and where we ran the command from) to Build context. Build context- this is the context of those files that are available when creating a dockerfile. As you can see, thanks to this we were able to copy the assembled war file into our image, into the web server directory. Now let's run our image:docker run -d --rm -p 8888:8080 jrdocker
First acquaintance with Docker - 22
To understand whether the server has started, you can look at the log from the container. The log can be obtained using the docker logs command, specifying the container by its ID or name. For example:
First acquaintance with Docker - 23
Well, don’t forget that we can always go to a running container by name with the command: winpty docker exec -it NameКонтейнера sh Now all that’s left is to connect. Previously, we specified EXPOSE , that is, we allowed access to port 8080 from inside the container. When we launched the container itself, we specified the -p ( incoming ports ) tag, thereby correlating port 8080 on the container (the Tomcat web server is waiting for connections there) with the port 8888 on a machine with a docker daemon. As we remember, we launched the docker daemon not directly, but through docker-machine. Therefore, let’s once again ask for data on our docker machines using the docker-machine ls command and contact the server in the container:
First introduction to Docker - 24
Thus, you and I have just launched our web application in a Docker container! ) I would also like to note the following. In case of access problems, you should remember that the Docker machine is first and foremost a Virtual BOx virtual machine. There may be problems with the virtual machine's network settings. A working VMBox configuration might look like this:
First acquaintance with Docker - 25
First acquaintance with Docker - 26

Layers

We have already figured out that images are created from dockerfiles and that dockerfiles are a set of commands. We also figured out that a dockerfile has a parent. And that the size of the images is different. Interestingly, you can see the history of how the image was built using the docker history command . For example:
First acquaintance with Docker - 27
It is important to say this to understand that, in essence, each image is a set of images. Each image change (each new command in the dockerfile) creates a new layer that has its own ID. You can read more about layers in the documentation " Docker: Images and Layers ". I also highly recommend reading the article on Habré: “ Docker images and containers in pictures .”

Conclusion

I hope this short overview was enough to get you interested in containerization. Below are links to additional material that may be useful: #Viacheslav
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION