Wood elf technology blog Http://prog3.com/sbdm/blog Http://prog3.com/sbdm/static.blog/images/logo.gif To do a little bit of technical sharing and exchange Http://prog3.com/sbdm/blog/shlazww Zh-cn Http://prog3.com/sbdm/blog Five 7:57:42 2016/1/21 <![CDATA[[原]深入理解 Docker 镜像 json 文件]]> Http://prog3.com/sbdm/blog/shlazww/article/details/48208445 Http://prog3.com/sbdm/blog/shlazww/article/details/48208445 Shlazww 12:57:43 2015/9/4 Many times, when we talk about Docker, often referred to Docker as a container solution, there is no small advantage in terms of virtualization resources. The advantages of lightweight virtualization technology aside, from the software life cycle point of view, Docker in packaged software, the ability to distribute software is equally outstanding. The latter is largely dependent on the mirror image technology of Docker.

Docker mirror technique provides a set of standard, creative use of Dockerfile to standardize the production process of the docker application, mirroring of the docker produce results for transmission and management. Finally through the docker mirroring operating docker container, container application delivery.

After this series for the Docker mirror image, we should have a clear Docker image of the storage, as well as the contents of the Docker image. Docker image content, it should be said that the two parts, in addition to the image layer in the file, but also includes a layer of JSON image file. The understanding of the image layer file is relatively simple, but the Docker image of the JSON file will be slightly complicated to understand. This article will take you to understand the Docker image of the JSON file.

We have been referred to the Docker mirror running Docker container, if you think carefully about this sentence, there may still be some doubts. It is easy to understand that the files in the Docker image layer are all static disk files, while the Docker container is a dynamic product, which can be considered as one or more processes. Then, the static Docker image is transformed into a dynamic Docker container, and there will be some hidden secrets behind it. We might as well take the following questions to think about the Docker image of the JSON file:

1 how to determine which process a Docker image should run, which is part of the information?

2 with the above information, the Docker image into a Docker container is the behavior of who is in the lead?

The static and the dynamic of the container

This time, we are still fromdynamicandstatic stateThese two words to see the Docker image of the previous life. First, the Docker mirror image layer file belongs to a static file, when the container to run after this part of the contents of the file system as a Docker container content, to provide a Docker container file system perspective. We take this view, and then look at the concept of Dockerfile.

In the Dockerfile primitives, we must be very familiar with ENV, VOLUME, EXPOSE, and CMD commands.

MYPATH=/root ENV: env command in constructing the docker mirror, mirror add an environment variable to the environmental variables in docker container startup role in the process of the container; this part of the information should not in the form of static files is introduced into the docker mirror layer file.

/data VOLUME: volume orders in constructing the docker mirror, mirror to add a data volume ID, so as to pass the mirror the container operation for container mounted a data volume; due to the construction of real data volume does not yet exist, so this part of the information should not in the form of static files is introduced into the Docker mirror layer file.

EXPOSE 80: expose commands in constructing the docker image recording actual monitoring inside a container port in order to through a bridge pattern configuration docker container network, DNAT conversion is carried out for the port and the host; this part of the information belongs to the docker container operation required information should not in the form of static files is introduced into the Docker mirror layer file.

CMD ["./run.sh"]: CMD command in constructing the docker mirroring, recording start docker container execute commands the entrance, generally used to specify the user's application; this part of the configuration information should not in the form of static files is introduced into the docker mirror layer file.

Dockerfile in the above examples of the 4 types of orders, through the analysis, we draw a preliminary conclusion:Part of the order of the Dockerfile contains a class of dynamic information, such information does not belong to the contents of the Docker image layer in the file.

Dynamic content storage

High portability guarantees the Docker imageA build, multiple operation, then make the Docker container can run smoothly, Docker will not abandon the dynamic content of the construction of Docker image. Therefore, the storage of dynamic content is particularly important.

At this time isDocker mirror JSON fileTiming of debut.When building a Docker image, all the dynamic information will be recorded in the JSON file corresponding to the Docker image.Need to pay attention to,Although the image of dynamic information will be stored in the docker mirror the JSON file, but does not represent the JSON file stores only dynamic information, Dockerfile construction process, opportunities for all operations will be recorded in the JSON file.

Implementation of dynamic content

The docker mirror JSON file to describe the dynamic information of the docker container, then JSON file as part of a docker mirroring, in docker system, by which a module to complete the analysis of the dynamic information in the JSON file and enforce it?

If you know that every Docker container is Daemon Docker's child process, then, will certainly associate to Daemon Docker. The answer is Daemon Docker. Standing on the starting point of the container, the role of Daemon Docker is the following two points:

1 Docker mirror image layer file as the Docker container rootfs.

2 extract the Docker image JSON files in the dynamic file to determine the starting process, and for the configuration of dynamic operating environment.

Daemon Docker, Docker image and Docker container three simple schematic as follows:

Write the picture here.

Through the above, we can use ubuntu:14.04 mirroring operating docker container, the former mirror layer content will as rootfs container; and the former JSON file, is parsed by a docker daemon, and extract the container entrance CMD information, and the container process environment variable env information, initialize a container process. Of course, the entry of the container process is derived from the rootfs provided by the mirror image. If at this time Ubuntu 14.04 mirror the JSON file also contains the volume information, then docker daemon will docker container in the host to create a directory of files, and mount to inside the container, use mirrored volume dynamic information, the use of other dynamic information is also similar.

The true face of Docker mirror JSON file

The full text of the analysis so far, or more from a theoretical point of view of the Docker image of the JSON document, then the reality of this type of JSON documents in the end what is the content? We still take ubuntu:14.04 as an example, uncover the Docker mirror JSON file of this face.

Image

A Docker mirror image containing the label usually has one or more levels of mirror image composition, and each mirror layer will contain a JSON file. In the picture above, we show the specific circumstances of the 4 mirror images in the ubuntu:14.04 image, especially the analysis of the image.8251da35e7a7andE5855facec0b. By looking at the two images of the JSON file, we can find that the two JSON files in the config attribute, in addition to the should be different from the image ID, only the Cmd attribute is different. As mirrorE5855facec0bIs a mirror8251da35e7a7The Dockerfile command is used as the parent mirroring, while constructing the sub image.CMD ["/bin/bash"], therefore, based on the JSON file of the parent, the child is updated to update the Cmd attribute in the config attribute and complete the generation of its own JSON file.Docker mirror image of the father and son JSON file has a lot of similarity, the child mirror only on the basis of the parent JSON file, modify the operation of its own corresponding to the difference caused by the Dockerfile command.

Mirror completed construction, docker mirror mirror layer file and JSON file are ready, then when docker daemon through the ubuntu:14.04 mirroring operating docker container. First, we extract the top mirror the JSON file, find config properties of CMD commands, and image file layer formed in the container rootfs find corresponding implementation program, final implementation, start of the container is finished. (the actual situation is more complex, will involve the Entrypoint and Cmd two parts of the content, the series will follow the role and the difference between the two.

Of course, in addition to JSON, the Cmd file of the config property in the User, ExposedPorts, Entrypoint, NetworkDisabled and a series of dynamic information needed to start the container.

summary

Docker mirroring the JSON file playing extremely important role and provides a static image to dynamic container into basis, also clearly record the difference between father and son image. Based on this difference, build a subsequent docker's cache mechanism was realized.

Write the picture here.

Welcome to the [Docker source analysis of the micro channel public number, more exciting upcoming.

Author: shlazww published in 12:57:43 2015/9/4Text link
Read: 151 comments: 0View comments
]]>
<![CDATA[[原]深入分析Docker镜像原理]]> Http://prog3.com/sbdm/blog/shlazww/article/details/48208365 Http://prog3.com/sbdm/blog/shlazww/article/details/48208365 Shlazww 12:51:59 2015/9/4 Part I: the basic knowledge of Docker image

1.1 what is the Docker mirror

From the whole point of view, a complete Docker mirror can support the operation of a Docker container, in the operation process of the Docker container to provide the main point of view of the file system. For example, a ubuntu:14.04 mirror, provides a basic version of the ubuntu:14.04, of course, this mirror is not included in the operating system Linux kernel.

When it comes to this, you may need to pay attention to the difference between the Linux kernel and the ubuntu:14.04Docker image. Traditional virtual machine installation ubuntu:14.04 will contain two parts. First, the release version of a Linux kernel, such as the kernel of Linux version 3.8; second, first specific release of Ubuntu, Linux kernel are not included in this part of the content, but contain than linux software management mode, driver software, such as apt get software management package.

After understanding the above, you can understand why in a Linux kernel version of the ubuntu:14.04 based on the 3.8, you can upgrade the Linux kernel version to 3.18, while the Ubuntu version is still 14.04. The most important is: the Linux kernel version and the Ubuntu operating system, the difference between the release.

The Linux kernel Ubuntu operating system version of a work machine so that the user experience. So flexible replacement Ubuntu operating system release, it is not also can be achieved. So Docker is very convenient to use this point, the technical means is the Docker image.

In the architecture of Docker, the Docker image is similar to the "Ubuntu operating system release", which can be run on any Linux kernel that meets the requirements. Simple point is the Debian operating system issue "docker mirror," Ubuntu operating system release version of "docker mirror like; if in a Debian mirror installed MySQL 5.6, then we can its name as a mirror image of Mysql:5.6; if there are 1.3 golang installed in a Debian mirror, that I can be the name as a mirror image of golang:1.3; by analogy, we can according to install their own software and get whatever you want the mirror.

So what is the final effect of the mirror image? Well understood, back to the Linux kernel to run through the mirror to run time we often provide the environment called the container.

The above content is from a macro point of view of the Docker mirror is what we re from the micro point of view to further Docker image. Just mentioned the "Debian image in the installation of MySQL 5.6, it has become a mysql:5.6 mirror", in fact, at this time the level of Docker image concept is reflected. The bottom of a Debian operating system image, superimposed on a MySQL layer, completed the construction of a MySQL image. Level concept is not difficult to understand, at this time we generally Debian operating system image is called the father of the MySQL mirror image layer.

The way of hierarchy management is greatly convenient for the distribution and storage of Docker image. When it comes to distribution, we naturally think of the flexibility of the Docker mirror image, the convenience of transmission, and superb portability. Hub Docker, as a mirror of the global warehouse, as the Docker ecology of the data warehouse, the world's Docker data together, is the lifeblood of the Docker ecosystem.

Docker has two aspects of the technology is very important, the first is the Linux container technology, the second is the Docker image technology. The technology itself is concerned, both can be copied is very strong, there is no absolute technical difficulties. However, docker hub due to the presence of large amounts of data, resulting in docker hub can be copied almost does not exist, which requires an ecological building.

1.2 Docker image content

What is the general introduction to the Docker mirror, and what do we see in the Docker image?

Prior to the introduction, I first share, I personally in contact with Docker for two years, the change of the content of the Docker mirror.

The first stage: initial contact Docker. I believe that many fans will be like me, there is such a knowledge: Docker image represents a container file system content;

The second stage: preliminary contact with the joint file system. The concept of the joint file system, which makes me aware of the technology of image level management, is part of the contents of the container file system.

The third stage: relationship between the study of the mirror image of the container and container is a dynamic environment, each layer image file belongs to static content, however Dockerfile in the env bike, volume, CMD and other content will eventually need to implement the operation of the environment of the container, and the content are not likely to lie directly to each layer image contains the contents of the file system, and then every a docker mirror also includes the relationship between the JSON file records with the container.

Therefore, the contents of the Docker image mainly contains two parts: first, the contents of the image layer; second, the mirror image JSON file.

1.3 Docker mirror storage location

Since it is said that the location of the mirror storage, then it should include: the mirror layer file and the mirror JSON file. Such as a ubuntu:14.04 mirror, contains 4 mirror layer, in the case of aufs storage driver, in the case of the disk can be shown as the following:

1.3.1 view mirror layer composition:

We can view the ubuntu:14.04 through the command history ubuntu:14.04 docker, the results are as follows:
Write the picture here.

1.3.2 mirror layer file content storage

The content of the Docker mirror layer is generally in the aufs root directory of the Docker path, for the /var/lib/docker/aufs/diff/, the specific circumstances are as follows:
Write the picture here.

The diagram shows the contents of the 4 mirror images of the mirror ubuntu:14.04, as well as the contents of the first level directory within each image layer. Need to pay extra attention to: there is no content in the image layer d2a0ecffe6fa, which is the so-called empty mirror.

1.3.3 mirror JSON file storage

For each mirror layer, Docker will save a copy of the corresponding JSON file, JSON file storage path for /var/lib/docker/graph, ubuntu:14.04 all the image layer of the JSON file storage path is shown as follows:
Write the picture here.

In addition to the JSON file, we also see that each mirror layer also contains a layersize file, the file is mainly to record the total size of the image layer inside the file content. Since it comes to the mirror image JSON file, in order to pave the way, the following posted ubuntu:14.04 hollow mirror layer JSON d2a0ecffe6fa file:
Write the picture here.

Docker mirror storage, and everyone to see this. At the same time introduced the basic knowledge of Docker mirror also come to an end. The following we enter the second part of the share.

The second part is the relationship between Dockerfile, Docker image and Docker container.

Dockerfile is the raw material of the software, the Docker image is the delivery of the software, and the Docker container can be regarded as the running state of the software. From the application point of view, the three different stages of Dockerfile, docker mirror and docker container, respectively, on behalf of the software, Dockerfile oriented development and docker image become delivery standards, docker container relates to the deployment and maintenance, three are indispensable together to act as the cornerstone of the docker system.

In simple terms, Dockerfile to build a Docker mirror, Docker mirror running through the Docker container.

We can from the point of view of the Docker container, to push back the relationship between the three. First can look at the following chart:
Write the picture here.

We assume that the mirror image of this container is constructed by the following Dockerfile:

FROMUbuntu:Fourteen point zero four  
ADDRun.sh /
VOLUME/Data  
CMD["./run.sh"]

2.1 Dockerfile and Docker images

First of all, we have a look at the relationship between Dockerfile and Docker images in the image above.

Ubuntu:14.04 FROM: set the base image, and then use all the mirror layers of the base mirror ubuntu:14.04 as a whole.

Run.sh ADD /: Dockerfile directory file run.sh to the root directory of the mirror, this time the new layer of the image is only one content, that is, the root directory run.sh.

/data VOLUMESetting the image of the VOLUME, this VOLUME the path inside the container is /data. Need to pay attention to is that at this time not in a new layer of the mirror add any files, file that is to build a magnetic mirror is empty, but updated mirror the JSON file, order by the image to start the container when the information gets.

CMD ["./run.sh"]Setting the default execution entry for the mirror, this command will not add any files in the new mirror image, just update the newly built JSON file based on the last layer of the JSON file.

Therefore, through the above analysis, the above Dockerfile can build a new image, including 4 mirror layers, each command will correspond to a mirror layer, there will be a parent-child relationship between the mirror. These relationships are clearly indicated in the picture.

2.2 Docker image and the relationship between the Docker container

Docker mirror is the basis for the operation of the Docker container, there is no Docker mirror, it is impossible to have a Docker container, which is one of the principles of Docker design.

It can be understood that: Docker mirror, after all, is a mirror image, which belongs to the static content; and the Docker container is not the same, the container is a dynamic content. Dynamic content, it is easy to think of the process, memory, CPU, etc.. Indeed, the Docker container as a dynamic content will contain these.

In order to facilitate understanding, you can put the docker container, understood as one or more of the operation process, and the running process will occupy the memory and CPU computing resources, the corresponding virtual network device and the corresponding file system resources. The Docker container is occupied by the file system resources, then through the Docker mirror image layer file to provide.

So, as a static image, how to have the ability to transform into a dynamic Docker container? At this point, we can imagine: first, what is the basis for transformation; second, by whom to perform this transformation operation.

Environment variables actually is transformed according to each mirror the JSON file, docker can through analytic docker mirroring the JSON file, learn what kind of process should be run on top of the image, it should be how to configure the process, this time also will realize the static to dynamic changes.

Who will carry out the transformation work? The answer is Docker's Guardian process. Perhaps you already understand this sentence: Docker container is essentially one or more processes, and the father of the container process is the process of Docker. So, the execution of the work is not difficult to understand the: docker daemon process holding a docker mirror the JSON file, for container configuration corresponding to the environment and real operation docker mirroring the specified process, complete the docker container to create a real.

After the Docker container is running, the Docker image JSON file is out of action. At this time, the vast majority of Docker mirror function is: to provide a file system for the Docker container perspective, the process of internal access to the document resources.

Once again, back to the picture, we'll look at some of the special relationships between the container and the mirror. First, before it has been mentioned that the Docker image is hierarchical management, the management of the Docker container, the Docker image is still hierarchical management. Since there is already a process in the container, the process will read and write to the file in the file system, so it will involve a question whether the container will tamper with the contents of the Docker image.

Nature is not the answer. Unity is concerned, as above, all of the Docker mirror layers are read-only for the container, and the container for the write operation is absolutely not in the image.

Since it is so, the realization of the principle is very important. The reason: docker Guardian process on the docker mirroring the top, and then add a readable writing layer, container all write operations will effect to this layer. And if the docker container need to write low-level docker image file, then this will involve a called copy - on write mechanism, namely aufs jointly file system assurance: firstly this file from the docker mirror layer copy to read the top write layer, then the container process of reading and writing layer copy write operation. The container process is concerned, it can only see the top of the file.

That finally we come to talk about: Docker container file system perspective, in the end is not the existence of some content, not stored in the Docker image of the?

The answer is still yes.

Again, a little bit, Docker images are stored in a number of static files. These documents should in principle and container specific information and host information is completely decoupled. Then the Docker container does not exist in the Docker image content mainly has the following several points:

Content of virtual file system such as 1./proc and /sys

2 container hosts files, hostname files and resolv.conf files, these things the specific environment of information, in principle, should not be driven into the mirror.

The Volume path of the 3 container, this part comes from the perspective from the host to mount path inside the container

The 4 part of the device file

Write the picture here.

Welcome to the [Docker source analysis of the micro channel public number, more exciting upcoming.

Author: shlazww published in 12:51:59 2015/9/4Text link
Read: 130 comments: 0View comments
]]>
<![CDATA[[原]Docker镜像内有啥,存哪?]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47692745 Http://prog3.com/sbdm/blog/shlazww/article/details/47692745 Shlazww 2:38:14 2015/8/17 It is said that the important thing to say three times, then I express my personal point of view:Docker mirrorIs the soul of Docker.

The first two to speak on the Docker image of the description, has been from a macro point of view one or two. Once you master the Docker for the level of the management of the image, as well as the Docker mirror the size of the real situation, then come to understand the contents of the Docker mirror and storage, it is a lot easier.

Docker mirror content

There is always the first time for the Docker mirror image, since then, of course, there is little growth, the author's own understanding of the process may wish to share with you:

1 initial contact DockerI believe that a lot of fans will be like me, there is such a knowledge: Docker image represents a container file system content;

2 preliminary contact with the joint file systemThe concept of the joint file system, which makes me aware of the technology of image level management, is part of the contents of the container file system.

3 study the relationship between image and container: container is a dynamic environment, each layer image file belongs to static content, however Dockerfile in the env bike, volume, CMD and other content will eventually need to implement the operation of the environment of the container, and the content are not likely to lie directly to each layer image contains the contents of the file system, that part of the contents of this docker the how to manage?

In addition, in the above third steps, there is a situation, I believe we are not unfamiliar: a lot of the size of the mirror layer 0, the image layer does not exist within the contents of any file. This is how the same thing?

You can recall the "one figure to see the contents of the Docker container file system", the generation of the empty mirror, which refers to "update the image of the JSON file". In fact, the previous foreshadowing, hinting at the truth:Docker mirror contentMirror layer file contentandMirror JSON fileForm, whether static or dynamic information, Docker are updated in the JSON file.

JSON each layer of the image of the Docker file, are playing a very important role, and its main role is as follows:

1 record the contents of the dynamic information of the container in the Docker image

2 record the true difference between father and son Docker image

3 make up the lack of the integrity and dynamic content of the Docker image content

Docker mirror JSON file can be considered to be a mirror of the metadata information, its importance is self-evident, this series will be in the next article focuses on the analysis of Docker image JSON file. Please look forward to.

Docker mirror storage location

Docker mirroring the content of theoretical analysis, look at how many somewhat foggy, whether docker mirror layers of the file, or JSON file, read to slightly boring. If you can see the real environment in Docker, I believe that the understanding of the mirror technology will have a lot of help.

We went straight to the theme, starting with the storage of Docker mirror, look at theseMirror layer file contentandMirror JSON fileWhere are stored in. (below shows the experimental environment: host operating system for ubuntu:14.04, Docker version for 1.7.1, graphdriver type for aufs, only contains ubuntu:14.04 a mirror).

View mirror layer composition

We can pass the orderHistory ubuntu:14.04 dockerView ubuntu:14.04, the results are as follows:
Write the picture here.

Figure shows a total of 4 ubuntu:14.04 mirror image layer.

Mirror layer file content storage

The content of the Docker mirror layer is generally in the aufs root directory of the Docker path, for the /var/lib/docker/aufs/diff/, the specific circumstances are as follows:
Write the picture here.

The diagram shows the contents of the 4 mirror images of the mirror ubuntu:14.04, as well as the contents of the first level directory within each image layer. Need to pay extra attention to: there is no content in the image layer d2a0ecffe6fa.

Mirror JSON file storage

For each mirror layer, Docker will save a copy of the corresponding JSON file, JSON file storage path for /var/lib/docker/graph, ubuntu:14.04 all the image layer of the JSON file storage path is shown as follows:
Write the picture here.

In addition to the JSON file, we also see that each mirror layer also contains a layersize file, the file is mainly to record the total size of the image layer inside the file content. Since it comes to the mirror image JSON file, in order to pave the way, the following posted ubuntu:14.04 hollow mirror layer JSON d2a0ecffe6fa file:
Write the picture here.

Because of the instructions for a layer of the image corresponding to the Dockerfile CMD, so mirror the content is empty, and mirror the JSON file will update the CMD domain, to obtain the value of the new CMD in order to follow the through the mirror the container operation, using the updated CMD.

summary

Docker mirroring the essence of Federated file system. However, in addition, for image metadata management (i.e., mirror image JSON file) opened the mirror through docker directly run docker container shortcut.

Write the picture here.

Welcome attention[Docker source code analysisMicro channel public number, more exciting upcoming.

Author: shlazww published in 2:38:14 2015/8/17Text link
Read: 451 comments: 2View comments
]]>
<![CDATA[[原]深刻理解Docker镜像大小]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47375009 Http://prog3.com/sbdm/blog/shlazww/article/details/47375009 Shlazww 22:45:01 2015/8/9 Say good but if there is no law of the container, the Docker image, the Docker is more boring.

Do you still remember the first contact Docker when you drop the Hub Docker from the mirror it? On the basis of that virgin image, you run a container of a career in a virgin container. Mirroring the cornerstone of the role has been very clear, in the world of Docker, can be said to be: Image No, Container No.

Further thinking about the Docker mirror, we may soon be associated with the following categories of images:

1 system level image: such as Ubuntu mirror, CentOS mirror and Debian container, etc.;

2 tool stack image: such as Golang mirror, Flask mirror, Tomcat mirror, etc.;

3 service level mirroring: such as MySQL mirror, MongoDB mirror, RabbitMQ mirror, etc.;

4 application level image: such as WordPress mirror, DockerRegistry mirror, etc..

Numerous image and want to run the docker container must be docker mirror; want docker image, we must first download the docker mirror; since involves a download mirror docker, there will naturally be docker mirrored storage. When it comes to Docker mirror storage, then we first talk about the knowledge of Docker image size.

The following will be from three angles to analyze the size of the Docker image:Dockerfile and mirror image,Joint file systemas well asMirror sharing relationship.

Dockerfile and mirror image

Dockerfile by a number of instructions, with the in-depth study of the relationship between Dockerfile and the mirror, soon we will find that each of the instructions in Dockerfile will correspond to a layer of Docker image.

Continue to take the following Dockerfile as an example:

FROMUbuntu:Fourteen point zero four
ADDRun.sh /
VOLUME/Data
CMD["./run.sh"]

Through the build Dockerfile above docker, will be on the basis of the Ubuntu:14.04 mirror, adding three separate images, followed by three different commands. The schematic diagram of the image is as follows:

image

With a preliminary understanding of the relationship between Dockerfile and the mirror, we are further connected to the size of each layer of the image.

Have to say, in the hierarchical management of Docker images, there are many layers of the size of 0. The size of the mirror layerNot for 0In the final analysis, the reason is: to build a Docker mirror, the current file system caused by the update. There are two major modifications to the update:

1.ADD or COPY command: the role of COPY or docker is to add content to the container in the build ADD build mirror image, as long as the content is added successfully, the current build of the layer image is to add the content of the size, such as the above commandsRun.sh ADD /, the size of the new building that is the size of the file run.sh.

2.RUN commandThe function of the RUN command is to run a command in the current empty mirror layer, and if the command needs to update the disk file, then all the updates are stored in the current image layer. For example:Echo DaoCloud RUNCommand does not involve changes to the content of the file system, so that the size of the current mirror layer is 0 after the command is run;WGet http://abc.com/def.tar RUNCommand will download the compressed package to the current directory, so the current level of the size of the image: the file system content of the incremental changes, that is, the size of the def.tar file.

Joint file system

Dockerfile in the command and mirror layer one one corresponds, then it means that the build docker is completed, the total size of the mirror image = the sum of the size of each layer of the mirror? The answer is yes. Still in the above image, for example: if ubuntu:14.04 mirror of the size of 200MB, and run.sh size to 5MB. Then the above three mirror from top to bottom, each layer of the size of the followed by 0, 0 and 5 MB, then eventually build the image size indeed for 0+0+5+200=205MB.

Although the size of the final image is the sum of each layer, it is required to pay extra attention to the size of the Docker image.Does not meanContents of the file system in the container size (not including /proc, /sys and mount the file, virtual file). For one reason, there is a great relationship between the file system and the joint file system.

First look at this simple example of Dockerfile (if the current directory in the Dockerfile has a 100MB compressed file compressed.tar):

Ubuntu: FROMFourteen point zero four
ADDCompressed.tar/
RM /compressed RUN.tar
ADDCompressed.tar/

Ubuntu 1.FROM: the size of the mirror image 200MB is ubuntu:14.04;

Compressed.tar 2.ADD /Compressed.tar file is 100MB, so the size of the current mirror layer is 100MB, the total size of the image is 300MB;

RM /compressed.tar 3.RUN: delete files compressed.tar. This deletion does not delete compressed.tar under a layer of file, only will in the current layer produced a compressed.tar delete marker, ensure that through the layer will not see compressed.tar, so the current image layer size is 0, the total size of the image to 300MB.

Compressed.tar 4.ADD /Compressed.tar file is 100MB, so the size of the current mirror layer is 300MB+100MB, the total size of the image is 400MB;

After the analysis, we found that the total size of the mirror image is 400MB, but if we run the image, we can quickly find out the root directory of the container.Du -shAfter that, the value is not 400MB, but 300MB or so. The main reason is: the nature of the joint file system to ensure that the two haveCompressed.tarThe mirror layer of the file, just the container to see a. At the same time this also illustrates a situation, when the user is based on a very large, even several GB mirror image of the operation of the container, the container inside view the root directory size, found that only 500MB less than, set smaller.

Analysis at this point, there is a point we need to pay attention to: the image size and the size of the container has a essential difference.

Mirror sharing relationship

Docker mirror said big, small is not small, but once the total number of the mirror, it is not on the local disk to cause a lot of storage pressure? Average each mirror 500MB, wouldn't it be 100 images that need to be prepared for the 50GB storage space?

The results are often not as we imagine, Docker in the mirror reuse design is very good, greatly saving the image occupied disk space. The multiplexing of Docker images is mainly reflected in: multiple different Docker images can share the same image layer.

Assuming that there is only one ubuntu:14.04 mirror in the local image store, we use two Dockerfile to illustrate the mirror reuse:

FROMUbuntu:Fourteen point zero four
Apt- RUNGetUpdate
Ubuntu: FROMFourteen point zero four
ADDCompressed.tar/

Assuming that the final build docker build up the mirror names are image1 and image2, because the two Dockerfile are based on ubuntu:14.04, therefore, image1 and image2 these two mirror images are multiplexed with a mirror image ubuntu:14.04. hypothesisApt-get update RUNModify the file system content for 20MB, the final local three mirror the size of the relationship should be as follows:

Ubuntu:14.04200MB

Image1: 200MB (ubuntu:14.04) +20MB=220MB

Image2: 200MB (ubuntu:14.04) +100MB=300MB

If only the size of the simple accumulation of three mirror, the results should be: 200+220+300=720MB, but due to the existence of mirror multiplexing, occupied by the actual amount of disk space is: 20020+100=320MB, a full save 400MB of disk space. Here, it is sufficient to demonstrate the great benefits of mirror reuse.

summary

Learning Docker at the same time, there are often three parts of the content is not open, that is, Dockerfile, Docker image and Docker containers, analysis of the size of the Docker mirror is also true. The Docker image size, seemingly unremarkable, but to optimize the image, the container must be involved in the contents of the disk quota.

This series will be analyzed by the following article Docker mirror image:

1 a deep understanding of the size of the Docker image

2 in fact, commit docker is very simple

3 have to say that the save docker and export docker difference

4 why some container files can not move

5 break Namespace MNT container VOLUME

Write the picture here.

Welcome to the Docker source analysis of the micro channel public number, more exciting upcoming.

Author: shlazww published in 22:45:01 2015/8/9Text link
Read: 535 comments: 1View comments
]]>
<![CDATA[[原]Docker源码分析(七):Docker Container网络 (上)]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47284675 Http://prog3.com/sbdm/blog/shlazww/article/details/47284675 Shlazww 22:58:06 2015/8/4 1 preface (what is Container Docker)

Now, docker technology is popular, everyone try and fun docker, at the same time, certainly can not be separated from a concept, that is "container" or "docker container". So we firstly from the angle of realization, to look at the "container" or "Docker Container" in the end what.

Gradually familiar with docker after, you will deeply feel: applications within the docker container deployment and operation is very convenient, as long as there is Dockerfile, one click application deployment environment is definitely not the Arabian nights; docker container within a running application can be subject to resource control and isolation, greatly satisfy the cloud computing era. Needless to say, these characteristics of Docker, the traditional mode of application is completely do not have the. However, behind these eyes a bright characteristic, in the end is who in "blink", in the end is who can support docker these characteristics? Do not know this time, we will think about the powerful Linux kernel.

In fact, this is a large part of the function needs to be attributed to the Linux kernel. Let's see what is Docker to Linux from the angle of the core, first from the Docker of Container. About Container Docker, the experience of the developer first feel sure there are two points: the internal can run applications (processes), as well as providing an isolated environment. Of course, the latter is certainly one of the reasons the industry called the "container".

Since Container Docker can run the process, then we first look at the relationship between the Container Docker and the process, or the relationship between the container and the process. First of all, I put forward such a question for you to think about whether the container can be separated from the process of existence". In other words, can create a container, and there is no process inside the container.

It can be said that the answer is negative. Since the answer is no, it is not possible to have a container, and then again the process, then the problem has come, "the container and the process is born together, or the first process and then the container?" It can be said that the answer is the latter. The following will slowly explain the reasons.

Explain reason why the question "whether the container can exist out of process" before, I believe everyone to say don't dissent: the docker create a docker container is a container, and the container provides process group isolated operating environment. So the problem is that the container in the end is what way to achieve the process of operation environment of the "isolation"". At this time, it is the turn of the Linux kernel technology grand debut.

When it comes to the "isolation" of the running environment, I believe that we are sure that the kernel characteristics of namespace Linux and CGroup will not be unfamiliar. Namespace is primarily responsible for namespace isolation, while CGroup is primarily responsible for resource usage constraints. In fact, it is precisely the combination of these two magical characteristics of the core, to ensure that the Container Docker isolation". So, namespace and CGroup and the process of what is the relationship? The answer to the question can be explained in the following order:

  1. When a child process is created by fork, the parent process uses the namespace technology to implement the child process and other processes (including the parent process);
  2. After the child process is created, the use of CGroup technology to process the child process, the realization of the process of resource use restrictions;
  3. System in the process of the sub namespace internal, create the need to isolate the environment, such as the isolation of the network stack, etc.;
  4. Namespace and CGroup two technologies are used, the process of the "isolation" environment is really established, then the "container" was born!

Birth from the point of view of the Linux kernel analysis of the container, streamlined processes such as the above four steps, and the four steps also happens to skillfully describes the namespace and CGroup both technology and process, and process and container. The relationship between the process and the container, nature is: the container can not be separated from the process, the first process, after the container. However, it is often said that "the use of Docker to create Container Docker (containers), and then the internal operation process in the container". In this regard, from the perspective of easy to understand, this can be understood, because the word "container", the existence of the word itself is more abstract. If you need a more accurate representation, then can be: "use docker create a process. For this process to create isolated environment. This environment can be said docker container (container), and then the inside of the container is running a user application process." Of course, the author of the original intention is not to deny a lot of people for the Container Docker or container, but hope and readers together to explore the Container Docker underlying technology to achieve the principle of.

For Container Docker or the container has a more specific understanding, I believe we will soon be the eye to locate the namespace and CGroup these two kinds of technology. Linux kernel of these two technologies, can play such a significant role, can not help but praise. So here we have a brief introduction to the two from the perspective of Container Docker implementation process.

First, talk about the usage of namespace in the creation of the container, first from the user to create and start the container. When the user creates and starts the container, Daemon fork will Docker the first process in the container A (for the time being called the process A, which is the Zi Jincheng Daemon Docker). Docker daemon executing fork, in the clone system call will incoming five parameter markers clone CLONE_NEWNS, clone CLONE_NEWUTS, clone CLONE_NEWIPC, clone CLONE_NEWPID and clone CLONE_NEWNET (currently docker 1.2.0 is not fully supports user namespace). The clone system call once introduced these parameters logo, sub process will no longer and the parent process sharing the same namespace, but by the Linux to create a new namespace (namespace), so as to ensure that the child and the parent process using isolated environment. In addition, if the child process fork once again A out of the sub process B and C, while fork did not pass into the corresponding namespace parameter flag, then the child process B and C will share the same command space with A (namespace). If Daemon Docker once again create a Container Docker, the first process in the container for the D, and D and fork out of the sub process E and F, then the three processes will also be in a new namespace. The namespace of the two containers are different from the Daemon namespace Docker. The simple schematic diagram of Docker on namespace is as follows:

Seventeen
Fig. 1.1 schematic diagram of namespace in Docker
Besides CGroup, we all know that you can use CGroup as a process group to do the control of resources. Namespace is different is that the use of CGroup is not in the process of creating the container to complete, but in the process of creating the container after the use of CGroup, so that the container process is in the state of resource control. In other words, the application of CGroup must wait until the first process in the container is created to achieve the. When the container process is created, Daemon Docker can be informed of the process of PID information within the container, and then the PID will be placed in the CGroup file system to specify the location, do the appropriate resource constraints.

It can be said that the Linux kernel namespace and CGroup technology, to achieve the isolation and restriction of resources. So for this isolation and limited environment, whether it is necessary to configure other essential resources. This time the answer is yes, the network stack is at this time for the container to add. When the container process finishes creating isolated operating environment, found the container although already in an isolated network environment (i.e., the new network namespace), but the process is not independent of the network stack can be used, such as independent of the network interface device. At this point, Daemon Docker Container Docker will be required for one one of the resources for its complete. Network, you need to specify the user in the network model, the configuration of the corresponding network resources Container Docker.

Container 2.Docker network analysis content arrangement

Docker container network will from the point of view of the source code, analyze docker container from scratch, create a docker container network context. Container Docker network creation process can be simplified as shown below:

Seventeen
Figure 2.1 Container Docker network to create a flow chart
Container Docker network analysis of the main contents of the following 5 parts:

  1. Container Docker network model;
  2. Client Docker configuration container network;
  3. Daemon Docker creates the container network flow;
  4. Execdriver network execution process;
  5. Libcontainer implementation of kernel mode network configuration.

Container Docker network creation process, the use of the networkdriver module is not the focus, the content of the analysis does not involve networkdriver. Here many readers will certainly have doubts. Needs to be emphasized is that networkdriver in docker: first, docker daemon create network environment, initialize the docker daemon network environment (for details, you can view the docker source analysis "series of the sixth), such as the creation of docker0 bridge etc.; second, assign IP addresses to docker container and docker container do port mapping etc.. While with the Container Docker network to create the relevant content is very small, only in the bridging mode, for the Container Docker network interface equipment assigned a available IP address.

This article for the "Docker source code analysis" series seventh - Container Docker network (on).

Container 3.Docker network model

As mentioned above, Docker can create an isolated network environment for Container Docker, in isolated network environment, Container Docker independent use of private network. Believe that a lot of Docker developers are also experienced Docker network characteristics in this area.

In fact, Docker in addition to Container Docker to create an isolated network environment, the same has the ability to create a shared network environment for Container Docker. In other words, when developers need docker container with the host or other containers of network isolation, docker can meet this demand; and when developers need docker container with the host or other containers sharing network, docker can also meet this demand. In addition, Docker can not create a network environment for Container Docker.

Summary of Container Docker network, you can draw 4 different modes: Bridge bridging mode, host mode, container other mode and none mode. The following is a preliminary introduction to 4 different network models.

3.1 bridge bridging mode

Container bridge Docker bridge mode can be said to be the most commonly used network model Docker developers. Brdige bridge mode for Container Docker to create an independent network stack, to ensure that the process group in the container to use a separate network environment, the realization of the network between the container, container and host host isolation. In addition, docker by host bridge (docker0) to connected container within the network stack and the host's network stack, the realization of network communication of the container with the host and the outside world.

Container bridge Docker bridging mode can refer to the following figure:

Seventeen
Fig. 3.1 schematic diagram of Container Bridge Docker bridge mode
The main steps of the Bridge bridging mode are as follows:

  1. Daemon Docker uses pair Veth technology to create two virtual network interface devices on the host machine, assuming that the veth0 and veth1. The characteristics of pair Veth technology can ensure that no matter which Veth receives the network message, the message will be transmitted to the other party.
  2. Docker Daemon veth0 Docker Daemon docker0 to create additional bridge. To ensure that the host host network messages can be sent to the veth0;
  3. Daemon veth1 will be added to the Container Docker Docker under the namespace, and was renamed eth0. In this way, to ensure the host's network packet if sent to veth0, immediately received by the eth0, realize the host to docker container network connectivity; at the same time, but also to ensure docker container used alone eth0, realize the isolation of the vessel network environment.

Bridge bridging mode, from the principle of Container Docker to the host machine and other machines and the network connectivity. However, due to the IP address of the host's IP address and Veth pair are not in the same segment, so only rely on Veth pair and namespace technology, is not enough to is outside the host network take the initiative to find docker container. In order to service the docker container can let host outside the perception of the world to the interior of the vessel exposed, docker using nat (network address translation, network address conversion), let the world outside the host can take the initiative to network message is sent to the container inside.

Specifically, when the Container Docker requires exposure to the service, the internal service must monitor the container IP and port number port_0, so that the outside world to initiate a request for access to the initiative. Due to the world outside the host, only know the network address of the host eth0, and does not know the docker container's IP address, even if know docker container's IP address, from the perspective of a two layer network, the outside world can not directly through the docker container's IP address access to the application in the interior of the container. Therefore, NAT uses the Docker method, and the port of the service monitor inside the container is bound to a certain port port_1 host ".

As a result, the process of external access to Container Docker internal services is:

  1. External access to the host host IP and host of the port port_1;
  2. When such a request is received by the host, because of the existence of DNAT rules, the request destination IP (IP host eth0) and destination port port 1 conversion, converted to IP of the container and the container port 0;
  3. Because the host knows the container IP, the request can be sent to the pair veth;
  4. Pair veth0 Veth to send the request to the container internal eth0, and ultimately to the internal services to deal with.

Using the DNAT method, you can make the world outside the host Docker host active access to Container Docker internal services. So Container Docker how to access the host outside the host of the world. The following is a brief analysis of the process of Container Docker access to the world outside of the host machine:

  1. Container Docker internal process was informed of the host service outside the IP address and port port_2, so Container Docker request. The independent network environment of the container guarantees that the source IP address of the request is the container IP (that is, the container's internal eth0), and the Linux kernel automatically allocates a source port for the process (assuming port_3);
  2. A request by the other end, the container eth0 sent to Veth pair at the veth0, is also arrived at the bridge (docker0);
  3. Docker0 Bridge opened the datagram forwarding function (/proc/sys/net/ipv4/ip_forward forward, so will request eth0 is sent to the host; and
  4. Host processing request, the use of SNAT on the request for the source address IP conversion, the source address IP (container IP address) is converted to host IP eth0 address;
  5. Host will be after the SNAT conversion of the message through the request of the destination IP address (host computer outside the world's IP address) to send to the outside world.

Here, a lot of people will ask: the docker container interior initiated external network request, when requests arrive the host of SNAT and send it to the outside world, when the outside world in response to the request and response docker of host's IP address, the destination IP address in the message must be the response message back to the host, the host is to be transferred to docker container?? On such a response, due to the port_3 port is not in the host host to do the corresponding DNAT conversion, in principle, will not be sent to the inside of the container. Why say for such a response, will not do DNAT conversion. The reason is very simple, and DNAT conversion is done for inside the container service listens on a specific port. The port is used for monitoring services, and container is internally initiated the request message, the source port number is certainly not occupied port listening service, so internal container initiated request response not through DNAT in the host.

In fact, this part of the content is to be completed by the iptables rules, the specific rules of iptables are as follows:

-I FORWARD -o docker0 iptables -m conntrack --ctstate RELATED ESTABLISHED, -j ACCEPT

The meaning of this rule is that in the host to network data packets docker0 bridge. If the data message and the connection has been established, the unconditional acceptance, and by the Linux kernel will be to send the original connection, a return to the docker inside the container.

Above is a brief introduction of bridge bridging mode in Container Docker. It can be said that the Bridger bridging mode from a functional point of view to achieve two aspects: first, so that the container has an independent, isolated network stack; second, so that the container and the host computer to establish the world through the NAT communication.

However, the bridge bridging mode of Docker Container in use, not for developers arranged everything. The most obvious is that the docker container does not have a public IP, and host eth0 is not in the same segment. The result is that the world outside of the host computer can not communicate directly with the container. Although NAT mode through an intermediate processing to achieve this point, but NAT mode still exists problems and inconveniences, such as: the container needs compete for port on the host and visitors to the service in the interior of the container to use service discovery informed service external port. In addition, the NAT model is implemented in the three layer network, so it will certainly affect the transmission efficiency of the network.

3.2 host model

The host mode in Container Docker is very different from the bridge bridge mode. The biggest difference is that the host model does not create an isolated network environment for the container. And the reason that the host mode, is because the docker's container will host and host share the same network namespace, so the docker container can and the host, host eth0, realize the communication with the outside world. In other words, Container IP Docker address is host IP eth0 address.

Container host Docker network model can refer to the following figure:

Seventeen
Fig. 3.2 schematic diagram of Container host Docker network model
Above the left of the Container Docker, which uses the host network model, while the other two Container Docker still continue to use the brdige bridge model, the two models exist in the host is not contradictory.

Docker container of host network model in the implementation process, because it does not need the additional bridge and virtual network adapter, so not involving docker0 and Veth pair. As mentioned in the introduction of namespace above, the parent process in the creation of the child process, if you do not use the CLONE_NEWNET parameter logo, then the child process will be created with the parent process to share the same network namespace. Docker is the use of this simple principle, in the process to create the process of starting the container, no incoming parameters of clone CLONE_NEWNET logo, realize the docker container and the host of sharing the same network environment, that is to realize the host network mode.

It can be said, Container Docker network model, the host model is a good complement to the bridge bridge model. Host mode using Container Docker, you can directly use the host's IP address to communicate with the outside world, if the host eth0 is a public IP, then the container also has the public IP. At the same time, the port of the service in the container can also use the host's port, without additional NAT conversion. Of course, there is such a convenient, will certainly lose some of the other characteristics, the most obvious is the weakening of the Container Docker network environment, that is, the container is no longer a separate, independent network stack. In addition, using host mode docker container although can let in the interior of the container services and traditional indifference, no transformation, but due to the weakening of network isolation, the container will share the competition in the network stack and host; in addition, inside the container will no longer have all the resources of the port. The reason is that part of the port resources has been services occupying the host itself, and part of the port has been used to bridge network model of the container port mapping.

3.3 container other mode

Container other container Docker network model is a more special network model in Docker. The reason is called the "container other model", because of this model under the Container Docker, will use other containers of the network environment. It is called "special", because the network isolation of the container in this mode will be between the bridge bridge mode and the host mode. Container Docker shared network environment of other containers, there are at least two containers do not exist between the network isolation, and these two containers and host and other containers in addition to the existence of network isolation.

Container other container Docker network model can refer to the following:

Seventeen
Fig. 3.3 schematic diagram of Container other container Docker network model

On the right side of the Container Docker that uses the container other network model, which can be used in the network environment is the left Container brdige Docker bridge model under the network.

Docker container other container network model in the implementation process, does not involve the bridge, the same also do not need to create a virtual network adapter Veth pair. Completion of the container other network model only requires two steps:

  1. Find container other (that is, the container needs to be shared network environment) of the network namespace;
  2. The newly created Container namespace (also need to share the container of other networks), the use of container namespace other.

Container other container Docker network model, can be used to better serve the communication between the container.

In this mode, the Container Docker can be accessed through the namespace to other containers under the localhost, the transmission efficiency is higher. Although a plurality of containers share a network environment, the overall formation of a plurality of containers is still isolated from the host and other containers. In addition, this model also saves a certain amount of network resources. But it should be noted that it does not improve the communication between the container and the host outside of the world.

3.4 none model

Container Docker fourth network model is the none model. As the name suggests, the network environment for the none, that is not Container Docker any network environment. Once Container none uses the Docker network model, then the container can only use the loopback network equipment, there will be no other network resources.

Can say none mode docker container do little network setting, but as the proverb goes "less is more", without the network configuration, as a docker developer to in this foundation to do other infinite number of possible network custom development. This also happens to reflect the opening of the Docker design concept.

4 author introduction

Sun Hongliang,DaoCloudNew team member, software engineer, VLIS Laboratory of Zhejiang University. Graduate school during active in PAAS and docker open source community, in-depth study and enrich the practice of cloud foundry, good at analysis of the underlying platform code, on the platform of the distributed architecture has some experience, has written a lot of depth technology blog. At the end of 2014 to join the DaoCloud partner to join the team, committed to the spread of Docker based container technology, to promote the pace of the application of the Internet in the container. Mailbox:Allen.sun@daocloud.io

Welcome to pay attention to the Docker source code analysis of the public number

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 22:58:06 2015/8/4Text link
Read: 167 comments: 0View comments
]]>
<![CDATA[[原]Docker源码分析(六):DOCKER DAEMON网络]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47283911 Http://prog3.com/sbdm/blog/shlazww/article/details/47283911 Shlazww 22:27:22 2015/8/4

Abstract:

The container characteristics and image characteristics of Docker have brought many benefits for Docker practitioners, however, the network characteristics of Docker can not satisfy the users. This article analysis the docker daemon create the detailed process of the network environment from the docker's network model, especially in the analysis of docker bridging mode created for docker container create network environment to pave the way.

1 Preface

Docker as an open source lightweight virtual container engine technology, has brought a new development model to the field of cloud computing. Docker with the container technology to completely release the power of lightweight virtualization technology, so that the expansion of the container, the application of the operation has become unprecedented convenience and efficiency. At the same time, Docker with a powerful mirror technology, so that the application of the distribution, deployment and management has become unprecedented convenient. However, Docker, after all, is a relatively new technology, in the world of Docker, the user is not once and for all, the most typical is the Docker network problem.

There is no doubt that, for Docker managers and developers, how to effectively and efficiently manage the interaction between the Docker container and Docker container network has been a huge challenge. At present, in the field of cloud computing, the vast majority of systems have adopted distributed technology to design and implement. However, in the original ecology of the Docker world, Docker network is not equipped with the ability of the host, which is more or less lags behind the rapid development of Docker in the field of cloud computing.

In industry, the solution of Docker network problem is imperative under this environment, many IT companies have developed their own new products to help improve the Docker network. These enterprises lack Google like Internet leader enterprise, at the same time, there are many start-ups first attack, in the forefront of unremitting exploration. These new products, Google launched the container management and arrangement of the open source project kubernetes, Zett.io company development through the network of virtual connection cross weave the host container tools, coreos team for kubernetes design of network coverage tools flannel, scheme Pipework docker official Engineer J R's me Petazzoni design their own SDN network solutions, and SocketPlane project etc..

For Docker managers and developers, Docker's inter host communication capabilities are important, but Docker's own network architecture is also important. Only in-depth understanding of the Docker's own network design and implementation, in order to extend the Docker based on the ability to host the host.

Docker own network mainly contains two parts: Daemon Docker network configuration, Container Docker network configuration. This paper mainly analyzes the network of Daemon Docker.

2 Daemon Docker network analysis content arrangement

In this paper, from the source point of view, the analysis of Daemon Docker in the starting process, the network environment for the Docker configuration, the chapter arrangements are as follows:

  1. Daemon Docker network configuration;
  2. Run Daemon Docker network initialization task;
  3. Create Docker bridge.

This article for the "Docker source analysis series" sixth - Daemon Docker network, the seventh will be arranged for Container Docker network.

3 Daemon Docker network configuration

In Docker environment, the Docker administrator has the right to configure the network model of Daemon Docker running process. About Docker network model, we are most familiar with the "bridge" model should be. Below the bridge model, the Docker network topology map (including the Daemon Docker network environment and Container Docker network environment):

Seventeen
Fig. 3.1 schematic diagram of Docker network bridge
However, "bridge" is the most commonly used mode in Docker network mode. In addition, Docker also provides users with more options, the following will be one one.

3.1 Daemon Docker network configuration interface

Daemon Docker every start of the process, will initialize its own network environment, so that the network environment to provide network communications services for Container Docker.

Docker administrator configure Docker network environment, you can start Daemon Docker, through the interface provided by the Docker to complete. In other words, you can use the docker binary executable file, run -d docker and add the appropriate flag parameters to complete.

Among the flag parameters are EnableIptables, EnableIpForward, BridgeIface, BridgeIP and InterContainerCommunication. The five parameters are defined in the./docker/daemon/config.go, the specific code is as follows:

Flag.BoolVar (&config.EnableIptables), "#iptables", "[]string{", "-iptables", "", "true", "Docker's addition rules Enable of iptables" ()
Flag.BoolVar (&config.EnableIpForward), "#ip-forward", "[]string{", "-ip-forward", true, "Enable", "" ("net.ipv4.ip_forward")
Flag.StringVar (&config.BridgeIP), "#bip", "[]string{", "-bip", "", "", "" this CIDR notation address for the network bridge's Use IP not compatible with -b "()
Flag.StringVar (&config.BridgeIface), "B", "[]string{", "-bridge", "", "" "", "" containers to a pre-existing network bridge\nuse'none'to Attach disable container networking "()
Flag.BoolVar (&config.InterContainerCommunication), "#icc", "[]string{", "-icc", "", true, "inter-container communication Enable"

The following describes the role of these 5 flag:

  • EnableIptables: make sure that Docker has the added permission for the iptables rule on the host host;
  • EnableIpForward: to ensure that the net.ipv4.ip_forward can be used, so that multiple network interface device mode, the data can be transmitted between the network devices;
  • BridgeIP: the Docker Daemon boot process, as in the environment of the network bridge configuration CIDR network address;
  • BridgeIface: docker network environment to specify the specific communication bridge. If the BridgeIface whose value is "None", without creating a bridge services docker container, closed docker container network capacity.
  • InterContainerCommunication: to ensure that the communication between the Docker container can be completed.

In addition to the Docker will be used to the 5 flag parameters, Docker in the creation of the network environment, but also the use of a DefaultIP variable, as follows:

Opts.IPVar (&config.DefaultIp), "#ip", "[]string{", "-ip", "0.0.0.0", "Default", "IP address to use when Binding container ports" ()

The variable's role is to use the IP as the default DefaultIp address when the port of the container is bound.

With the above Daemon Docker network background knowledge, the following focuses on the analysis of the use of BridgeIP and BridgeIface, in the start of Daemon Docker network configuration:

Eighteen
In depth understanding of BridgeIface and BridgeIP, and proficiency in the use of the corresponding flag parameters, that is, how to configure the Daemon Docker network environment. Need to pay special attention is that the Daemon Docker network and Container Docker network there is a big difference. Daemon Docker to create a network environment for Container Docker, Container Docker network needs to provide support for Daemon Docker network, but not the only. A vivid example, docker daemon can create docker0 bridge, for docker container bridge model to provide support, however docker container still can according to user needs to create your own network, the docker container of the network can be bridged mode network. At the same time, it can directly share using the host's network interface, in addition to other modes, in the docker source analysis "series article 7 -- docker container network in detail.

3.2 Daemon Docker network initialization

As the last section said, Docker administrators can be related to the network with the flag parameters BridgeIface and BridgeIP, to create a network environment for Daemon Docker. The most simple and docker administrator by execution "docker - D" will have completed the run docker daemon, and docker daemon at boot time, according to the above two flags parameter value, create the corresponding network environment.

Daemon Docker network initialization flow chart is as follows:

Nineteen
Figure 3.2 Daemon Docker network initialization flow chart
Daemon Docker network initialization process in general, it is based on the analysis of the flag parameters to determine what type of network environment in the end. From the flow chart, we can know that the Daemon Docker to create a network environment, there are two branches, it is not difficult to find a branch representative are: Docker to create a network drive, as well as the Docker network does not do any operation.

Following with reference to Daemon Docker network initialization flow chart specific analysis implementation steps.

3.2.1 start Daemon Docker transfer flag parameters

Users start Daemon Docker, and the command line in the desired flag parameters of the incoming.

3.2.2 analytic network flag parameters

Flag package to parse the command line flags parameter, which and docker daemon network configuration related flags parameter has five, respectively is: EnableIptables, EnableIpForward, BridgeIP, BridgeIface and InterContanierCommunication introduced various flags parameter role above existing.

3.2.3 pretreatment flag parameters

Pre process and network configuration related flag parameter information, including the detection of configuration information compatibility, as well as to determine whether to create a Docker network environment.

First check whether the configuration information that is not compatible with each other, the source is located./docker/daemon/daemon.go#L679-L685.

There are two types of compatibility information in this section. The first is the compatibility of BridgeIP and BridgeIface configuration information, the specific performance for the user to start Daemon Docker, if the same specified value of BridgeIP and BridgIface, then there is a problem of compatibility. Reasons for both belong to the exclusion of. In other words, if the user specifies the device name of the new bridge, so the bridge has been in existence, without the IP address of the designated bridge BridgeIP; if the user specifies the new bridge network IP address BridgeIP. So the bridge must also not to build successful, then docker Daemon in the new bridge using the name of the default bridge "docker0". Specific as follows:

For mutually incompatible config options / / Check
If config.BridgeIface! "" = = "{& & config.BridgeIP!
Nil return, fmt.Errorf ("specified -b You & --bip, exclusive options. Please mutually specify only one.")
}

The second is the compatibility of EnableIptables and InterContainerCommunication configuration, specifically refers to the two flag parameters can not be specified at the same time as false. The reason is very simple, if the specified false is InterContainerCommunication, then that Daemon Docker does not allow the creation of the Docker container to communicate with each other. But in order to achieve the above purpose, Docker is the use of iptables filtering rules. Therefore, once again set the EnableIptables for the false, the use of the closure of iptables, that is, the results of a self contradictory. Code as follows:

If! Config.EnableIptables & & {config.InterContainerCommunication!
Nil return, fmt.Errorf ("specified --iptables=false with --icc=false. uses ICC You iptables to function. Please set --icc or --iptables to true.")
}

Check the system configuration information compatibility issues, Daemon Docker will then determine whether the need for Daemon Docker configuration network environment. The basis for judging whether the value of BridgeIface is equal to the value of DisableNetworkBridge, DisableNetworkBridge in the./docker/daemon/config.go#L13Is defined as the amount of const, the value of the string none". Therefore, if BridgeIface "None", is DisableNetwork is true, the final docker daemon will not create network environment; if BridgeIface "None", is DisableNetwork is false, the final docker daemon need to create a network environment (bridging mode).

3.2.4 determine the Docker network model

Docker network mode is determined by the configuration information DisableNetwork. Because the value of DisableNetwork has been obtained in the last link, this link can determine the Docker network model. This part of the source code implementation is located./docker/daemon/daemon.go#L792-L805, as follows:

If! Config.DisableNetwork!
Job: = eng.Job ("init_networkdriver")

Job.SetenvBool ("EnableIptables", config.EnableIptables)
Job.SetenvBool ("InterContainerCommunication", config.InterContainerCommunication)
Job.SetenvBool ("EnableIpForward", config.EnableIpForward)
Job.Setenv ("BridgeIface", config.BridgeIface)
Job.Setenv ("BridgeIP", config.BridgeIP)
Job.Setenv ("DefaultBindingIP", config.DefaultIp.String ())

Err if: = err (); job.Run! = nil {
Nil err, return
}
}

If DisableNetwork is false, the need to create a network environment, the specific pattern for creating Docker bridge model. The steps to create a network environment are:

  1. Create a job named "init_networkdriver";
  2. For the job configuration environment variables, set the environment variables are EnableIptables, InterContainerCommunication, EnableIpForward, BridgeIface, BridgeIP and DefaultBindingIP;
  3. Run job.

Run the "init_network" is to create a Docker bridge, this part will be detailed in the next section analysis.

If DisableNetwork is true. The description does not need to create a network environment, the network model belongs to the none model.

Above is all the process of Daemon Docker network initialization.

3.3 create Docker Bridge

Docker network is often the most frequently mentioned topic Docker developers. The most commonly used mode in Docker network is bridge bridge mode. This section will create a detailed analysis of the Docker bridge creation process.

Through the implementation of "init_network" the job Docker bridge to complete the operation to create." "Init_network" is implemented as a function of InitDriver, which is located in the./docker/daemon/networkdriver/bridge/driver.go#L79, the running process is as follows:Twenty

Figure 3.3 Docker Daemon create the bridge flow chart

3.3.1 extraction of environmental variables

In the realization of the InitDriver function, Docker first extract the "init_networkdriver" environment variables of the job. Such a total of 6 environmental variables, the role of the above has been described in detail. Specific implementation code is:

(VaR
*net.IPNet network
EnableIPTables = job.GetenvBool ("EnableIptables")
ICC = job.GetenvBool ("InterContainerCommunication")
IpForward = job.GetenvBool ("EnableIpForward")
BridgeIP = job.Getenv ("BridgeIP")
)

DefaultIP if: = job.Getenv ("DefaultBindingIP"); defaultIP! = "" {
DefaultBindingIP = net.ParseIP (defaultIP)
}

BridgeIface = job.Getenv ("BridgeIface")

3.3.2 Docker bridge device name

After the extraction of job environment variables, then determine the name of the final use of Docker bridge device. Therefore, docker created in the first a bool variable named usingDefaultBridge meaning whether to use default bridge equipment. The default value is false. Then, if bridgeIface environment variable value is null, then the user starts the docker, without specifying the particular bridge device name, therefore docker first will usingDefaultBridge set to true, and then use the default bridge device name DefaultNetworkBridge, namely docker0; if bridgeIface value is not empty, is judge condition does not hold, continue down the execution. This part of the code is implemented as:

UsingDefaultBridge: = false
If {bridgeIface = = ""
UsingDefaultBridge = true
BridgeIface = DefaultNetworkBridge
}

Find the bridgeIface bridge equipment

Determine the bridgeIface docker bridge equipment, docker first by bridgeIface device name in the host to find the device is real. If there is, to return to the bridge device IP address, if not, it will return nil. Implementation code is located in./docker/daemon/networkdriver/bridge/driver.go#L99, as follows:

Err, addr: = networkdriver.GetIfaceAddr (bridgeIface)

GetIfaceAddr implementation in./docker/daemon/networkdriver/utils.go and implementation steps for: first by golang net bag method for InterfaceByName gets name for bridgeIface bridge equipment, and obtained the following results:

  • If the named bridgeIface bridge device does not exist, returns error;
  • If there is called the bridgeIface bridge device, return to the bridge equipment IP address.

Needs to be emphasized is that GetIfaceAddr function returns the error, indicating that the host does not exist bridgeIface the bridge device. And such results will have two different situations: first, the user specifies the bridgeIface, so usingDefaultBridge is false, and the bridgeIface bridge equipment in the host does not exist; second, the user does not specify bridgeIface, so usingDefaultBridge is true, bridgeIface called docker0, and docker0 bridge in the host is not exist.

Of course, if the GetIfaceAddr function returns an IP address, current host on such bridgeIface the bridge device. Such results will also have two kinds of different situations: first, the user specifies the bridgeIface, so usingDefaultBridge is false, and the bridgeIface bridge equipment in the host already exist; second, the user does not specify bridgeIface, so usingDefaultBridge to true, bridgeIface called docker0, and docker0 bridge in the host also have exist. The second case is generally: users in the host for the first time start docker daemon, creates a default bridge equipment docker0, then docker0 bridge equipment has been exist on the host, so after without specifying a bridge device and restart docker daemon, docker0 already exists in the.

The following two sections will be separately from the bridgeIface has been created with the bridgeIface did not create two different situations analysis.

BridgeIface 3.3.4 has created the situation

Docker daemon where the bridge equipment host bridgeIface. Docker daemon still need user authentication in the configuration information whether the bridge device to specify the IP address. When the user starts Daemon Docker, if you do not specify the bridgeIP parameter information, then Daemon Docker uses the original IP address called bridgeIface.

When the user specifies bridgeIP parameter information, then need to verify: whether to match the specified bridgeIP parameter information and bridgeIface bridge equipment original IP address information. If the two match, the proof through, to continue down the execution; if they do not match, the proof does not pass, throw an error and display "bridgeIP with the existing bridge configuration information does not match". This section is located./docker/daemon/networkdriver/bridge/driver.go#L119-L129, the code is as follows:

Network = addr. (*net.IPNet)
Validate that the bridge IP matches / the IP specified by BridgeIP
BridgeIP if! = "" {
BiP, _, err = net.ParseCIDR (bridgeIP)
Err if! = nil {
Job.Error return (ERR)
}
If! Network.IP.Equal (BIP) {
Job.Errorf return ("IP bridge (%s) does match not existing bridge configuration%s", network.IP, BiP ()
}
}

BridgeIface 3.3.5 did not create the situation

Docker Daemon is located on host bridgeIface bridge device is not created, has already been introduced there will be two cases:

  • User specified bridgeIface not created;
  • The user does not specify a bridgeIface, and not create docker0.

When a user specified bridgeIface does not exist in the host, that didn't use the docker's default bridge device name docker0. Docker print log information "designated bridge device not found" and return to the bridge not found error message. Code implementation is as follows:

If! UsingDefaultBridge!
Job.Logf ("not found:%s bridge", bridgeIface)
Job.Error return (ERR)
}

When using the default bridge device name, and docker0 bridge equipment has not yet been created. Docker daemon is immediately realize create the bridge operation, and returns the IP address of the docker0 bridge equipment. Code as follows:

If the Iface is not / found try to create it
Job.Logf ("new bridge for%s creating", bridgeIface)
Err if: = createBridge (bridgeIP); err! = nil {
Job.Error return (ERR)
}

Job.Logf ("Iface addr getting")
Err, addr = networkdriver.GetIfaceAddr (bridgeIface)
Err if! = nil {
Job.Error return (ERR)
}
Network = addr. (*net.IPNet)

For creation of docker daemon bridge equipment docker0 all by createBridge bridgeIP to achieve, createBridge implemented in./docker/daemon/networkdriver/bridge/driver.go#L245

The main steps of the realization of createBridge function are:

  1. To determine the IP address of docker0 bridge device;
  2. Create a docker0 bridge device through the createBridgeIface function, and were randomly assigned to the MAC address of the bridge equipment;
  3. The first step will have been identified in the IP address, added to the newly created docker0 bridge device
  4. Start docker0 bridge device.

The following detailed analysis of the specific implementation of the 4 steps.

First Daemon docker0 to determine the IP Docker address, the way to judge whether the user specified bridgeIP. If the user does not specify a bridgeIP segment, to find the right from the Docker prepared IP segment in the addrs list. Specific code implementation is located in./docker/daemon/networkdriver/bridge/driver.go#L257-L278, as follows:

Len if (bridgeIP) = 0 {
_, _, err = net.ParseCIDR (bridgeIP)
Err if! = nil {
Err return
}
IfaceAddr = bridgeIP
{else} {
For _, addr: = range {addrs
_, dockerNetwork, err = net.ParseCIDR (addr)
Err if! = nil {
Err return
}
If: err = networkdriver.CheckNameserverOverlaps (nameservers, dockerNetwork) {err = nil;
If: err = networkdriver.CheckRouteOverlaps; err = nil (dockerNetwork) {
IfaceAddr = addr
Break
{else} {
Log.Debugf ("%s%s", addr, ERR)
}
}
}
}

The candidate network address for addrs bridge device:

Addrs = []string{
"172.17.42.1/16", Don't use it conflicts / 172.16.0.0/16 with EC2 DNS 172.16.0.23
"10.0.42.1/16", Don't try using the entire / even /8, that's too intrusive
"10.1.42.1/16",
"10.42.42.1/16",
"172.16.42.1/24",
"172.16.43.1/24",
"172.16.44.1/24",
"10.0.42.1/24",
"10.0.43.1/24",
"192.168.42.1/24",
"192.168.43.1/24",
"192.168.44.1/24",
}

Through the implementation of the above process, make sure to find a usable IP network address, ifaceAddr; if it is not found, is returned error log, show that there is no suitable IP address assigned to docker0 bridge equipment.

Second steps to create a docker0 bridge device through the createBridgeIface function. The realization of createBridgeIface function is as follows:

CreateBridgeIface error (string name) func {
Err, kV: = kernel.GetKernelVersion ()
Only set the bridge's MAC address / if the kernel version is > 3.3
That it was not supported / / before
SetBridgeMacAddr: = err = = nil (kv.Kernel > = 3 & & & & kv.Major > = 3)
Log.Debugf ("bridge MAC address setting =%v", setBridgeMacAddr)
Netlink.CreateBridge return (name, setBridgeMacAddr)
}

The above code through the host Linux kernel information, determine the support set bridge equipment MAC address. If the Linux kernel version is greater than 3.3, the configuration MAC address is supported, otherwise it is not supported. The Docker is not less than 3.8 of the kernel version running on it is stable, it can be considered that the kernel support configuration MAC address. Finally, through the CreateBridge netlink function to achieve the creation of the docker0 bridge.

Netlink is a kind of special socket communication mode in Linux, which provides the way of two-way data transmission between user application and kernel. In this mode, the user can use the standard API netlink to use the powerful function of socket, and the kernel state requires the use of specialized kernel netlink to use API.

Libcontainer netlink package CreateBridge to create the actual bridge equipment, the specific use of the system call code are as follows:

Syscall.Syscall (syscall.SYS_IOCTL, uintptr (s), SIOC_BRADDBR, uintptr (unsafe.Pointer (nameBytePtr)) (())

After creating a bridge device for docker0 bridge device configuration MAC address, to achieve the function of setBridgeMacAddress.

The third step is to create the docker0 bridge device IP address binding. The last step has completed only created from the bridge equipment docker0, still need to docker0 bridge device binding IP address. Specific code to achieve:

Netlink.NetworkLinkAddIp if (Iface, ipAddr, ipNet); err! = nil {
Fmt.Errorf return ("to add private network:%s Unable err",)
}

NetworkLinkAddIP implementation is also located in the netlink libcontainer package, the main function is: through the netlink mechanism for a network interface device binding an IP address. The fourth step is to start the docker0 bridge device. Specific implementation code for:

Err if: = netlink.NetworkLinkUp (Iface); err! = nil {
Fmt.Errorf return ("to start network bridge:%s Unable err",)
}

NetworkLinkUp achieve the same in libcontainer netlink package, to start the docker bridge device function.

So far, docker0 bridge after determine the IP, to create, to bind IP, starting four links. CreateBridge about docker0 bridge equipment all complete.

3.3.6 bridge device network address

After creating a bridge equipment, bridge equipment will present a network address. Bridge network address: docker Daemon in creating a docker container using the network address assign IP addresses to docker container. Docker use the code network = addr. (*net.IPNet) to obtain the network address of the bridge equipment.

3.3.7 configuration Daemon iptables Docker

After creating a bridge, docker daemon for container and host configure iptables, including container between the link operation provide support to host all the external to internal flow formulation transmission rules. This section details can refer to"Docker source code analysis (four): Daemon NewDaemon Docker implementation". Code is located in./docker/daemon/networkdriver/bridge/driver/driver.go#L133, as follows:

Iptables for link support / / Configure
EnableIPTables if {
Err if: = setupIPTables (addr, ICC); err! = nil {
Job.Error return (ERR)
}
}

We can always try removing the / / iptables
Err if: = iptables.RemoveExistingChain ("DOCKER"); err! = nil {
Job.Error return (ERR)
}

EnableIPTables if {
Err, chain: = iptables.NewChain ("DOCKER", bridgeIface)
Err if! = nil {
Job.Error return (ERR)
}
Portmapper.SetIptablesChain (chain)
}

3.3.8 configuration network device data reported forward function

In the Linux system, the packet forwarding function is prohibited by default. Packet forwarding is that when a host host has a number of network devices, if one receives a packet, it needs to forward it to another network device. By modifying the value of /proc/sys/net/ipv4/ip_forward, which is set to 1, you can ensure that the system can achieve data packet forwarding function, the code is as follows:

IpForward if {
IPv4 forwarding / / Enable
Err if: = ioutil.WriteFile ("/proc/sys/net/ipv4/ip_forward", []byte{'1','\n'}, 0644); err! = nil {
Job.Logf ("unable to enable IPv4 forwarding:%s\n WARNING:", ERR), ()
}
}

3.3.9 registered network Handler

The last step in creating a Daemon Docker network environment is to register 4 network related Handler. The four handler are the allocate interface, release interface, allocate port and link, the role is the docker container distribution network equipment, recycling docker container network equipment, for docker container allocation of port resources, and for the docker container implementation link operation.

At this point, Daemon Docker network environment to complete the initial work.

4 Summary

In the industrial sector, Docker network issues concern. The network environment of Docker can be divided into Daemon Docker network and Container Docker network. This article from the Daemon Docker network, analyzes the well-known Docker bridge model.

Docker container technology and mirror technology, has brought a lot of benefits to Docker practitioners. However, the development of Docker network still has great potential. The next article, Container Docker network, will bring a more flexible Docker network configuration.

5 author introduction

Sun Hongliang,DaoCloudNew team member, software engineer, VLIS Laboratory of Zhejiang University. Graduate school during active in PAAS and docker open source community, in-depth study and enrich the practice of cloud foundry, good at analysis of the underlying platform code, on the platform of the distributed architecture has some experience, has written a lot of depth technology blog. At the end of 2014 to join the DaoCloud partner to join the team, committed to the spread of Docker based container technology, to promote the pace of the application of the Internet in the container. Mailbox: allen.sun@daocloud.io

6 references

  1. Netlink LINUX mechanism
  2. Net Package

Welcome to pay attention to the Docker source code analysis of the public number

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 22:27:22 2015/8/4Text link
Read: 149 comments: 0View comments
]]>
<![CDATA[[原]Docker源码分析(五):Docker Server的创建]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47283865 Http://prog3.com/sbdm/blog/shlazww/article/details/47283865 Shlazww 22:16:27 2015/8/4

[Abstract]

Server Docker as the Daemon Docker architecture in the request of the portal, took over all the Daemon Docker external communication. Communication API standard, the security of the communication process, the concurrent capacity of service requests, are often the most concerned about the content of Docker users. In this paper, based on the source code, analysis of the Server Docker most of the details of the implementation, and strive to help Docker users to study the design concept of Server Docker.

1 Server Docker profile

Docker architecture, Server Docker is an important part of Daemon Docker. Server Docker the most important function is: to accept the user to send the request through the Client Docker, and in accordance with the corresponding routing rules to achieve routing distribution.

At the same time, Server Docker has a very good user friendliness, the support of a variety of communication protocols greatly reduce the threshold of Docker users to use the Docker. In addition, Server Docker design and implementation of a detailed and clear API interface for Docker users to choose to use. Communication security, Server Docker can provide a secure transport layer protocol (TLS), to ensure that the data encryption transmission. In terms of concurrent processing, Daemon Docker has used a large number of goroutine in the Golang, greatly improving the service side of the concurrent processing capacity.

This article for the "Docker source code analysis" series of fifth - Server Docker.

2 Server Docker source analysis content arrangement

This article will analyze the creation of Server Docker from the source point of view. The main contents are as follows:

  1. "Serveapi" the creation of the job and the implementation process, on behalf of the creation of Server Docker;
  2. Depth analysis of the implementation process of "serveapi" for this job;
  3. Server Docker to create Listener and service API process analysis.

3 Server Docker creation process

"Docker source code analysis (three): Daemon Docker start"The main analysis of the Daemon Docker start, and in the mainDaemon () run the last link, to achieve the creation and run called "serveapi" job. The role of this link is: to allow Daemon API to provide Docker access services. In essence, this is the realization of the Docker architecture Server Docker in the creation and operation.

From a process point of view, the Server Docker is created and run, representing the entire life cycle of the "serveapi" job: create a Job instance job, configure the job environment variable, and finally execute the job. This chapter is divided into three sections to analyze these three different stages.

3.1 create a "serveapi" job

Job is the most basic task execution unit within the Docker architecture, so the execution of the task of creating the Server Docker is no exception, and it needs to be represented as an executable Job. In other words, you need to create a Server Docker, you must create a corresponding Job. Specific Job to create the form is located in./docker/docker/daemon.go, as follows:

Job: = eng.Job ("serveapi", flHosts...)

The above code through the Engine instance eng to create an instance of the Job type job, job called "serveapi", while using the value of flHost to initialize the job.Args. The role of flHost is: the configuration of the Server Docker monitor protocol and monitor the address.

The docker source code analysis (3): docker Daemon Start "mainDaemon () of the specific implementation process, the link in the loading builtins have to eng object registered key" serveapi "handler, and the value of the handler for api.ServeApi need to pay attention to is. Therefore, when running a serveapi called "job", the Handler will execute the job, that is, api.ServeApi.

3.2 configuration job environment variables

After creating the Job instance Docker, Daemon job for the job configuration environment parameters. In realizing the job, the job configuration parameters are two ways: first, create an instance of your job, job direct initialization parameters specified args attribute; second, build the job, the job to add the environment variable specified by the. The following code implements the job configuration environment variable for the creation:

Job.SetenvBool ("Logging", true)
Job.SetenvBool ("EnableCors", *flEnableCors)
Job.Setenv ("Version", dockerversion.VERSION)
Job.Setenv ("SocketGroup", *flSocketGroup)

Job.SetenvBool ("Tls", *flTls)
Job.SetenvBool ("TlsVerify", *flTlsVerify)
Job.Setenv ("TlsCa", *flCa)
Job.Setenv ("TlsCert", *flCert)
Job.Setenv ("TlsKey", *flKey)
Job.SetenvBool ("BufferRequests", true)

 

For the above configuration, the sum of the environment variables is summarized as follows:

12:10:05 2014-12-09 screen screenshot
3.3 run job

Configuration completed job environment variables, then the implementation of the job running function, the specific implementation of the code as follows:

Err if: = err (); job.Run! = nil {
Log.Fatal (ERR)
}

Eng object in the key has been registered as "serveapi" Handler, so when running job, the implementation of this value Handler value, the corresponding value Handler for api.ServeApi. So far, known as the "serveapi" of the job's life cycle is complete. Below will be an in-depth analysis of the Handler job, api.ServeApi implementation details of the specific implementation.

4 ServeApi running process

This chapter will deeply analyze the Server API to provide Docker services, from the perspective of the source code analysis of the Server Docker architecture design and implementation.

As a monitoring request, process request, the server and docker server first clear their own needs to provide services to many kinds of communication protocols, in docker the C / S mode of architecture, you can use the protocol: TCP and UNIX socket form, and FD form. Subsequently, Server Docker according to the different protocols, respectively, to create a different server instance. Finally, in the different server instance, the creation of the corresponding routing module, monitoring module, and processing the request of the Handler, the formation of a complete server.

"Serveapi" this job at run time, will execute the api.ServeApi function. ServeApi: current loop checking all docker daemon support communication protocol, and for each protocol to create a goroutine, in the goroutine arranged inside a service to HTTP requests the server end. ServeApi code implementation is located in./docker/api/server/server.go#L1339:

First, determine whether the length of job.Args 0, due to the flHosts to initialize job.Args, so job.Args length if 0, that no docker server is not listening at the protocol and address, the parameter error, error information is returned. Code as follows:

If len (job.Args) = = 0 {
Job.Errorf return ("%s PROTO://ADDR [PROTO://ADDR usage:...]", job.Name)
}

 

Second, the definition of two variables, protoAddrs on behalf of the content of flHosts; while the chError definition and the length of the same error channel type protoAddrs pipe, chError's role in the following will be explained. It also defines the activationLock, which is a job used to synchronize "serveapi" and "acceptconnections" for the two channel implementation. In serveapi runtime and ListenAndServe ServeFd. Since there is no content activationLock the channel in the blocking, and when run acceptionconnections "the job, will first notify the init process docker daemon has been started, and close activationLock, and also opened the serveapi continued implementation of the. It is because of the existence of activationLock, to ensure that the "acceptconnections" of the operation of the job to notify the "serveapi" to open the effect of the official service in API. Code as follows:

(VaR
ProtoAddrs = job.Args
ChErrors = make (error Chan, len (protoAddrs))
)
ActivationLock = make (struct{} Chan)

 

Third, traversal protoAddrs, namely job.Args, which each are in accordance with the string ": / /" segment, if the segmentation protoAddrParts the length of the not for 2, a written form of the protocol and address error, error return job; if not 2. Then segmentation for each item in the agreement protoAddrPart[0] and address protoAddrParts[1]. Finally, create a goroutine to perform the ListenAndServe operation. Goroutines operation mainly depends on the operation result of the ListenAndServe (protoAddrParts[0], protoAddrParts[1], job). If the return error, is chErrors has error, the completion of the execution of the current goroutine; if there is no return error, the goroutine continued operation and continued to provide services. One of the most important is the realization of ListenAndServe, the function of the specific implementation of how to create listener, router and server, and to coordinate the work of the three, and ultimately serve the API request. Code as follows:

For _, protoAddr: = range {protoAddrs
ProtoAddrParts: = strings.SplitN (protoAddr: / /, 2)
Len if (protoAddrParts) = 2 {
Job.Errorf return ("%s PROTO://ADDR [PROTO://ADDR usage:...]", job.Name)
}
Func go () {
Log.Infof ("for HTTP on%s (%s)", AddrParts[0] proto, protoAddrParts[1]), (Listening)
ChErrors

 

Fourth, according to the value of the chErrors operation, if the chErrors this channel error content, then ServeApi the function return; if no error, then the loop is blocked. Code as follows:

For: I = 0; I < len (protoAddrs); I + = {1
Err: =

 

At this point, the operation process of ServeApi has been analyzed in detail, including the realization of the core part of ListenAndServe, and the next chapter begins to.

5 ListenAndServe implementation

The function of ListenAndServe is to make Server Docker listen to a specified address, accept the request on the address, and route the request to the corresponding processing function Handler. From the implementation point of view, ListenAndServe mainly realizes the set a service to the HTTP server, the server will be listening on the specified address request, and specific protocol to examine the request, eventually completed the request routing and distribution. Code implementation is located in./docker/api/server/server.go.

The implementation of ListenAndServe can be divided into the following 4 parts:

  1. Create router routing instance;
  2. Create listener listener instance;
  3. Create http.Server;
  4. Start API service.

ListenAndServe implementation process is as follows:

ListenAndServe

Figure 5.1 ListenAndServer execution flow chart
Below will follow the ListenAndServe execution flow chart one one in-depth analysis of the various parts.

5.1 create router routing instance

First of all, the implementation of ListenAndServe through the createRouter to create a router routing instance. Code implementation is as follows:

Err, R: = createRouter (job.Eng, job.GetenvBool ("Logging"), job.GetenvBool ("EnableCors"), job.Getenv ("Version") ("")
Err if! = nil {
Err return
}

 

CreateRouter implementation is located in./docker/api/server/server.go#L1094.

Creating router routing instance is an important link, the role of the routing instance is: Server Docker is responsible for the request for routing and distribution. The realization of the process, the main two steps: first, to create a new router routing instance; second, to add the router instance route records.

5.1.1 create an empty routing instance

In essence, gorilla/mux through the package createRouter to achieve a powerful router and distributor. As follows:

R: = mux.NewRouter ()

 

NewRouter () function returns a new instance of R router. When you create an instance of Router, the two properties of the object are assigned to the Router and the two properties are nameRoutes and KeepContext. The namedRoutes property is a map type, the key to string, value for route routing record type; in addition, attribute of KeepContext is false, said docker server after finish processing the request, it removed the content of the request, no request storage operation. Code is located in./docker/vendor/src/github.com/gorilla/mux/mux.go#L16, as follows:

NewRouter *Router () func {
&Router{namedRoutes: make return (map[string]*Route), false} KeepContext:
}

 

Visible, the type returned by the above code is mux.Router. Mux.Router will through a series of registered record route, to accept the request do match, first by the requested URL or other conditions, find the corresponding routing records, and call the route record executive handler. Mux.Router has the following characteristics:

  • Requests can be based on the URL's host name, path, path prefix, shemes, request header, request value, HTTP request method type, or the use of custom match rules;
  • URL host name and path can have a regular expression to represent;
  • Registered URL can be directly used, can also be retained, so that the use of maintenance resources can be guaranteed;
  • Routing records can be used to sub routers: if the parent route record matches, nested records will only be used to test. When designing a routing record in a group to share the same matching conditions, such as the host name, the prefix or other repetitive attributes, the way the sub routing is very helpful
  • Mux.Router implements the http.Handler interface, it is compatible with the standard http.ServeMux.

5.1.2 add route record

Router routing instance r creation is completed, the next step is to add the required route records for the Router instance R. Routing records store the information that is used to match the request, including the matching rules for the request, and the Handler execution entry after the match.

Go back toCreateRouter implementation codeIn the first judge Daemon Docker startup process there is no open DEBUG mode. By docker executable file to start the docker daemon, analytical flags parameter. If flDebug value is false, then do not need to configure the debug environment; if flDebug value is true, then illustrate the need to add debug function docker daemon. Specific code to achieve the following:

Os.Getenv if ("DEBUG") = "" {
AttachProfiler (R)
}

 

The function of AttachProiler (R) is to add the routing records related to the DEBUG, and the specific implementation is located in the routing instance R../docker/api/server/server.go#L1083, as follows:

AttachProfiler func (*mux.Router router) {
Router.HandleFunc ("/debug/vars", expvarHandler)
Router.HandleFunc ("/debug/pprof/", pprof.Index)
Router.HandleFunc ("/debug/pprof/cmdline", pprof.Cmdline)
Router.HandleFunc ("/debug/pprof/profile", pprof.Profile)
Router.HandleFunc ("/debug/pprof/symbol", pprof.Symbol)
Router.HandleFunc ("/debug/pprof/heap", pprof.Handler ("heap").ServeHTTP)
Router.HandleFunc ("/debug/pprof/goroutine", pprof.Handler ("goroutine").ServeHTTP)
Router.HandleFunc ("/debug/pprof/threadcreate", pprof.Handler ("threadcreate").ServeHTTP)
}

 

Analysis of the above source code, you can find Server Docker using two packages to complete the work related to DEBUG: expvar and pprof. Package expvar to provide a standardized interface to the public, so that these public variables can be accessed through the HTTP in the form of the "/debug/vars" under the URL, the transmission format for JSON. Package Docker will run the Server pprof analysis data through the "/debug/pprof/" this URL outward exposure. These runtime information includes the following content: the list of available information, running the command information, CPU information, program function reference information, ServeHTTP the function information (using a heap, goroutine use and thread).

Go back toCreateRouter function implementationAfter completing all the work of the DEBUG function, Docker Docker creates an object map of the M type, which is used to initialize the route record of the routing instance R. To simplify the m object, the code is as follows:

M: = map[string]map[string]HttpApiFunc{
"GET": {
......
"/images/{name:.*}/get": getImagesGet,
......
},
"POST": {
......
"/containers/{name:.*}/copy": postContainersCopy,
},
"DELETE": {
"/containers/{name:.*}": deleteContainers,
"/images/{name:.*}": deleteImages,
},
"OPTIONS": {
"" ": optionsHandler,
},
}

 

Object m type map, where key is a string type, representing the HTTP request type, such as "get", "post", "delete", value for another type of map, the map represents is mapping of URL and execution of the handler. In the second map type, key is the string type, representing the request URL, value for the HttpApiFunc type, representing the specific implementation of Handler. The definition of HttpApiFunc type is as follows:

HttpApiFunc func type (*engine.Engine eng, version.Version version, http.ResponseWriter W, *http.Request R, map[string]string vars, error)

 

Completion of the definition of object m, and then Server m through the object Docker to add a routing instance r routing records. Object m request method, request URL and request processing Handler these three kinds of content can be the object r to build a routing record. Implementation code. As follows:

Method routes, for: = m range {
Route FCT, for: = routes range {
Log.Debugf ("%s Registering,%s", method, route)
LocalRoute: = route
LocalFct: = FCT
LocalMethod: = method

F: = makeHttpHandler (Eng, logging, localMethod, localRoute, localFct, enableCors, version.Version (dockerVersion)) ()

If {localRoute = = ""
R.Methods (localMethod).HandlerFunc (f)
{else} {
R.Path ("/v{version:[0-9.]+}" + localRoute).Methods (localMethod).HandlerFunc (f) ()
R.Path (localRoute).Methods (localMethod).HandlerFunc (f) ()
}
}
}

 

The code above, in the first layer circulation, according to the HTTP request partition method and request their routing record, the second layer circulation, by matching the requested URL division, and corresponding to the URL execution of the handler. In the nested loop, a function f is returned by makeHttpHandler. In this function, the logging information, CORS information (cross domain resource sharing protocol), and version information is returned. The following example shows the implementation of makeHttpHandler, M can be seen from the object, for the "GET" request, the request URL for "/info", then the request Handler for "getInfo"". Implementation of the makeHttpHandler specific code is as follows:

MakeHttpHandler func (*engine.Engine eng, bool logging, string localMethod, string localRoute, HttpApiFunc handlerFunc, bool enableCors, dockerVersion, version.Version http.HandlerFunc) {
Func return (http.ResponseWriter W, *http.Request R) {
The request / / log
Log.Debugf ("%s%s Calling", localMethod, localRoute)

Logging if {
Log.Infof ("%s%s", r.Method, r.RequestURI)
}

Strings.Contains if (r.Header.Get ("User-Agent"), "Docker-Client/") {
UserAgent: = strings.Split (r.Header.Get ("User-Agent"), "/")
If len (userAgent) = = 2 & &! DockerVersion.Equal (version.Version (userAgent[1])) {
Log.Debugf ("client and server don't have the same version (%s client:, server:,%s), userAgent[1], dockerVersion," (Warning:).
}
}
Version: = version.Version (mux.Vars (R) ["version"])
If {version = = ""
Version = api.APIVERSION
}
EnableCors if {
WriteCorsHeaders (W, R)
}

Version.GreaterThan if (api.APIVERSION) {
Http.Error (W), fmt.Errorf ("and server don't have same version client (client:%s,%s server:), version, api.APIVERSION,).Error (), http.StatusNotFound ()
Return
}

Err if: = handlerFunc (Eng, version, W, R, mux.Vars (R)); err! = nil {
Log.Errorf ("for%s%s returned error:%s Handler, localMethod,, localRoute,, ERR)
HttpError (W, ERR)
}
}
}

 

MakeHttpHandler can be seen directly to the implementation of a function func (http.ResponseWriter W, *http.Request R). To determine the logging parameters makeHttpHandler incoming in the realization of the func function. If true, the handler's execution through the log display, also passed through the makeHttpHandler of enableCors parameter to determine whether in the HTTP request header file add cross domain resource sharing information, if it is true, is through the function writeCorsHeaders response to add the cors of HTTP header, the code is implemented in./docker/api/server/server.go#L1022, as follows:

WriteCorsHeaders func (http.ResponseWriter W, *http.Request R) {
.Add () w.Header ("Access-Control-Allow-Origin", "*")
.Add () w.Header ("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
.Add () w.Header ("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, OPTIONS,")
}

 

The most important part of the implementation is located in handlerFunc (Eng, version, W, R, mux.Vars (R)), such as the following code:

如果错误:= handlerfunc(ENG版,W,R,MUX。VAR(R));错误!=无{
日志。errorf(“处理程序返回错误:%s %s %s”,localmethod,局部路由,ERR)
HTTPError(W,ERR)
}

 

对于”获得“请求类型,“信息”请求URL的请求,由于处理名为getInfo,也就是说handlerfunc这个形参的值为getInfo,故执行部分直接运行getInfo(ENG版,W,R,MUX。VAR(R)),而的具体实现位于GetInfo。/码头/接口/服务器/服务。去# l269,如下:

函数GetInfo(ENG * engine.engine,版本。版本,W http.responsewriter,R * http.request,VARs地图[字符串]字符串)误差{
W header()。集(“内容类型”、“application/json”)
eng.servehttp(W,R)
零回报
}

 

以上makehttphandler的执行已经完毕,返回功能函数,作为指定URL对应的执行处理程序。

创建完处理函数处理器,需要向路由实例中添加新的路由记录。如果URL信息为空,则直接为该HTTP请求方法类型添加路由记录;若URL不为空,则为请求URL路径添加新的路由记录。需要额外注意的是,在URL不为空,为路由实例R添加路由记录时,考虑了API版本的问题,通过r.path(“/ V {版:[ 0-9。] + }”+局部路由),方法(localmethod)。handlerfunc(F)来实现。

至此,MUX。路由器实例R的两部分工作工作已经全部完成:创建空的路由实例R,R添加相应的路由记录为,最后返回路由实例R.

5.2创建听众监听实例

路由模块,完成了请求的路由与分发这一重要部分,属于listenandserve实现中的第一个重要工作。对于请求的监听功能,同样需要模块来完成。而在listenandserve实现中,第二个重要的工作就是创建听众。听众是一种面向流协议的通用网络监听模块。

在创建听众之前,先判断Docker服务器允许的协议,若协议为FD形式,则直接通过servefd来服务请求;若协议不为FD形式,则继续往下执行。

在程序执行过程中,需要判断”serveapi”这个工作的环境中”bufferrequests”的值,是否为真,若为真,则通过包listenbuffer创建一个听众的实例L,否则的话直接通过包净创建听众具体的代码位于实例L.。/码头/接口/服务器/服务器。去# l1269,如下:

如果工作。getenvbool(“bufferrequests”){
我的意思listenbuffer。newlistenbuffer(原,地址,activationlock)
{ }
我,呃=净。听(原地址)
}

 

由于在maindaemon()中创建”serveapi”这个工作之后,给工作添加环境变量时,已经给”bufferrequets”赋值为真实,故使用包listenbuffer创建听众实例。

listenbuffer的作用是:让Docker服务器可以立即监听指定协议地址上的请求,但是将这些请求暂时先缓存下来,等Docker守护全部启动完毕之后,才让Docker服务器开始接受这些请求。这样设计有一个很大的好处,那就是可以保证在Docker守护还没有完全启动完毕之前,接收并缓存尽可能多的用户请求。

若协议的类型为TCP,另外工作中环境变量TLS或者tlsverify有一个为真,则说明Docker需要支持HTTPS服务器服务,需要为Docker服务器配置安全传输层协议(TLS)的支持。为实现TLS协议,首先需要建立一个TLS。配置类型实例tlsconfig,然后在tlsconfig中加载证书,认证信息等,最终通过包TLS中的newlistener函数,创建出适应于接收HTTPS协议请求的听众实例L,代码如下:

L = TLS。newlistener(L,tlsconfig)

至此,创建网络监听的听众部分已经全部完成。

5.3创建http.server

泊坞窗服务器同样需要创建一个对象来运行服务端在HTTP服务器。listenandserve实现中第三个重要的工作就是创建http.server:

httpsrv:= HTTP服务器{地址:地址,处理器:R }

 

其中地址为需要监听的地址,R为路由器路由实例MUX。

5.4启动API服务

Creates an instance of the http.Server. Docker server immediately start service API, the docker server started in the listener listener instance l accept the request, and to every request generates a new goroutine to do exclusive service. For each request, the goroutine will read request, query the route entries in the routing table, find a matching route entry, the final call to the route record in the execution of the handler, after the completion of execution, not to request return response information. Code as follows:

HttpSrv.Serve return (L)

 

At this point, ListenAndServer of all processes have been analyzed, Server Docker has begun to target different protocols, service API request.

6 Summary

Server Docker as the Daemon Docker architecture in the request of the portal, took over all the Daemon Docker external communication. Communication API standard, the security of the communication process, the concurrent capacity of service requests, are often the most concerned about the content of Docker users. In this paper, based on the source code, analysis of the Server Docker most of the details of the implementation. Hope Docker users can study the design concept of Server Docker, and can make better use of Server Docker to create greater value.

7 introduction of the author

Sun Hongliang,DaoCloudNew team members, software engineers, Zhejiang University computer science graduates.

Graduate school during active in PAAS and docker open source community, in-depth study and enrich the practice of cloud foundry, good at analysis of the underlying platform code, on the platform of the distributed architecture has some experience, has written a lot of depth technology blog.

At the end of 2014 to join the DaoCloud partner to join the team, committed to the spread of Docker based container technology, to promote the pace of the application of the Internet in the container.

Welcome to exchange, mail:Allen.sun@daocloud.io

8 references

  1. Channels tutorial] [Golang
  2. Mux] [Package
  3. Expvar] [Package
  4. Pprof] [Package

Welcome to pay attention to the Docker source code analysis of the public number

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 22:16:27 2015/8/4Text link
Read: 144 comments: 0View comments
]]>
<![CDATA[[原]Docker源码分析(四):Docker Daemon之NewDaemon实现]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47283795 Http://prog3.com/sbdm/blog/shlazww/article/details/47283795 Shlazww 22:12:51 2015/8/4

[Abstract]

Docker architecture Daemon Docker to support the operation of the entire background, but also the unified management of the Docker architecture graph, graphdriver, execdriver, volumes, container Docker and other resources. Can say, docker daemon complex operation were targeted by the daemon to scheduling, and newDaemon happened to can help you understand all the ins and outs of.

1 Preface

Docker ecosystem is becoming more and more perfect, the developer community is increasingly large, which allows the industry to continue to have a very optimistic attitude Docker. However, for the majority of developers, the use of Docker technology is already not the threshold, to enjoy the benefits of Docker technology is not difficult. Today, how to explore the docker adapt to the scene, how to develop the docker surrounding technology, and how to bridge the docker new technology and traditional physical machine or VM technology gap, have occupied docker study of thinking and practice.

This article for the "Docker source code analysis" fourth - Daemon NewDaemon Docker to achieve, and strive to help the majority of Docker enthusiasts have more to understand the core of Docker - Daemon Docker implementation.

2 NewDaemon role profile

There are many important concepts in the Docker architecture, such as: graph, graphdriver, execdriver, networkdriver, volumes, containers Docker, etc.. Docker implementation process, the need to carry out unified management of the above entities, and Daemon Daemon in the Docker instance is designed to complete the task.

From the source point of view, the NewDaemon function of the implementation of the excellent completion of the Daemon Docker to create and load the daemon task, the ultimate realization of the unified management of Daemon Docker resources.

3 NewDaemon source analysis content arrangement

In this paper, from the source point of view, analysis of the Daemon Docker loading process to achieve the NewDaemon, the entire analysis process as follows:

NewDaemon process
4 NewDaemon specific implementation

In the "Docker source code analysis" series of third, there is an important link for: the use of daemon to load the goroutine object and run. When loading and running daemon objects, the first job is to:

Err, D: = daemon.NewDaemon (daemonCfg, Eng)

 

This part of the code analysis is as follows:

  • Function name: NewDaemon;
  • Function call to achieve the specific package location:./docker/daemon;
  • Function to achieve the source file:./docker/daemon/daemon.go;
  • Function for incoming argument: daemonCfg, defined the docker daemon running process required in many configuration information; eng, created in mainDaemon engine object instance.
  • Function return type: D, specific Daemon object instance; err, error state.

Into./docker/daemon/daemon.goThe concrete realization of NewDaemon, the code is as follows


NewDaemon func (*Config config, *engine.Engine Eng) (*Daemon, error) {
Err, daemon: = NewDaemonFromDirectory (config, Eng)
Err if! = nil {
Nil err, return
}
Daemon nil, return
}

 

Visible, in the realization of the process of NewDaemon, mainly rely on the NewDaemonFromDirectory function to achieve the operation environment to create Daemon. The implementation of this function, the incoming parameters and the return type are the same as the NewDaemon. The following will be the length of the details of the details.

4.1. application configuration information

In the implementation process of NewDaemonFromDirectory, the first work is: how to apply the incoming configuration information. This part of the configuration information service in the Daemon Docker operation, and in the Daemon Docker start early on the completion of the initial. The main function of the configuration information is: for the user free configuration Docker optional features, making the Docker running more close to the user's expectations of the running scene.

Configuration information processing consists of 4 parts:

  • Configuration MTU container Docker;
  • Detection of bridge configuration information;
  • Container communication configuration;
  • Processing PID file configuration.

One by one analysis of configuration information processing.

4.1.1. configuration Docker container MTU

Mtu information in the config application of the maximum transmission unit (MTU) characteristics of the container network. The source of the MTU is as follows:

If {config.Mtu = = 0
Config.Mtu = GetDefaultNetworkMtu ()
}

 

If the value of Mtu is 0, the Mtu is set to the default value by the GetDefaultNetworkMtu function; otherwise, the Mtu value in the config is used. Due to the default profile./docker/daemon/config.go(hereinafter referred to as the default profile), the Mtu property value is 0, so the implementation of GetDefaultNetworkMtu. The specific implementation of GetDefaultNetworkMtu function is located in./docker/daemon/config.go:


GetDefaultNetworkMtu int () func {
If Iface err (ERR); networkdriver.GetDefaultRouteIface: = = = {nil
Iface.MTU return
}
DefaultNetworkMtu return
}

 

GetDefaultNetworkMtu implementation. Through the packet networkdriver GetDefaultRouteIface access to specific network equipment, if the existence of the network device, return the MTU attribute of the network equipment value; otherwise, returns the default MTU value defaultNetworkMtu, value of 1500.

Detection of 4.1.2. bridge configuration information

After processing the Mtu property in the config, immediately detect BridgeIface and BridgeIP in the config and the two information. BridgeIface and BridgeIP's role is to create a bridge to provide parameters for task "init_networkdriver". Code as follows:

If config.BridgeIface! "" = = "{& & config.BridgeIP!
Nil return, fmt.Errorf ("specified -b You & --bip, exclusive options. Please mutually specify only one.")
}

 

The meaning of the above code: if the config BridgeIface and BridgeIP two attributes of the are not empty returns nil object, and returns an error, the error message content: the user specifies both BridgeIface and BridgeIP. These two properties belong to the mutex types can only be at most to one of them. stayDefault configuration fileBridgeIface and BridgeIP are empty.

4.1.3. inspection container communication configuration

The communication configuration of the container is mainly aimed at the two attributes of EnableIptables and InterContainerCommunication in config. The role of the EnableIptables attribute is to enable Docker to add to the iptables rule; the function of InterContainerCommunication is to start the function of the communication between container and Docker. Code as follows:

If! Config.EnableIptables & & {config.InterContainerCommunication!
Nil return, fmt.Errorf ("specified --iptables=false with --icc=false. uses ICC You iptables to function. Please set --icc or --iptables to true.")
}

 

Code meaning: if the value of EnableIptables and InterContainerCommunication two properties are false, then return the nil object and error information. Where the error message is: the user will be more than two properties are set to false, container communication needs iptables support, need to set at least one of which is true. InDefault configuration fileThe values of these two attributes are true.

4.1.4. processing network function configuration

Next, the DisableNetwork property of the config is processed to prepare for subsequent use in creating and executing the Daemon Docker network environment, which is created and run in the name of "init_networkdriver" job.

Config.DisableNetwork = config.BridgeIface = = DisableNetworkBridge

 

Because the value of the DisableNetwork attribute in the config is empty, the value of the other DisableNetworkBridge is the string "None", so the value of DisableNetwork in the final false is config. Follow up "init_networkdriver" job needs to be performed.

4.1.5. processing PID file configuration

Deal with the PID file configuration, the main work for: Daemon Docker to run the PID to create a PID file, the path of the file that is Pidfile in the config property. And to add a Daemon shutdown to the Docker operation to remove the Pidfile function, so that the Daemon Docker exit, you can delete the Pidfile in the first time.Processing PID file configuration informationThe code implementation is as follows:


Config.Pidfile if! = "" {
Err if: = utils.CreatePidFile (config.Pidfile); err! = nil {
Nil err, return
}
Eng.OnShutdown (func) {
Utils.RemovePidFile (config.Pidfile)
})
}

 

Code execution process. Firstly, we detected the config Pidfile if the property is empty, if it is empty, is skip the block of code to execute; if not empty, is first in the file system create specific Pidfile, then add a handler to the eng of the attributes onShutdown function with complete body of work for the utils.RemovePidFile config.Pidfile, namely in docker daemon to shutdown operation, delete the file Pidfile. stayDefault configuration fileThe initial value of the Pidfile file is "/var/run/docker.pid"".

Above is the analysis of the configuration information processing.

4.2. detection system support and user rights

After preliminary processed docker's configuration information, docker of its running environment were a series of detection, mainly includes three aspects: * type, operating system support for docker daemon; * user privilege level; * kernel version and processor support.

The realization of the system support and the user's authority is relatively simple,Implementation codeAs follows:


Runtime.GOOS if = "Linux" {
Log.Fatalf ("Docker daemon is The only supported on Linux")
}
Os.Geteuid if () = 0 {
Log.Fatalf ("Docker daemon needs to The be run as root")
}
Err if: = err (); checkKernelAndArch! = nil {
Log.Fatalf (err.Error ())
}

 

First, the type of the operating system is detected by runtime.GOOS. Runtime.GOOS returns the type of operating system operating system, can be Linux, Darwin, FreeBSD, etc.. Combined with the specific code, you can find that if the operating system is not Linux, then the Fatal error log will be reported, the content of Daemon Linux can only support the Docker operating system".

Then, through the os.Geteuid (), the test program users have sufficient permissions. (os.Geteuid) group ID group is returned to the caller. Combined with the specific code, which can be said that if the return is not 0, it is not in the identity of the user's identity to run root, reported the Fatal log.

Finally, by checkKernelAndArch (), the version of the kernel is detected as well as the host processor type. CheckKernelAndArch () to achieve the same./docker/daemon/daemon.go. In the implementation process, the first work is: test program running the processor architecture is "AMD64", and the current Docker runtime can only support the AMD64 processor architecture. The second work is: to detect the Linux kernel version is to meet the requirements, and the current Daemon Docker required to run the kernel version if too low, you must upgrade to 3.8.0.

4.3. configuration work path

Configure Daemon Docker work path, mainly to create a working directory where Daemon Docker is running. Implementation process, through the Root attribute to complete the config. stayDefault configuration fileThe value of the Root attribute is "/var/lib/docker"".

stayImplementation of the configuration work pathIn, the steps are as follows: (1) using standardized path to create a tempdir and path name TMP; (2) by TMP, create a point to TMP file symbolic link realTmp; (values 3) using realTemp, created and assigned to the environment variables TMPDIR; (4) processing config attribute EnableSelinuxSupport; (5) will realRoot re assignment to config.Root, and create docker daemon work root directory

4.4. load and configure storage drive graphdriver

Load and configure the storage drive graphdriver, the purpose is: make Daemon Docker to create the Docker mirror image management required to drive the environment. Graphdriver for the completion of the Docker container image management, including storage and access.

The creation of Graphdriver 4.4.1.

This part of the source code is located in./docker/daemon/daemon.go#L743-L790, detailed analysis of the specific details are as follows:

Graphdriver.DefaultDriver = config.GraphDriver
Err, driver: = graphdriver.New (config.Root, config.GraphOptions)

 

First, for the graphdriver package in the DefaultDriver object assignment, the value of the GraphDriver attribute in the configDefault configuration fileIn the middle, the value of the GraphDriver attribute is empty; similarly, the attribute GraphOptions is empty. And then through the new function in graphDriver to achieve the storage drive graph.

Create specific graphdriver is a very important part of the implementation details from the graphdriver package in the New function to complete. Get into./docker/daemon/graphdriver/driver.goIn the implementation steps are as follows:

First, traverse the array to select graphdriver, the array contents of os.Getenv ("DOCKER_DRIVER") and DefaultDriver. If not empty, the GetDriver function directly back to the corresponding Driver object instance, if all are empty, then continue to be executed. This part of the content of the role is: to allow the graphdriver to load, first to meet the user's custom options, and then meet the default value. Code as follows:

For _, name: range = []string{os.Getenv (DOCKER_DRIVER, DefaultDriver}) {
Name if! = "" {
GetDriver return (name, root, options)
}
}

 

Second, traversal priority array selection graphdriver, the contents of the priority array is in turn as the "aufs", "brtfs", "devicemapper" and "VFS"". If followed by verification, GetDriver success, then directly return the corresponding Driver object instance, if not successful, then continue to be executed. This part of the role of the content is: in the absence of the specified as well as the default Driver, from the priority array to select Driver, the highest priority for the current aufs". Code as follows:

For _, name: = range {priority
Err, driver = GetDriver (name, root, options)
Err if! = nil {
If err = ErrNotSupported || err = = ErrPrerequisites err = = ErrIncompatibleFS {||
Continue
}
Nil err, return
}
Driver nil, return
}

 

Third, select graphdriver from the already registered drivers array. In "aufs", "Btrfs", "devicemapper" and "VFS" are four different types of init in the driver function, they are graphdriver to the drivers array of the corresponding initialization method. Respectively located./docker/daemon/graphdriver/aufs/aufs.go, as well as the corresponding position of the other three types of driver. This part of the content of the role is: in the absence of priority drivers array, the same can be registered by the driver to select the specific graphdriver.

4.4.2. to verify the compatibility of SELinux and Btrfs

Due to incompatibility SELinux docker currently running on the Btrfs file system so when config configuration information to enable SELinux support and driver type is Btrfs, returns nil object, and report such log. Code implementation is as follows:

As Docker on Btrfs and SELinux / are incompatible at present, error on both being enabled
If config.EnableSelinuxSupport driver.String ("Btrfs") = = {
Nil return, fmt.Errorf ("is not supported with SELinux the BTRFS graph driver!")
}

 

4.4.3. create container warehouse directory

Daemon Docker in the creation of the Docker container, the container will need to be placed in a warehouse directory, unified management. And this directory is daemonRepo, the value is: /var/lib/docker/containers, and through the daemonRepo to create the corresponding directory. Code implementation is as follows:

DaemonRepo: = path.Join (config.Root, "containers")
If: err = os.MkdirAll (daemonRepo, 0700); err! = nil & & os.IsExist (ERR) {!
Nil err, return
}

 

4.4.4. migration container to aufs type

When the type of aufs is graphdriver, all the contents of the existing graph need to be migrated to the aufs type; if not for aufs, then continue to be executed. Implementation code is as follows:

Err if = migrateIfAufs (driver, config.Root); err! = nil {
Nil err, return
}

 

This part of the migration mainly includes Repositories, Images and Containers, the specific implementation is located in./docker/daemon/graphdriver/aufs/migrate.go

功能(一个程序)迁移(PTH的字符串,setupinit功能(P系列)错误)错误{
如果pathexists(路径。加入(PTH,“图”)){
如果错误:= a.migraterepositories(PTH);错误!=无{
返回错误
}
如果错误:= a.migrateimages(路径。加入(PTH,“图”));错误!=无{
返回错误
}
返回a.migratecontainers(路径。加入(PTH,“容器”),setupinit)
}
零回报
}

 

的功能是:在迁移库码头工人守护的根工作目录下创建库AUFS的文件,存储所有与图像相关的基本信息。

图像:图像镜像都迁移至迁移的主要功能是将原有的AUFS司机能识别并使用的类型,包括AUFS所规定的层,不同的与MNT目录内容。

集装箱:集装箱内部的环境使用迁移的主要功能是将AUFS司机来进行配置,包括,创建集装箱内部的初始层(init层),以及创建原先集装箱内部的其他层。

4.4.5。创建镜像图

创建镜像图的主要工作是:在文件系统中指定的根目录下,实例化一个全新的图对象,作用为:存储所有标记的文件系统镜像,并记录镜像之间的关系。实现代码如下:

G、错误:=图。newgraph(路径。加入(config.root,“图”),驱动)

 

newgraph的具体实现位于。/码头/图/ graph.go,实现过程中返回的对象为图类型,定义如下:

struct {类型图
根弦
idindex * truncindex.truncindex
graphdriver司机司机。
}

 

其中根表示图的工作根目录,一般为/ var / lib /码头/图”;idindex使得检索字符串标识符时,允许使用任意一个该字符串唯一的前缀,在这里idindex用于通过简短有效的字符串前缀检索镜像与容器的ID;最后司机表示具体的graphdriver类型。

4.4.6。创建volumesdriver以及量图

在Docker中体积的概念是:可以从Docker宿主机上挂载到Docker容器内部的特定目录。一个体积可以被多个Docker容器挂载,从而Docker容器可以实现互相共享数据等。在实现卷时,码头工人需要使用文件系统司机来管理它,由于卷的管理不会像容器文件系统管理那么复杂,故Docker采用VFS驱动实现的管理代码实现如下卷:

volumesdriver,错误:= graphdriver。getdriver(“VFS”配置。根,配置。graphoptions)
卷,错误:=图。newgraph(路径。加入(config.root,“卷”),volumesdriver)

 

主要完成工作为:使用VFS创建volumesdriver;创建相应的卷目录,并返回卷图对象。

4.4.7。创建tagstore

tagstore主要是用于存储镜像的仓库列表(库列表)。代码如下:

库,错误:=图。newtagstore(路径。加入(config.root,“库”+驱动。string()),G)

 

newtagstore位于。/码头/图/ tags.go,tagstore的定义如下:

型tagstore struct {
路径字符串
图*图
库映射[字符串]库
互斥同步。
pullingpool地图[字符串]陈struct { }
pushingpool地图[字符串]陈struct { }
}

 

需要阐述的是tagstore类型中的多个属性的含义:

  • 路径:tagstore中记录镜像的仓库文件位置;
  • 图:相应的图实例对象;
  • 库:记录具体的镜像的仓库的数据结构;
  • 同步互斥:tagstore的互斥锁。
  • pullingpool:记录池,记录有哪些镜像正在被下载,若某一个镜像正在被下载,则驳回其他Docker客户端发起下载该镜像的请求;
  • pushingpool:记录池,记录有哪些镜像正在被上传,若某一个镜像正在被上传,则驳回其他Docker客户端发起上传该镜像的请求;

4.5。创建Docker守护网络环境

创建Docker守护运行环境的时候,创建网络环境是极为重要的一个部分,这不仅关系着容器对外的通信,同样也关系这容器间的通信。

When you create a network, Daemon Docker is done by running a job called "init_networkdriver". Code as follows:

If! Config.DisableNetwork!
Job: = eng.Job ("init_networkdriver")

Job.SetenvBool ("EnableIptables", config.EnableIptables)
Job.SetenvBool ("InterContainerCommunication", config.InterContainerCommunication)
Job.SetenvBool ("EnableIpForward", config.EnableIpForward)
Job.Setenv ("BridgeIface", config.BridgeIface)
Job.Setenv ("BridgeIP", config.BridgeIP)
Job.Setenv ("DefaultBindingIP", config.DefaultIp.String ())

Err if: = err (); job.Run! = nil {
Nil err, return
}
}

 

Analysis of the above source can be known, through the DisableNetwork config attribute to determine, in theDefault configuration fileThis attribute is defined, but it has no initial value. But in the application configuration information to deal with the network function configuration, the DisableNetwork attribute is assigned to false, so the result of the judgment statement is true, the implementation of the corresponding code block.

First create a job called "init_networkdriver", and then set the environment variable for the job, the value of the environment variable is as follows:

  • Environment variable EnableIptables, the use of config.EnableIptables to assign, for true;
  • Environment variable InterContainerCommunication, the use of config.InterContainerCommunication to assign, for true;
  • Environment variable EnableIpForward, the use of config.EnableIpForward to assign, the value of true;
  • Environment variable BridgeIface, the use of config.BridgeIface to assign, as the empty string"";
  • Environment variable BridgeIP, the use of config.BridgeIP to assign, as the empty string"";
  • Environment variable DefaultBindingIP, the use of config.DefaultIp.String () to assign, as 0.0.0.0".

After setting the environment variables, then run the job, as in key eng for "init_networkdriver" handler, value for the bridge.InitDriver function, the specific implementation is located in./docker/daemon/networkdriver/bridge/dirver.go, the role of: * docker service network equipment address acquisition; * to create the specified IP address of the bridge; * enabled iptables function and configuration; * is also the object of Eng registered four handler, such as "the allocate interface", "release interface", "allocate port", "link".

4.5.1. to create Docker network equipment

Create docker network equipment, belonging to the docker daemon create network environment of the first step, the actual work is created from the bridge equipment docker0.

In InitDriver function operation process, we first use the job environment variable initialization of internal variables; then according to the current network environment, to determine whether to create docker0 bridge, if docker exclusive bridge has been in existence, continue down the execution; otherwise, create docker0 bridge. Specific implementation asCreateBridge (bridgeIP)As wellCreateBridgeIface (bridgeIface).

The function of createBridge: in the host start created with the specified name bridge equipment's task, and the bridge device configuration a and other equipment not in conflict with the network address. And createBridgeIface by calling the system responsible for create concrete bridge equipment, and set the MAC address, achieved through netlink package libcontainer CreateBridge.

4.5.2. enable iptables function and configuration

After creating a bridge, docker daemon for container and the host configure iptables, including container between the link operation provide support to host all the external to internal flow formulation transmission rules. Code is located in./docker/daemon/networkdriver/bridge/driver/driver.go#L133-L137, as follows:

Iptables for link support / / Configure
EnableIPTables if {
Err if: = setupIPTables (addr, ICC); err! = nil {
Job.Error return (ERR)
}
}

 

In the course of the setupIPtables call, the address addr docker bridge network address, the ICC is true, that is, allow docker container to visit each other. Hypothesis bridge device called docker0, bridged network address IP Docker0_ip set of iptables rules and steps are as follows: (1) using iptables tool to open the new bridge NAT function, use the following command:

-I POSTROUTING iptables -t NAT -s docker0_ip -j docker0 -o MASQUERADE

 

(2) through the ICC parameters, determine whether to allow inter container communication, and the development of the corresponding Forward iptables chain. Container communication between the data packet sent from the container, after docker0, and also need to be sent to the docker0 docker0, and ultimately to the designated container. In other words, out of the docker0 packet, if you need to open docker0, then that is the communication data of the container package. Commands are used as follows:

-I FORWARD -i docker0 iptables -o docker0 -j ACCEPT

 

(3) allows to receive from the container, and is not sent to other container packets. In other words, all of the data packets that are issued from the docker0 and are not continuing to send to the docker0, using the command are as follows:

-I FORWARD iptables -i docker0 docker0 -j ACCEPT -o

 

(4) for the docker0, which is connected to a set of data packets, the Docker has no condition to accept the packets, the use of the order is as follows:

-I FORWARD -o docker0 iptables -m conntrack --ctstate RELATED ESTABLISHED, -j ACCEPT

 

4.5.3. enable system packet forwarding function

In the Linux system, the packet forwarding function is prohibited by default. Packet forwarding, when the host host is a multi card, if one of the data packets received a card, and need to be forwarded to the other network card. By modifying the value of /proc/sys/net/ipv4/ip_forward, which is set to 1, you can ensure that the system can achieve data packet forwarding function, the code is as follows:

IpForward if {
IPv4 forwarding / / Enable
Err if: = ioutil.WriteFile ("/proc/sys/net/ipv4/ip_forward", []byte{'1','\n'}, 0644); err! = nil {
Job.Logf ("unable to enable IPv4 forwarding:%s\n WARNING:", ERR), ()
}
}

 

4.5.4. create DOCKER chain

On the bridge device to create a name for the DOCKER chain, the chain is used in creating the docker container and set the port mapping. Implementation code is located in./docker/daemon/networkdriver/bridge/driver/driver.go, as follows:

Err if: = iptables.RemoveExistingChain ("DOCKER"); err! = nil {
Job.Error return (ERR)
}
EnableIPTables if {
Err, chain: = iptables.NewChain ("DOCKER", bridgeIface)
Err if! = nil {
Job.Error return (ERR)
}
Portmapper.SetIptablesChain (chain)
}

 

4.5.5. register Handler to Engine

After the bridge created and finished configuring basic iptables rules and docker Daemon in the network is engine registered four handler, the handler's name and functions as follows: * the allocate interface: docker container allocation an exclusive card; * realease interface: release NIC; * allocate port: assign a port docker container; * link: docker container to achieve the link operation.

Due to the Docker architecture, the network is a very important part, so the Docker network will be arranged in the "Docker source code analysis" series of sixth.

4.6. to create graphdb and initialize

Graphdb is a graphic database built on SQLite, which is usually used to record the connection between the nodes and the nodes. Daemon Docker uses graphdb to record the association between images. The code to create the graphdb is as follows:

GraphdbPath: = path.Join (config.Root, "linkgraph.db")
Err, graph: = graphdb.NewSqliteConn (graphdbPath)
Err if! = nil {
Nil err, return
}

 

The above code is first determined graphdb directory /var/lib/docker/linkgraph.db; followed by the NewSqliteConn graphdb package open graphdb. The use of driven "SQLite3, data source name for" /var/lib/docker/linkgraph.db "; finally through NewDatabase function to initialize the graphdb, graphdb create entity table, edge table, and in the two table initialization part data. NewSqliteConn function implementation is located in./docker/pkg/graphdb/conn_sqlite3.go, code implementation is as follows:

NewSqliteConn func (string root) (*Database, error) {
......
Err, Conn: = sql.Open ("SQLite3", root)
......
NewDatabase return (Conn, initDatabase)
}

 

4.7. create execdriver

Execdriver is used in Docker to perform the container Docker task driver. After the creation and initialization of Docker, Daemon graphdb then created the execdriver, the specific code is as follows:

Err, Ed: = execdrivers.NewDriver (config.ExecDriver, config.Root, sysInitPath, sysInfo)

 

Visible, in the creation of execdriver, the need for the 4 part of the information, the following is a brief introduction of the 4 parts of the information:

  • Specified config.ExecDriver:Docker runtime exec driven category, in the default configuration file using the default "native", also can be the value that is "LxC", use interface LxC docker container internal operations are executed.

  • Root run time of the config.Root:Docker path, the default configuration file for "/var/lib/docker"";

  • SysInitPath: system to store the path of dockerinit files, generally /var/lib/docker/init/dockerinit-1.2.0";

  • SysInfo: system function information, including: the container's memory limit function, exchange area memory limit function, data forwarding function, as well as AppArmor security function.

Before the implementation of execdrivers.NewDriver, first through the following code to obtain the desired target dockerinit file path localPath, as well as the system in which the actual path dockerinit file sysInitPath:

LocalCopy: = path.Join (config.Root, "init", fmt.Sprintf ("dockerinit-%s", dockerversion.VERSION)
SysInitPath: = utils.DockerInitPath (localCopy)

 

Through the implementation of the above code, localCopy "/var/lib/docker/init/dockerinit-1.2.0, and sysyInitPath path for the current operation of the docker dockerinit-1.2.0 practical, utils.DockerInitPath implementation is located in./docker/utils/util.go. If localCopy and sysyInitPath are not equal, then the current system in the dockerinit binary files, not in the localCopy path, the need to copy it to localCopy, and the file settings.

After setting the location of the dockerinit binary file, Daemon Docker creates a Sysinfo object that records the functionality of the system. SysInfo definition, located in./docker/pkg/sysinfo/sysinfo.go, as follows:

SysInfo struct type {
Bool MemoryLimit
Bool SwapLimit
Bool IPv4ForwardingDisabled
Bool AppArmor
}

 

Which MemoryLimit by judging the cgroups filesystem mount path existence memory.limit in bytes and Memory.soft_limit_in_bytes limit in bytes file to assignment, if there were, set to true, otherwise it is set to false. Memory.memsw.limit_in_bytes by judging the SwapLimit file to assign, if the file exists, then set to true, or set to false. AppArmor through the host whether there is /sys/kernel/security/apparmor to judge, if there is, then set to true, or set to false.

When execdrivers.NewDriver is executed, the execdriver.Driver object instance is returned, and the specific code implementation is located in the./docker/daemon/execdriver/execdrivers/execdrivers.go, as a result of the choice to use exec as the native driver, the implementation of the code, to return to the final execdriver, such as the following, where the native.NewDriver implementation is located./docker/daemon/execdriver/native/driver.go:

Native.NewDriver return (path.Join (root, "execdriver", "native"), initPath ()

 

4.8. creates a daemon object

Daemon Docker after more than a lot of settings and the creation of the object, the integration of many content, to create the ultimate example of Daemon daemon, the code is as follows:

Daemon: = &Daemon{
DaemonRepo repository,
&contStore{s: make containers: (map[string]*Container)},
G graph,
Repositories repositories,
Truncindex.NewTruncIndex idIndex: ([]string{}),
SysInfo sysInfo,
Volumes volumes,
Config config,
Graph containerGraph,
Driver driver,
SysInitPath sysInitPath,
Ed execDriver,
Eng eng,
}

 

The following analysis of the properties of the Daemon type:

4.9. detection DNS configuration

After creating the Daemon type instance Docker, Daemon daemon uses daemon.checkLocaldns () to detect the configuration of DNS in the Docker operating environment, and the definition of the checkLocaldns function is located in the../docker/daemon/daemon.go, the code is as follows:

Func (*Daemon checkLocaldns) error () daemon {
Err, resolvConf: = resolvconf.Get ()
Err if! = nil {
Err return
}
If len (daemon.config.Dns) = = 0 & & {utils.CheckLocalDns (resolvConf)
Log.Infof ("Local (127.0.0.1) DNS resolver found in resolv.conf and containers can't use it. Using default external servers:%v", DefaultDns (), ()
Daemon.config.Dns = DefaultDns
}
Nil return
}

 

The above code first through the resolvconf.Get () method to obtain the DNS server information in /etc/resolv.conf. If the local DNS file in 127.0.0.1, and container Docker can not use the address, it uses the default external DNS server, 8.8.8.8, 8.8.4.4, and its assigned to the config file in the Dns attribute.

4.10. boot load has been containers Docker

When Daemon Docker starts, it will go to see the content in the daemon.repository, which is in the /var/lib/docker/containers. If there is a container Docker, then let Daemon Docker to load this part of the operation of the container, the container information collection, and to do the corresponding maintenance.

Method for processing shutdown set 4.11.

After loading the existing container Docker, Daemon Docker set up a number of shutdown operations in the need to implement the handler. Code as follows:

Eng.OnShutdown (func) {
Err if: = err (); daemon.shutdown! = nil {
Log.Errorf ("daemon.shutdown ():%s", ERR)
}
Err if: = err (); portallocator.ReleaseAll! = nil {
Log.Errorf ("portallocator.ReleaseAll ():%s", ERR)
}
Err if: = err (); daemon.driver.Cleanup! = nil {
Log.Errorf ("daemon.driver.Cleanup ():%s", err.Error (), ()
}
Err if: = err (); daemon.containerGraph.Close! = nil {
Log.Errorf ("daemon.containerGraph.Close ():%s", err.Error (), ()
}
})

 

It is known that eng object shutdown operation, the need to implement the above as a parameter func () {...... } function. The function, main complete Part 4 of the operation: * running daemon object shutdown function, do the daemon in the aftermath of the work; * by portallocator.ReleaseAll () release all prior to occupancy resources; * by daemon.driver.Cleanup (), through the implementation of the mount unmount all layers graphdriver; * shut down graphdb through daemon.containerGraph.Close () connection.

4.12. returns a daemon object

When all the work is completed, Daemon Docker returns the daemon instance, and eventually returns to the mainDaemon () Daemon in the loaded goroutine to continue executing.

5 Summary

In this paper, from the source point of view depth analysis of the Daemon Daemon Start in the process of creating and loading Docker object. In this part of the paper summarized the content involved very much, daemon logic, one one in-depth, comprehensive and specific.

In the framework of Docker, Daemon Docker content is the most abundant and comprehensive, and NewDaemon to achieve but cover the vast majority of Daemon Docker startup process. Can think that Docker is the essence of Daemon NewDaemon implementation process. Deep understanding of the implementation of NewDaemon, namely Docker Daemon mastered the operation sequence of events.

6 introduction of the author

Sun Hongliang,DaoCloudNew team members, software engineers, Zhejiang University computer science graduates.

Graduate school during active in PAAS and docker open source community, in-depth study and enrich the practice of cloud foundry, good at analysis of the underlying platform code, on the platform of the distributed architecture has some experience, has written a lot of depth technology blog.

At the end of 2014 to join the DaoCloud partner to join the team, committed to the spread of Docker based container technology, to promote the pace of the application of the Internet in the container.

Welcome to exchange, mail:Allen.sun@daocloud.io

7 references

Go Programming Language-Packages] [The
Matches] [Iptables
Variables:] [/proc/sys/net/ipv4/*
Lost packages of docker] [The

Welcome to pay attention to the Docker source code analysis of the public number

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 22:12:51 2015/8/4Text link
Read: 152 comments: 0View comments
]]>
<![CDATA[[原]Docker 容器日志的那些事儿]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47283617 Http://prog3.com/sbdm/blog/shlazww/article/details/47283617 Shlazww 22:05:31 2015/8/4 If time can flow backwards, every step of the real world can be decomposed to the smallest, recorded, is the log, everything is the log.

To face up to history and examine the log can choose to forget, can also choose to remember; experienced, can choose the collection, also can let it covered with dust.

Docker container and how it is not? A log is like a timeline, you're in or not, and he's there. Some people on their good intentions, some people are at random. If you do not believe, you can recall, whether to treat the Docker container.

1 traditional application log

Should not be hurt too deeply in the past, into a new world, should still miss the past it. The new world "temptation" and a new rhythm, I believe that still can not cover up the old stereotype. For decades, the application of life is how to record?

1.1, many people focus on results, the process may turn a blind eye, the application log may with the standard output (stdout and stderr error) and sped away, can not catch, can not freeze. The results unsatisfactory extremely jietan.

1.2 netrose, an encyclopedic mind wit may write a poem book on the wall. Revisiting, awakening the night night. Application log, too, have the person of heart will log (poem) and persistence to somewhere (book on the inner wall), to facilitate future access to.

1.3 can whenever and wherever possible poems and inscriptions, ancient people walk a thousand miles, it is difficult to believe that all the poems full of memories. No matter how far, if the memory can be hidden in a beautiful memory for the future, for the best. Ten years ago, Chen teacher that a computer to do; last year, the big cousin's cell phone also helped her to do. Such a life, not to mention the log. Log log, in fact, the application log can also be sent to somewhere, centralized processing.

2.Docker times log

Docker era of the log, the pace has not been too big, after all, safety first. However, there is no denying that the development of the times always let you unexpected highlights.

If you are in a container application, even if you are discarding or is free and uninhibited, docker container will record your dribs and drabs, as long as you against the standard the standard error output said a word of action. (Docker container all the standard error will be Daemon Docker to take over)

If you are a do read the numerous human, punched Nanshan, kick Beihai, Sihai fled the docker container, you in Beijing one night, perhaps the next day in Shanghai you already sober unabated; on the third day travel Hangzhou your is not remember yesterday in Shanghai a few star hotels. (Docker container itself should be as far as possible without the state, the container is used in the persistent log has a state, frequent migration should not be container log management).

If you have a kidney machine, if you continue to support the big cousin. The Docker container in you, it is easy to travel extensively through to the container to see the cloud, we pass. (docker container in the application log, if your hair to the centralized log processing center, is the best policy, unification; problem is the high cost, have to have money to buy kidney machine, still need to unified standard)

3 get the Docker container persistent log

Read countless people, but difficult to have a bit, presumably not as you would like to taiwan. Exhale, how was informed that Beijing one night all, now mr.gives some skills to easily transport application in docker container internal lasting the log.

If you are already familiar with the principle of docker logs, then standard output errors of those things, in your seems natural not to mention. If we add some Dockerfile CMD knowledge, the following understanding naturally ripe.

Target:

Through the standard output, the application of persistent log file transfer Docker container.

Method

CMD instructions for simple refactoring applications Dockerfile.

Problem hypothesis:

Originally applied CMD Dockerfile instructions for the CMD ["Python", "app.py"], the path to the print log is /var/log/app.log.

Concrete realization:

The first step: in the original Dockerfile where the directory, create a run.sh file, the contents of the document as:

`# /bin/bash!

-F /var/log/app.log tail &

Python app.py Exec

The second step: modify the Dockerfile, delete the original CMD, replace the three instructions.

Instruction 1: run.sh ADD /;

Instruction two: Chmod +x run.sh RUN;

Instruction three: CMD ["./run.sh"]

Principle analysis:

Run.sh started a background process, using the tail command to force the content of the /var/log/app.log to the standard output,

Then use the exec command to run the app.py Python as the main process of the container.

Sketch Map

Docker log

The new era, the technological revolution has brought great convenience, may also need to change a little bit of the original approach, the Docker container log management is also the case. After all, Night in One Beijing, just for the Docker container in a lens, he said Action, human and material resources are saved, a lot easier than Sanlitun's one minute.

Presumably, the cost should not be high.

Welcome to pay attention to the Docker source code analysis of the public number

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 22:05:31 2015/8/4Text link
Read: 251 comments: 0View comments
]]>
<![CDATA[[原]docker exec 与容器日志]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47283467 Http://prog3.com/sbdm/blog/shlazww/article/details/47283467 Shlazww 21:56:07 2015/8/4 Flipping through the docker's history, you will find docker has been stressed in the "application" word, docker also hope to provide container solution for distributed applications.

From the perspective of the life cycle of Docker application software, the development work seems to be located in the construction of Docker, and then the container of the test, deployment and operation and maintenance are closely related to the Docker container. Have to say, Docker thinking under the application of software, management process and the traditional scene has a great difference.

The biggest difference is: Docker container operating environment closed. The operation of a single application, so that the container is a lack of functional services. Although users can get the information part of the container through the docker's level, but still can not directly learned application of internal state information (although docker advocate container operation stateless applications, such as: inside a container application persistence of log files, using the volume inside the temporary storage and so on. And these information in the traditional mode, can be relatively easy to get.

In order to alleviate the obstacles of the container operation environment closure, Docker provides the exec docker command, which is convenient for the user to execute the specified command outside the container, so as to realize the user's requirement.

You exec docker today? If not, the sense of flexibility through the container you deserve to have; if so, then you have to look at the contents of the following.

1 container process tree with exec docker


With the popularity of Docker, I believe more and more Docker lovers have realized:

(1) the Docker container is in fact a number of processes;

(2) and "under normal circumstances" these processes present a "tree" relationship;

(3) the process of PID in container is 1;

(4) if the container main process exits, all processes in the container are exited.

Actually, in docker before 1.3 does not support docker exec. More than view few wrong, but now the situation is already different, see below:

2 exec docker principle and container log


In this paper, the principle of exec docker can be understood as the following two steps:

  • Daemon Docker to create a user specified process /bin/bash, so the parent process for Docker Daemon /bin/bash
  • Daemon P5 for the process of Docker set limits, such as: join the container main process P1 where the isolation environment (namespaces), and other processes, as limited by the resources (CGroup), etc.

Observation above, analysis of the principle, it is not difficult to find that the internal process of the container is not a tree. However, why always emphasize the "tree" relationship?

The answer is: the tree of the inheritance relationship is conducive to container management. To the docker logs to achieve analysis "to sell the Guanzi" standard docker exec of the output not as container log "as an example, the docker daemon create process the main vessel of above, responsible for take over the standard output of main process, so as to ensure the container main process under all process of the standard output is over, however docker Daemon in the newly created docker exec required execution process, the standard output for the latter did not and the main process of the container association, also has not been docker daemon special treatment, so an exec docker the execution process standard output is not into the container of the log file.

Although a part of docker exec the execution course is container, but more accurate understanding docker container log can is like this: docker container logs only responsible for the application of the standard output, not including docker exec derived process of the standard output.

Although the title of this article and the related logs, but almost all are talking about an exec docker. Now comes, might as well in command of the tested provided a wake up:

  • Exec docker to complete the interaction between the inside and outside of the container, but want to complete a large number of standard output need to be cautious
  • Every time exec Docker, Daemon docker will record a execID, should not be too frequent

From the description of the principle of docker exec to vessel log of some small trick is introduced, together with the above docker logs analysis that many people will think of docker container log with a more complete understanding.

However, the author has a different view. After the application of Docker, the log is still a very difficult thing. I think: the container internal log file app.log and logs docker still can not meet the traditional model of the log demand.

Welcome to pay attention to the Docker source code analysis of the public number

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 21:56:07 2015/8/4Text link
Read: 190 comments: 0View comments
]]>
<![CDATA[[原]docker logs 实现剖析]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47283337 Http://prog3.com/sbdm/blog/shlazww/article/details/47283337 Shlazww 21:51:40 2015/8/4 Docker can easily build the user's application, that is, build;

Docker can also be applied to the rapid distribution, that is, ship;

Finally, Docker still has the ability to start the application, that is, run.

Build, Ship, Run, a simple 3 step, minutes for DevOps to create a shortcut to manage the application life cycle.

Application is running up, application running, running state believe that the engineers are most concerned about the point. At this point, Docker how to help engineers to solve problems?

Want to know whether the application is still running? "PS docker" will tell you.

Want to learn how to use the resources of the application? "Stats docker" for you.

Want to know the application's running log? "Logs docker" is definitely your best choice.

Today, docker container application log analysis, is a learned state of running the application logic, and analysis of application performance of the magic weapon of choice.

Docker container based on the log, already a lot of people are doing; that we do not know how to Docker container log is how to do? If we do not know the implementation of the principle of Docker log, then this article can take you to spy on the logs docker.

1 Docker container application how to generate log?

You can imagine, if there is no Docker, your application how to print log? Generally, there are two kinds of:

First, to the standard output (stdout) in the print log; second, set the log file app.log (or other file name), to this document print log.

Docker from the beginning of the birth, the user has never made a standard specification, the log is no exception, there has never been a limit. In this case, the Docker container application log is nothing more than two kinds of. Second very good understanding, still to the container in a log file printing; however, the first one, the application of the standard output (stdout) the way to print the log, how to present to the user?

2 Docker container application log implementation

For log files, Docker can not also should not go deep into the application of internal logic, intercepted and taken over the contents of the log file, which will only destroy the Docker universal. But for the standard output of the application in the Docker container, Docker does the job. Specific implementation, you can refer to the following figure:


Hypothesis application is docker vessel internal operation of the application, so for the application of the first part of the standard output (stdout) log, docker Daemon in the operation of the container will create a coroutine (goroutine), responsible for the standard output log.

Because this goroutine binds the standard output file descriptor for all processes within the container, all the standard output logs used in the container will be received by the goroutine. Goroutine receives a container of the contents of the standard output, immediately this part of the content, write with the container, corresponding to the log file, log files are located in /var/lib/docker/containers/<container_id> ID, the file name for <container_id>-json.log <container_id>-json.log. So far, all the standard output log information on the application of the container has been taken over by the Daemon Docker, and oriented to the corresponding log file with the container.

3 how do users view the container log?

Log always needs to be viewed by the user, docker logs Docker command to provide users with the log interface. The essence of the principle of logs docker is based on the <container-id>-json.log which corresponds to the container one one, in addition to the logs -f docker command.

The following is a brief introduction to the meaning of the parameters of the logs docker command:

  • No parameters: the direct display of all the log information of the container
  • Tail: starting from the end of the required display container log
  • Since: starting from a certain time to display the container log
  • Timestamp: display the log time stamp when the container log is displayed
  • F: a current time point, all the log information container log file <container-id>-json.log print; independent all log information and log files after this point in time, directly receive goroutine write to the log file in the file descriptor, and display

All in all, the processing of the Docker container log will not be complicated. This article read, log the sequence of events, crystal clear.

Of course, you can also do two experiments to test the contents of the above:

  • Experiement 1: running an application through the Docker, the log will print from the standard print log, and then through the logs docker to view the log
  • Experiement 2: run a Docker container, and then exec docker command into the container, and then through the echo, cat and other commands to the standard output of the container print content, and finally through the logs docker view log

Experiment is the sole criterion for testing truth. You will find, Experiement 1, view the log will have a log; while the Experiement 2 is not found in the echo, cat, and other commands standard output log.

Experiement finished 2, instantly destroyed three concept is the above error? Can clearly tell you no, how does that conflict exist?

Welcome to pay attention to the Docker source code analysis of the public number

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 21:51:40 2015/8/4Text link
Read: 208 comments: 0View comments
]]>
<![CDATA[[原]一图看尽Docker容器文件系统]]> Http://prog3.com/sbdm/blog/shlazww/article/details/47283037 Http://prog3.com/sbdm/blog/shlazww/article/details/47283037 Shlazww 21:34:34 2015/8/4 DockerfileIs the raw material of the software,Docker mirrorIs the delivery of software products, andDocker containerIt can be considered as the running state of the software. From the application point of view, the three different stages of Dockerfile, docker mirror and docker container, respectively, on behalf of the software, Dockerfile oriented development and docker image become delivery standards, docker container relates to the deployment and maintenance, all three are indispensable together to act as cornerstone docker.

Docker mirror

Docker image is a product of Dockerfile, is a prerequisite for the Docker container, a link. Docker technology development for more than two years, I believe we have heard very early Docker mostly usedJoint file system(Filesystem Union) to provide a file system service for the Docker container.

On the Docker mirror, there are the following characteristics:

  • Generated by Dockerfile

  • Presentation hierarchy

  • Each layer contains: mirror image file and JSON metadata information

Docker container

Docker container is the running state of Docker mirror image. Generally speaking, that is, on the Docker mirror, the running process. There are two ways to start the process, the user can choose to run their own separate specified command, you can also choose to run the Docker mirror inside the specified command.

Docker container file system, it can be said that most of the Docker image to provide. Why do you say it is the most? In fact, there is a reason, the image content, although many, but still not all. Below, I will take everyone to see what Docker mirror, and the contents of the Docker container is not in the Docker image.

Docker container file system

Let us look at the Docker container file system:

Write the picture here.

The picture is from a more comprehensive perspective.Dockerfile,Docker mirrorandDocker containerThe relationship between the three.

Dockerfile embodiment

The Docker container is already running, but go back, we can still find the shadow of Dockerfile. In the picture above, we can find,Docker containerAttachmentDocker mirrorBut,Docker mirrorTheDockerfileThis is the way:

FROMUbuntu:Fourteen point zero four
ADDRun.sh /
VOLUME/Data
CMD["./run.sh"]

We can see that each command in the Dockerfile is present in the form of an independent mirror layer in the Docker image.

Docker mirror image

There is no doubt that the Docker image is constructed by Dockerfile, and we can see that the 4 layer in the graph is marked as a Docker image. As the core of Docker technology, we have to understand how Docker constructs the mirror image, and what is the product of the Docker mirror image building.

First contact Docker, to understand the level of management of the Docker mirror, it is easy to think: each layer of Docker images are contained in the corresponding file system file. In fact, otherwise, the above 4 commands in the Dockerfile, it is a good evidence.

  • Ubuntu:14.04 FROM: set the base image, and then use all the mirror layers of the base mirror ubuntu:14.04 as a whole.
  • Run.sh ADD /: Dockerfile directory file run.sh to the root directory of the mirror, this time the new layer of the image is only one content, that is, the root directory run.sh.
  • /data VOLUMESetting the image of the VOLUME, this VOLUME the path inside the container is /data. It should be noted that this does not add any files to the new layer of the image, but the JSON file is updated to get this information from the image to start the container.
  • CMD ["./run.sh"]Setting the default execution entry for the mirror, this command will not add any files in the new mirror image, just update the newly built JSON file based on the last layer of the JSON file.

Docker container embodiment

Related to the Docker container, it is dynamic content, everything seems to have a life. As mentioned above, the file system of the Docker container not only contains the Docker image. Remark is not false, figure in the top two layers, is a docker docker container new content, and the two layers just does not belong to category of image.

These two layers are the initial layer of the Docker container.Layer Init(in) with a read and write layerReadWrite LayerIn the initial layer, most of the initialization of the container environment, and the container related environmental information, such as the container host name, host host information and domain name service files, etc..

Again to see readable writing layer, this layer effect is very big, docker mirror layers and on top of the two layers together, docker container in the process only to read write have write permission, other layers to process are read-only (Read-Only). Such as AUFS and other file systems, write the lower image content will involveCOW (Copy-on-Write) technology. In addition, about VOLUME and hosts, hostname, resolv.conf container file will mount here. Need to pay extra attention to is: Although docker container has the ability in read / write layer to see volume and the hosts file content, but that is only the mount point, the real content in the host.

summary

Docker mirror is static, Docker container is dynamic, there is a close relationship between the two. Docker container file system from the perspective of both, I believe it will be of great help to everyone.

Docker image and Docker container file system, is absolutely very detailed content, based on these concepts, there are too many interesting topic can be launched, this series will follow the following articles to analyze:

1 a deep understanding of the size of the Docker image

2 in fact, commit docker is very simple

3 have to say that the save docker and export docker difference

4 why some container files can not move

5 break Namespace MNT container VOLUME

Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 21:34:34 2015/8/4Text link
Read: 345 comments: 0View comments
]]>
<![CDATA[[原]Docker源码分析(二):Docker Client创建与命令执行]]> Http://prog3.com/sbdm/blog/shlazww/article/details/39233467 Http://prog3.com/sbdm/blog/shlazww/article/details/39233467 Shlazww 19:56:11 2014/9/12

[Abstract]


In this paper the docker source code analysis of the second series, in docker architecture based, continue to starting from the source point of view, analyzing how users create docker client, and how the docker client specific user request. Can be said to play the most attractive Docker, starting from the use of Docker, the use of Docker, from the master Client Docker start.

1 Preface

Today, Docker as the industry's leading lightweight virtual container management engine, to the global developer provides a novel and convenient software integration test and deployment of the road. In team development software, Docker can provide a reusable operating environment, flexible resource configuration, convenient integration test methods and a key way of deployment. It can be said that the advantages of Docker in the simplification of continuous integration, operation and maintenance of the deployment of the most vividly, it allows developers to liberate from the former, the focus on the development of the real.

However, the function of the Docker to play to the extreme, is not an easy task. In the case of a deep understanding of the Docker architecture, the use of Client Docker is also very necessary. The former can refer to"Docker source analysis" series of Docker architecture, and this paper mainly aimed at the latter, from the perspective of source code analysis Docker Client, and strive to help developers more profound understanding of the specific implementation of Client Docker, and ultimately better grasp the use of Client Docker. That this article for the "Docker source code analysis" series of second - Client Docker article.

2 Client Docker source code analysis section arrangement

This article from the source point of view, the main analysis of the two aspects of Client Docker: creation and command execution. The first four chapters are arranged as follows:

The first chapter is the introduction, introducing the role of Docker and the necessity of research on Client Docker.

The second chapter introduces some chapter arrangement.

In the third chapter, from the creation of Client Docker, source code analysis, mainly divided into three sections.

In the 3.1 section, the analysis of how to use the docker command, the analysis of the command line flag parameters, as well as the docker command in the request parameters.

In the 3.2 section, the analysis of how to deal with the specific information of the flag parameters, and to collect the configuration information required by Client Docker.

In Section 3.3, the analysis of how to create a Client Docker.

In the fourth chapter, on the basis of the existing Client Docker, it is analyzed how to execute the docker command, which is divided into two sections.

In the 4.1 section, the analysis of how to resolve the request parameters in the docker command, to obtain the type of request.

In the 4.2 section, the analysis of how Client Docker will perform a specific request command, will eventually be sent to the Server Docker.

3 Client Docker creation

The creation of Client Docker, in essence, is the Docker user through the executable file docker, and Server Docker to establish a connection with the client. The following points are divided into three sections of the Client Docker to create the process.

The following flow chart for the entire docker source code:

Docker-2-1

Figure through the flow chart of the way, so that readers more clearly understand the process of creating and executing the request Client Docker. Which involves a lot of the source code in the specific terms in the following will be explained in one one and analysis.

Analysis of flag parameters of Docker 3.1. command

As we all know, in the concrete implementation of Docker, Server Docker and Client docker are completed by the executable file Docker to create and start. So, it is very important to understand the way in which docker can be executed.

For both, the first example illustrates the difference. Server Docker start command for -d docker or --daemon=true docker; and Client Docker is reflected in the --daemon=false PS docker, pull NAME docker, etc..

Above docker request parameters are divided into two classes: first class as an argument on the command line, the docker program to run the need to provide the parameters, such as: - D, --daemon=true, --daemon=false etc.; the second category is docker sent to docker server actual request parameters, such as: PS, pull name etc..

For the first class, we used to be called the flag parameter, in the standard library go language, while also providing aFlag packageAnalysis of the command line parameters.

Explain the above background, then enter the Client Docker to achieve the creation of the source, located in./docker/docker/docker.goIn the go file, the main function that contains the entire Docker, which is the entire Docker (regardless of Docker Daemon or Client Docker) the operation of the portal. Part of the main function code is as follows:

Main func () {
Reexec.Init if () {
Return
}
Flag.Parse ()
Validate daemon flags here / / FIXME:
......
}

In the above code, the first to determine the return value of the reexec.Init method, if it is true, then quit running, otherwise continue to execute. View in./docker/reexec/reexec.goReexec.Init ()The return value of the code segment can be found to be false because there is no Initializer registration before the docker runs.

And then, the main function passes the flag parameter in the command line by calling the flag.Parse (). View source can be found in the Docker./docker/docker/flag.goDefines a number of flag parameters, and through the init function to initialize. Code as follows:

(VaR
FlVersion = flag.Bool ([]string{"V", "-version"}, false, "version information and quit Print")
FlDaemon = flag.Bool ([]string{"d", "-daemon"}, false, "daemon mode Enable")
FlDebug = flag.Bool ([]string{"D", "-debug"}, false, "debug mode Enable")
FlSocketGroup = flag.String ([]string{"G", "-group"}, "docker", "to assign the UNIX socket specified by -H when running in daemon mode use the empty string to setting Group of group" (disable a)
FlEnableCors = flag.Bool ([]string{"#api-enable-cors", "-api-enable-cors"}, false, "CORS headers in the remote API Enable")
FlTls = flag.Bool ([]string{"-tls"}, false, "TLS Use; by tls-verify flags implied")
fltlsverify =旗。布尔([ ]字符串{”tlsverify”},虚假,“使用TLS验证远程(守护:验证:验证客户端,客户端程序)”)
    
/ /这是因为他们在下面()初始化默认值取决于dockercertpath不完全初始化运行直到()
和*的字符串
flcert *字符串
flkey *字符串
flhosts []字符串
)
    
func(){
在此=旗。字符串([ ]字符串{”tlscacert”},文件路径。加入(dockercertpath,defaultcafile),“只相信遥控器提供一个由CA签名的证书在这里”)
flcert =旗。字符串([ ]字符串{”tlscert”},文件路径。加入(dockercertpath,defaultcertfile)、“TLS证书文件的路径)
flkey =旗。字符串([ ]字符串{”tlskey”},文件路径。加入(dockercertpath,defaultkeyfile)、“TLS密钥文件路径)
选择。hostlistvar(与flhosts,[ ]字符串{“H”、“宿主”},“插座(S)绑定到服务器模式nspecified使用一个或多个TCP:/ /主机:端口,UNIX:/ / /路径/插座,FD:/ / *或FD:/ / socketfd”。)
}

 

这里涉及到了Golang的一个特性,即init函数的执行。在Golang中init函数的特性如下:

初始化函数用于程序执行前包的初始化工作,比如初始化变量等;
*每个包可以有多个init函数;
*包的每一个源文件也可以有多个init函数;
*同一个包内的init函数的执行顺序没有明确的定义;
*不同包的init函数按照包导入的依赖关系决定初始化的顺序;
初始化函数不能被调用,而是在主要函数调用前自动被调用。

因此,在主要函数执行之前,码头工人已经定义了诸多旗参数,并对很多旗参数进行初始化。定义的命令行旗参数有:flversion、fldaemon、fldebug、flsocketgroup、flenablecors、fltls、fltlsverify、和、flcert、flkey、flhosts等。

以下具体分析fldaemon:

*定义:fldaemon =旗。布尔([ ]字符串{“D”,“恶魔”},虚假,“使守护进程模式”)
* fldaemon的类型为布尔类型
* fldaemon名称为“D”或者“恶魔”,该名称会出现在Docker命令中
* fldaemon的默认值为假
* fldaemon的帮助信息为”使守护进程模式”
*访问fldaemon的值时,使用指针* fldaemon解引用访问

在解析命令行旗参数时,以下的语言为合法的:

* D -守护
* a true,--守护=真
* D =“true”,——守护=“true”
* D =真实”——守护=真实”

当解析到第一个非定义的旗参数时,命令行旗参数解析工作结束。举例说明,当执行Docker命令泊坞窗--守护=假版本= False PS时,旗参数解析主要完成两个工作:

*完成命令行旗参数的解析,名为守护进程和版本的旗参数fldaemon和flversion分别获得相应的值,均为假;
*遇到第一个非旗参数的参数PS时,将PS及其之后所有的参数存入旗。args(),以便之后执行Docker客户端具体的请求时使用。

如需深入学习旗的解析,可以参见源码命令行参数旗的解析

3.2。处理旗信息并收集Docker客户端的配置信息

有了以上旗参数解析的相关知识,分析Docker的主要函数就变得简单易懂很多。通过总结,首先列出源代码中处理的旗信息以及收集Docker客户端的配置信息,然后再一一对此分析:

*处理的旗参数有:flversion、fldebug、fldaemon、fltlsverify以及fltls;
*为Docker客户端收集的配置信息有:protoaddrparts(通过flhosts参数获得,作用为提供Docker客户端与服务器的通信协议以及通信地址)、tlsconfig(通过一系列旗参数获得,如* fltls、* fltlsverify,作用为提供安全传输层协议的保障)。

随即分析处理这些旗参数信息,以及配置信息。

在parse()之后的代码如下旗:

如果flversion {
showversion()
返回
}

 

不难理解的是,当经过解析旗参数后,若flversion参数为真时,调用showversion()显示版本信息,并从主要函数退出;否则的话,继续往下执行。

如果fldebug {
Os.Setenv ("DEBUG", "1")
}

 

If the flDebug parameter is true, create a system environment variable named DEBUG by the Setenv function in the OS package and set it to "1"". Continue to perform.

If len (flHosts) = = 0 {
DefaultHost: = os.Getenv ("DOCKER_HOST")
If defaultHost = = "|| {*flDaemon
We do not have a / If host, default to UNIX socket
DefaultHost = fmt.Sprintf ("unix://%s", api.DEFAULTUNIXSOCKET)
}
If: _, err = api.ValidateHost (defaultHost); err = nil {!
Log.Fatal (ERR)
}
FlHosts = append (flHosts, defaultHost)
}

 

More than the source of the main analysis of the internal variables flHosts. The role of flHosts is to provide the Client host to connect to the Docker object, but also for the Server Docker to provide the object to be monitored.

Analysis of the process, the first judge whether the length of the flHosts variable is 0, if the words, through the OS package was named DOCKER_HOST environment variable value, the value will be assigned to defaultHost. If defaultHost is empty or flDaemon is true, then there is no definition of a host object, then the default is set to socket UNIX, the value of api.DEFAULTUNIXSOCKET, which is located in the./docker/api/common.go, the value is "/var/run/docker.sock", so unix:///var/run/docker.sock as "defaultHost"". Verify the legitimacy of the defaultHost, the value of defaultHost will be appended to the end of the flHost. Continue to perform.

*flDaemon if {
MainDaemon ()
Return
}

 

If the flDaemon parameter is true, then the implementation of the mainDaemon function, the realization of Daemon Docker start, if the mainDaemon function is completed, then exit the main function, the general mainDaemon function will not take the initiative to end. Since this section describes the start of Client Docker, it is assumed that the flDaemon parameter is false, do not execute the above code block. Continue to perform.

Len if (flHosts) > 1 {
Log.Fatal ("specify only one -H Please")
ProtoAddrParts: = strings.SplitN (flHosts[0]: / /, 2)

 

Above, if the length of flHosts is greater than 1, then throw the error log. Then the flHosts the string array in the first element, segmentation, the / / "segmentation, the segmentation of the two parts into the variable protoAddrParts array in the. The function of protoAddrParts is to resolve the protocol and address of establishing communication with Server Docker, which is one of the necessary configuration information in the process of Client Docker.

(VaR
*client.DockerCli cli
Tls.Config tlsConfig
)
TlsConfig.InsecureSkipVerify = true

 

Since it has been assumed that the flDaemon is false, you can identify the operation of the main function is to create and execute Client Docker. Here to create two variables: one for the type is the client.DockerCli pointer to the object cli, the other is the type of tls.Config object tlsConfig. And set the InsecureSkipVerify tlsConfig property to true. TlsConfig object is created to protect the CLI in the transmission of data, follow the secure transport layer protocol (TLS). Secure transport layer protocol (TLS) For the confidentiality and data integrity of the two communication applications, the protocol has two layers: the TLS protocol and the TLS handshake protocol. TlsConfig is an optional configuration information for the Client Docker creation process.

If we should verify the / server we need to load a trusted CA
*flTlsVerify if {
*flTls = true
CertPool: = x509.NewCertPool ()
Err, file: = ioutil.ReadFile (*flCa)
Err if! = nil {
Log.Fatalf ("read CA cert%s:%s *flCa", Couldn't, ERR)
}
CertPool.AppendCertsFromPEM (file)
TlsConfig.RootCAs = certPool
TlsConfig.InsecureSkipVerify = false
}

 

If the flag parameter for this flTlsVerify is true, then it is required to verify the security of the server side, tlsConfig objects need to load a trusted Ca file. The path of the CA file for the value of the *flCA parameter, the final completion of the RootCAs object in the tlsConfig attribute values, and the InsecureSkipVerify property is set to false.

TLS is / / If enabled try to load and send client certificates
If *flTls *flTlsVerify {||
_, errCert = os.Stat (*flCert)
_, errKey = os.Stat (*flKey)
If errCert = nil and errKey = = nil {
*flTls = true
Err, cert: = tls.LoadX509KeyPair (*flCert, *flKey)
Err if! = nil {
Log.Fatalf ("load X509 key pair:%s. Key encrypted Couldn't?", ERR) ()
}
TlsConfig.Certificates = []tls.Certificate{cert}
}
}

 

If there is one of the two flag parameters for the flTlsVerify and flTls for true, it indicates the need to load and send a certificate of the client. Eventually the certificate content to the Certificates attribute of tlsConfig.

At this point, the flag parameter has been fully processed, and the configuration information required to complete the Client Docker has been collected. After the content for the Client Docker how to achieve the creation and implementation.

Docker Client 3.3. start

Client Docker is created in fact, in the case of the existing configuration parameter information, through the NewDockerCli package in the Client method to create an instance of CLI, the source code is as follows:

If *flTls *flTlsVerify {||
CLI = client.NewDockerCli (os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], &tlsConfig,)
{else} {
CLI = client.NewDockerCli (os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], nil,)
}

 

If the flags parameter flTls is true or flTlsVerify really, is that need to use TLS protocol to ensure the security of transmission, so create a docker client, brought the parameters of TlsConfig; otherwise, also create docker client, just TlsConfig is nil.

On the Client package in the implementation of the NewDockerCli function, you can see./docker/api/client/cli.go.

NewDockerCli func (io.ReadCloser in, out, io.Writer, err, proto, string addr, tlsConfig, *tls.Config *DockerCli) {
(VaR
IsTerminal = false
Uintptr terminalFd
Scheme = "http"
)
    
TlsConfig if! = nil {
Scheme = "https"
}
    
In if! = nil {
File OK, if: = out. (*os.File); OK {
TerminalFd = file.Fd ()
IsTerminal = term.IsTerminal (terminalFd)
}
}
    
If err = {nil
Err = out
}
&DockerCli{return
Proto proto,
Addr addr,
In in,
Out out,
Err err,
IsTerminal isTerminal,
TerminalFd terminalFd,
TlsConfig tlsConfig,
Scheme scheme,
}
}

 

Overall, the creation of DockerCli objects is relatively simple, the more important DockerCli attributes have proto: transmission protocol; addr:host target address, tlsConfig: the configuration of secure transport layer protocol. If tlsConfig is not null in, need to use secure transmission protocol, and DockerCli object of the scheme set to "HTTPS", in addition to about the input, output and error display configuration, eventually returning to the object.

By calling the NewDockerCli function, the program eventually completed the creation of Client Docker, and returned to the main function to continue to perform.

4 Docker command execution

Main function so far, there are the following contents need to be executed for the Docker command service: the creation of the Client Docker, docker commands in the request parameters (after the flag parse stored in flag.Arg ()). That is, Client docker is needed to analyze the request parameters in the Docker command, and eventually send the corresponding request to the Server Docker.

Docker Client 4.1. resolution request command

Client Docker parsing request command work, in the Docker command execution part of the first completed, directly into the main function after theSource section:

Err if: = cli.Cmd (flag.Args) (); err! = nil {
Sterr OK, if: = err. (*utils.StatusError); OK {
Sterr.Status if! = "" {
Log.Println (sterr.Status)
}
Os.Exit (sterr.StatusCode)
}
Log.Fatal (ERR)
}

 

Access to the source code, you can find, as previously said, the first analysis of the specific request parameters stored in flag.Args (), the implementation of the Cmd function as a function of cli. Get intoCmd function of./docker/api/client/cli.go:

Executes the specified command / / Cmd
Func (*DockerCli CLI) Cmd (args) error (string) {
Len if (args) > 0 {
Exists, method: = cli.getMethod (args[0])
If! Exists!
Fmt.Println ("Command not found: Error:", args[0])
Cli.CmdHelp return (args[1:]...)
}
Method return (args[1:]...)
}
Cli.CmdHelp return (args...)
}

 

By the code notes, Cmd function to perform the specific instructions. In the realization of the source code, first of all to judge the length of the parameter list of the request is greater than 0, if not, there is no request for information, returns the help information docker command; if the length is greater than 1, that there is a request message, first by request in the parameter list of the first element args[0] methods used to obtain the specific method. If the method method does not exist, the Help information returned by the docker command, if present, calls the specific method method, the parameters for the args[1][10] and all of the request parameters after.

Or take a specific docker command, for example, daemon=false - version=false - pull Name docker. Through the above analysis, we can sum up the following operation process:

(1) after the analysis of flag parameters, the docker request parameters "pull" and "Name" are stored in flag.Args ();

(2) to create a good Client cli for Docker, CLI cli.Cmd (flag.Args) ()... );

In the Cmd function, through the args[0] is "pull", the implementation of cli.getMethod (args[0]), to obtain the name of the method;

(3) in the getMothod method, by processing the value of the final return CmdPull is method";

(4) the final implementation of method (args[1:])... (that is, CmdPull (args[1:])... ).

Docker Client 4.2. to execute the request command

The last section through a series of commands to resolve, and finally found the specific order of the implementation method, this section mainly introduces the Client Docker how to deal with and send the request through the implementation method.

Because the different request content is different, the implementation process is roughly the same, this section still takes an example to explain the process, the example is: pull NAME docker.

Client Docker in the implementation of the above request command, will execute the CmdPull function, the incoming parameter is args[1:].... Specific source codeCmdPull function in./docker/api/client/command.go.

The following one by one analysis of the CmdPull source code to achieve.

(1)

CMD: = cli.Subcmd ("pull", "NAME[: TAG]", "an image or a repository Pull from the registry")

 

CLI package through the Subcmd method to define a type of object CMD Flagset;

(2)

Tag: = cmd.String ([]string{"#t", "#-tag"}, "", "tagged image in a repository Download")

 

CMD object to define a type of flag, called "#t" or "#-tag", the initial value is null.

(3)

Err if: = cmd.Parse (args); err! = nil {
Nil return
}

 

The args parameter analysis, process analysis, to extract the whether the flag tag parameters are in accordance with the, if the assignment to tag parameters and the rest of the parameters were stored in the cmd.NArg (); if no words, all the parameters stored in the cmd.NArg (in).

(4)

Cmd.NArg if () = 1 {
Cmd.Usage ()
Nil return
}

 

After the flag analysis to determine the parameters of the list, if the parameter list of the number of parameters is not 1, then the need to pull more than image, the pull command is not supported, then call the wrong processing method cmd.Usage (), and return nil.

(5)

(VaR
V = url.Values{}
Remote = cmd.Arg (0)
)
V.Set ("fromImage", remote)
If {*tag = = ""
V.Set ("tag", *tag)
}

 

URL parameter required to create a map type variable V, the variables used to store pull mirror. Then the parameter list of the first value is assigned to a remote variables and remote as the key to fromImage add value to V; finally if tag information, the tag information as the key to "tag" add value to V.

(6)

Remote, _ = parsers.ParseRepositoryTag (remote)
Resolve the Repository name from FQN / to hostname + name
Hostname, _, err = registry.ResolveRepositoryName (remote)
Err if! = nil {
Err return
}

 

Through the remote variables to resolve the mirror where the host address, and the name of the mirror.

(7)

Cli.LoadConfigFile ()
Resolve the Auth config relevant for / this server
AuthConfig: = cli.configFile.ResolveAuthConfig (hostname)

 

Obtain the authentication configuration information needed by cli object and Server Docker communication.

(8)

Pull: = func (registry.AuthConfig authConfig) error {
Err, buf: = json.Marshal (authConfig)
Err if! = nil {
Err return
}
RegistryAuthHeader: = []string{
Base64.URLEncoding.EncodeToString (buf),
}
Cli.stream return ("POST", "/images/create?" +v.Encode (), nil, cli.out, map[string][]string{,
"X-Registry-Auth": registryAuthHeader,.
})
}

 

Defines a function named pull, the incoming parameter type is registry.AuthConfig, the return type is error. The main content of the function is: cli.stream...... Part). This part specifically launched a Server POST Docker request, the request of the URL for "/images/create?" +v.Encode (), the request of the authentication information for: X-Registry-Auth "map[string][]string{": RegistryAuthHeader,}.

(9)

Err if: = pull (authConfig); err! = nil {
Strings.Contains if (err.Error (), "Status 401") {
Fmt.Fprintln (cli.out, "login prior to pull: \nPlease")
Err if: = cli.CmdLogin (hostname); err! = nil {
Err return
}
AuthConfig: = cli.configFile.ResolveAuthConfig (hostname)
Pull return (authConfig)
}
Err return
}

 

Since the last step is just the definition of pull function, this step specific call to perform the pull function, if the success of the final return, if the return error, then do the appropriate error handling. If the return error is 401, you need to log in, go to the login link, after completion, continue to perform the pull function, if completed, the final return.

The above is the whole implementation process pull requests, the other is similar in the execution of the request process. In short, the request execution process, most of them are will command line about the request parameters are preliminary treatment, and add the corresponding auxiliary information, through the end of the specified protocol to docker server sends a docker client and docker server agreed good API request.

5 Summary

This article from the perspective of the source code from the docker executable file to start, to create Client Docker, and ultimately sent to the Server Docker request complete process.

The author believes that by learning and understanding the docker client source can not only allow users to master the docker command, also can make the user in special circumstances have the ability to modify the docker client source code, to meet some special requirements of the system itself, to achieve customized docker client to maximize the docker thought of opening up to the value.

6 introduction of the author

Sun Hongliang,DaoCloudNew team members, software engineers, Zhejiang University computer science graduates.

Graduate school during active in PAAS and docker open source community, in-depth study and enrich the practice of cloud foundry, good at analysis of the underlying platform code, on the platform of the distributed architecture has some experience, has written a lot of depth technology blog.

At the end of 2014 to join the DaoCloud partner to join the team, committed to the spread of Docker based container technology, to promote the pace of the application of the Internet in the container.

Welcome to exchange, mail:Allen.sun@daocloud.io

7 references

[in Docker (two): Docker command line quest "
Go Programming Language] [The
[GO standard library - command line parameters analysis flag package]
Reference-Command Line] [Docker


Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 19:56:11 2014/9/12Text link
Read: 3519 comments: 2View comments
]]>
<![CDATA[[原]Docker源码分析(三):Docker Daemon的启动]]> Http://prog3.com/sbdm/blog/shlazww/article/details/39188933 Http://prog3.com/sbdm/blog/shlazww/article/details/39188933 Shlazww 16:49:29 2014/9/11

[Abstract]

[Docker source code analysis (three): Daemon Docker start] Docker as the industry's highly respected lightweight virtual container management engine, its powerful background capabilities all by Daemon Docker. Starting from the source code, this paper introduces the start of Daemon Docker process, and in-depth analysis of the implementation details of each step in the start process. Docker run really can be described as the carrier for the daemon, scheduling management by the engine, the task is performed by job.

1 Preface

Since the birth of Docker, it has led the field of lightweight virtual container technology boom. In this trend, Google, IBM, Redhat and other industry leaders have joined the Docker camp. Although the docker still mainly based on the Linux platform, but Microsoft has repeatedly announced support for docker, from the previously announced azure support docker and kubernetes, today announced the next generation windows server of the original ecology support docker. Microsoft of this series of measures to show how much of a compromise to the Linux world, of course, this also had to let the world have a new understanding of the great influence of Docker.

Docker's influence is self-evident, but if you need to in-depth study of the internal implementation of Docker, the author believes that the most important is to understand the Daemon Docker. In the Docker architecture, Client Docker communicates with Daemon Docker through a specific protocol, while Daemon Docker mainly carries most of the work during the Docker operation. This is the "Docker" series of third source code analysis - Docker Daemon.

2 Daemon Docker profile

Daemon Docker is running in the Docker architecture in the background of the guard process, can be divided into Server Engine, Docker and Job three parts. Docker daemon that is through docker server module accept docker client request, and in the engine to handle the request, and then according to the type of request, to create the specified job and run and operation process has several possible: to docker registry to obtain mirror, pass over graphdriver container image localization operation execution, vessel network environment configuration by networkdriver, by execdriver perform the operation in the interior of the container implementation etc..

The following is a schematic diagram of the Daemon Docker architecture:

Docker-3-1

3 Daemon Docker source analysis content arrangement

This article from the source point of view, the main analysis of the starting process of Daemon Docker. Because there are great similarities docker daemon and docker client startup process, so after the start process is introduced. This paper emphatically analyses start process in the most important link: create a daemon process mainDaemon ().

4 Daemon Docker startup process

Since both Daemon Docker and Client Docker are started by an executable file docker, the startup process is very similar. Docker executable file run, run the code through different command line flag parameters, to distinguish between the two, and eventually run the respective parts of the two.

When starting Daemon Docker, you can generally use the following command: --daemon=true docker; D - docker; d=true - docker, etc.. Then by the main docker () function to resolve the above command of the corresponding flag parameters, and ultimately complete the Daemon Docker start.

First, attach the Daemon Docker start flow chart:

Docker-3-2

Because of the "Docker source code analysis" seriesDocker Client articlesIn the Docker () has been involved in the main () function to run a lot of previous work.Docker Client articles), and docker Daemon Start will be involved in the work, so this paper omits some of the same, and specific source mainly for only the subsequent and docker daemon related content carries on the thorough analysis, namely mainDaemon () implementation.

5 mainDaemon () of the specific implementation

Through the flow chart of Daemon Docker, we can draw a conclusion: all the work related to Daemon Docker is included in the implementation of mainDaemon () method.

Macroscopically speaking, mainDaemon () to complete the creation of a daemon process, and to make its normal operation.

From the functional point of view, mainDaemon () to achieve the two parts: first, create a Docker running environment; second, service in Client Docker, receive and process the corresponding request.

From the implementation details,Implementation process of mainDaemon ()Mainly contains the following steps:

* the daemon config initiliaze (in this part of the init () function to achieve, that is in front of the mainDaemon () to run executes, but because is closely related to the operation of this part of the content and mainDaemon (), so can think is mainDaemon () operational prerequisite);
* command line flag parameter check;
* create a engine object;
* set engine signal acquisition and processing method;
* load builtins;
* use goroutine to load daemon objects and run;
* print Docker version and drive information;
The creation and operation of Job "serveapi".

Below will be one one in-depth analysis of the above steps.

5 configuration initialization

Before the mainDaemon () run, the config configuration information needed for Daemon Docker has been initialized. Specific implementation is as follows, located in./docker/docker/daemon.go:

(VaR
DaemonCfg = &daemon.Config{}
)
Init func () {
DaemonCfg.InstallFlags ()
}

 

First, declare a variable of the Config type in the daemon package, named daemonCfg. The Config object defines the configuration information required by the Daemon Docker. At the start of Daemon daemonCfg, the Docker variable is passed to Daemon Docker and is used.

The Config object is defined as follows (including the interpretation of some of the attributes)../docker/daemon/config.go:

Config struct type {
String //Docker Daemon PID Pidfile file of the process
Root path used by string //Docker Root runtime
AutoRestart bool / / has been enabled to support docker run, restart the
[]string //Docker DNS using Server Dns
[]string //Docker DnsSearch to use the specified DNS to find the domain name
Mirrors []string / / the specified priority Docker Registry image
EnableIptables bool / / Docker enabled iptables function
EnableIpForward bool / / net.ipv4.ip_forward enabled function
EnableIpMasq bool / / IP enabled camouflage technology
The default IP DefaultIp net.IP / / use the binding container port
BridgeIface string / / add to the existing bridge container network
BridgeIP string / / create the bridge IP address
FixedCIDR string / / IP specified IPv4 subnet, subnet bridge must be included
InterContainerCommunication bool / / host on the same whether to allow communication between the container
String //Docker GraphDriver runtime use of a specific storage drive
GraphOptions storage []string / / set driver options
The specific exec ExecDriver string / / Docker runtime use drive
Mtu int / / MTU container network settings
DisableNetwork bool / / definition, after not initialized
EnableSelinuxSupport bool / / SELinux enabled function support
Context map[string][]string / / definition, after not initialized
}

 

After the declaration of daemonCfg, init () function to achieve the daemonCfg variables in the various attributes of the assignment, the specific implementation is: daemonCfg.InstallFlags (), located in./docker/daemon/config.go, the code is as follows:

Func (*Config InstallFlags) config () {
Flag.StringVar (&config.Pidfile), "P", "[]string{", "-pidfile", "/var/run/docker.pid", "Path", "to use for daemon PID file"
Flag.StringVar (&config.Root), "g", "[]string{", "-graph", "/var/lib/docker", "Path", "to use as the root of the Docker" (runtime)
......
Opts.IPVar (&config.DefaultIp), "#ip", "[]string{", "-ip", "0.0.0.0", "Default", "IP address to use when Binding container ports" ()
Opts.ListVar (&config.GraphOptions, []string{"-storage-opt"}, "storage driver options Set")
......
}

 

In the implementation of InstallFlags () function, the main is to define a certain type of flag parameters, and the value of the parameter is bound to the specified attributes of the config variables, such as:

Flag.StringVar (&config.Pidfile, []string{"P", "-pidfile", "/var/run/docker.pid", "Path", "to use for daemon PID file"

 

The meaning of the above statement is:

* define a flag parameter for the String type;
* the name of the flag is "P" or "-pidfile"";
* the value of the flag is "/var/run/docker.pid", and the value is bound to the variable config.Pidfile;
* the description of the flag information for the to use for Path daemon PID file".

At this point, the configuration information needed for the Daemon Docker is declared and initialized.

5.1 flag parameter check

From this section, the real entry into Daemon mainDaemon Docker () operation analysis.

The first step is the examination of the flag parameter. Specifically, that is, when the docker command is parsed by the flag parameter, the remaining parameters are judged to be 0. If 0, then docker daemon start command is correct, normal operation; not to 0, then the docker daemon is started in the incoming excess parameters at this time will output an error message and exit the program is running. Specific code is as follows:

Flag.NArg if () = 0 {
Flag.Usage ()
Return
}

 

## **5.2 to create engine object * *

In the mainDaemon () in the process of running, flag parameters after the inspection is completed, then create a engine object, the code is as follows:

Eng: = engine.New ()

 

Engine is the running engine of Docker architecture, and it is also the core module of Docker. Engine plays the role of container Docker storage warehouse and manages these containers in the form of job.

stay./docker/engine/engine.goThe Engine structure is defined as follows:

Engine struct type {
Map[string]Handler handlers
Handler catchall
黑客临时牛车/数据(见砍去)
标识字符串
作者输出IO。
作者stderr IO。
STDI N IO。读者
测井bool
任务sync.waitgroup
我sync.rwmutex /锁关闭
关闭布尔
OnShutdown [ ] func() /关机程序
}

 

其中,发动机结构体中最为重要的即为处理属性。该处理属性为地图类型,关键为字符串类型,价值为处理类型类型的定义如下其中处理程序:

式处理功能(工作)状态

 

可见,处理为一个定义的函数。该函数传入的参数为工作指针,返回为状态状态。

介绍完发动机以及处理器,现在真正进入new()函数的实现中:

功能new() *发动机{
英格:=和发动机{
处理程序:使(图[字符串]处理程序),
身份:randomstring()工具,
输出:输出系统,
标准:标准操作系统,
输入:输入系统,
日志:真实,
}
eng.register(“命令”,功能(工作任务)状态{
对于_,名称:=范围工程commands() {
工作。printf(“%s”,名称)
}
返回statusok
})
复制现有的全局处理程序
K、V =范围globalhandlers {
eng.handlers [K] = V
}
回归工程
}

 

分析以上代码,可以知道new()函数最终返回一个发动机对象。而在代码实现部分,第一个工作即为创建一个发动机结构体实例ENG;第二个工作是向ENG对象注册名为命令的处理器,其中处理为临时定义的函数功能(工作任务)状态{ },该函数的作用是通过工作来打印所有已经注册完毕的命令名称,最终返回状态statusok;第三个工作是:将已定义的变量globalhandlers中的所有的处理器,都复制到ENG对象的属性中最后成功返回ENG对象句柄。

5.3设置发动机的信号捕获

回到maindaemon()函数的运行中,执行后续代码:

陷阱(eng.shutdown)信号。

 

该部分代码的作用是:在Docker守护的运行中,设置陷阱特定信号的处理方法,特定信号有SIGINT SIGTERM以及SIGQUIT;当程序捕获到SIGINT或者SIGTERM信号时,执行相应的善后操作,最后保证Docker守护程序退出。

该部分的代码的实现位于。/码头/包装/信号/ trap.go实现的流程分为以下4个步骤:

*创建并设置一个通道,用于发送信号通知;
*定义信号数组变量,初始值为os.sigint,OS。SIGTERM;若环境变量调试为空的话,则添加SIGQUIT信号数组至OS;
*通过gosignal。通知(C,信号…)中通知函数来实现将接收到的信号信号传递给C.需要注意的是只有信号中被罗列出的信号才会被传递给C,其余信号会被直接忽略;
*创建一个goroutine里来处理具体的信号信号,当信号类型为OS。中断或者syscall。SIGTERM时,执行传入陷阱函数的具体执行方法,形参为cleanup(),实参为eng.shutdown。

shutdown()函数的定义位于。/码头/发动机/ engine.go,主要做的工作是为泊坞窗 守护的关闭做一些善后工作。

善后工作如下:

* Docker守护不再接收任何新的工作;
* Docker守护等待所有存活的工作执行完毕;
* Docker守护调用所有关机的处理方法;
*当所有的处理执行完毕,或者15秒之后,shutdown()函数返回。

由于在信号。陷阱(工程停工)函数的具体实现中执行eng.shutdown,在执行完eng.shutdown之后,随即执行操作系统。退出(0),完成当前程序的立即退出。

5.4加载内置

为ENG设置完陷阱特定信号的处理方法之后,Docker守护实现了的加载代码实现如下内置:

如果错误:=内部寄存器(ENG);错误!=无{
日志:致命的(错误)
}

 

The main work is to load the builtins for: engine more than a registered Handler, so that the follow-up in the implementation of the corresponding tasks, run the specified Handler. These Handler include: network initialization, API web service, event query, version view, Registry Docker validation and search. Code implementation is located in./docker/builtins/builtins.go, as follows:

Register error (*engine.Engine Eng) func {
Err if: = daemon (Eng); err! = nil {
Err return
}
Err if: = Remote (Eng); err! = nil {
Err return
}
Err if = events.New ().Install () err (Eng);! = nil {
Err return
}
Err if: = eng.Register ("version", dockerVersion); err! = nil {
Err return
}
Registry.NewService.Install () return (Eng)
}

 

The following analysis of the realization of the most important 5 parts: daemon (Eng), remote (Eng), events.New ().Install (Eng), eng.Register ("version", dockerVersion) and.Install () registry.NewService (Eng) ().

5.4.1 register initialization network driven Handler

Daemon (Eng) to achieve the process, mainly for the eng object registered a key for the "init_networkdriver" Handler, the value of the bridge.InitDriver Handler function, the code is as follows:

Daemon error (*engine.Engine Eng) func {
Eng.Register return ("init_networkdriver", bridge.InitDriver)
}

 

Need to pay attention to is that value to eng object registered handler does not represent the handler function will be run directly, such as bridge.InitDriver, and not directly run, but will bridge.InitDriver entrance to the function, written in Eng handlers to attribute.

The specific implementation of Bridge.InitDriver is located in./docker/daemon/networkdriver/bridge/driver.go, the main effect is:

* get network equipment for Docker service address; bridge *S create the specified IP address;
* configure network iptables rules;
* in addition to the eng object is registered a number of Handler, such as "allocate_interface", "release_interface", "allocate_port", "link"".

5.4.2 registered API service Handler

Remote (Eng) implementation process, mainly for the eng object registered two Handler, respectively, "serveapi" and "acceptconnections"". Code implementation is as follows:

Remote func (*engine.Engine Eng) error {err if: = eng.Register ("serveapi", apiserver.ServeApi); err! = nil {err return} eng.Register return ("acceptconnections", apiserver.AcceptConnections)}, ("") ("").

 

The registration of the two Handler names are "serveapi" and "acceptconnections", the corresponding implementation methods are apiserver.ServeApi and apiserver.AcceptConnections, the specific implementation is located in./docker/api/server/server.go. Which, ServeApi execution. Through the cycle of multiple protocols, create a goroutine to configure the specified http.Server. For different protocol request service; and AcceptConnections mainly in order to inform the init daemon, docker Daemon has been started, you can let the Daemon Docker process to accept the request.

5.4.3 registered events event Handler

Events.New ().Install (Eng), realization process, multiple event registered docker, function is to docker users provide API, so that the user can view the docker internal events information by the API, log information and that count information. Specific code is located in./docker/events/events.go, as follows:

Func (*Events E) Install (*engine.Engine Eng) error {
Jobs: = map[string]engine.Handler{
"Events": e.Get,
"Log": e.Log,
"Subscribers_count": e.SubscribersCount,
}
Name job, for: = jobs range {
Err if: = eng.Register (name, job); err! = nil {
Err return
}
}
Nil return
}

 

5.4.4 registered version of Handler

Eng.Register (the "version", dockerVersion) of the realization of the process, to eng object registration key for "version" and the value is "dockerVersion" execution method handler, dockerVersion during the execution of the will to a version of the job of the standard output write docker's version, docker API version, GIT version, go language runtime version and operating system version information. The specific implementation of dockerVersion is as follows:


DockerVersion engine.Status (*engine.Job job) func {
V: = &engine.Env{}
V.SetJson ("Version", dockerversion.VERSION)
v.setjson(“apiversion”API。apiversion)
v.set(“gitcommit”,dockerversion。gitcommit)
v.set(“goversion”运行。version())
v.set(“操作系统”,运行时。古斯)
v.set(“拱”,运行时。goarch)
如果kernelversion,错误:=内核。getkernelversion();错误= = nil {
v.set(“kernelversion”,kernelversion。string())
}
如果_,错误:= v.writeto(工作。stdout);错误!=无{
返回工作(错误)
}
返回engine.statusok
}

 

5.4.5注册注册表的处理程序

注册表。newservice()。安装(ENG)的实现过程位于。/码头/注册表/ service.go,在ENG对象对外暴露的API信息中添加泊坞窗 注册表的信息。当注册表。newservice()成功被安装安装完毕的话,则有两个调用能够被ENG使用:“验证”,向公有注册表进行认证;“搜索”,在公有上搜索指定的镜像安装的具体实现如下注册表:


函数(的服务)安装(ENG *发动机。发动机)误差{
eng.register(“验证”,s.auth)
eng.register(“搜索”,搜索)
零回报
}

 

至此,所有内部的加载全部完成,实现了向ENG对象注册特定的处理程序。

5.5使用goroutine里加载守护对象并运行

执行完内部的加载,回到maindaemon()的执行,通过一个goroutine里来加载对象并开始运行这一环节的执行,主要包含三个步骤守护进程:

通过init函数中初始化的daemoncfg与ENG对象来创建一个守护对象D;通过守护对象的安装函数,向ENG对象中注册众多的处理;在Docker守护启动完毕之后,运行名为”acceptconnections”的工作,主要工作为向init守护进程发送”准备= 1”信号,以便开始正常接受请求。

代码实现如下:


去func() {
D错误:=恶魔。maindaemon(daemoncfg,ENG)
如果犯错!=无{
日志:致命的(错误)
}
如果错误:= d.install(ENG);错误!=无{
日志:致命的(错误)
}
如果错误:= eng.job(“acceptconnections”)。run();错误!=无{
日志:致命的(错误)
}
}()

 

以下分别分析三个步骤所做的工作。

5.5.1创建守护对象

守护进程。maindaemon(daemoncfg,ENG)是创建守护对象D的核心部分。主要作用为初始化Docker守护的基本环境,如处理配置参数,验证系统支持度,配置Docker工作目录,设置与加载多种驱动,创建图环境等,验证DNS配置等。

由于守护进程。maindaemon(daemoncfg,ENG)是加载Docker守护的核心部分,且篇幅过长,故安排《Docker源码分析》系列的第四篇专文分析这部分。

5.5.2通过守护对象为发动机注册处理程序

当创建完守护对象,goroutine里执行d.install(ENG),具体实现位于。/码头/守护/ daemon.go


功能(后台守护进程(ENG * *)安装发动机。发动机)误差{
为名称,方法:=范围图[字符串]引擎。
“高度”:daemon.containerattach,
......
“image_delete”:daemon.imagedelete,
{
如果错误:= eng.register(名称、方法);错误!=无{
返回错误
}
}
如果错误:=恶魔。repositories()。安装(ENG);错误!=无{
返回错误
}
eng.hack_setglobalvar(“httpapi。守护进程,守护进程)
零回报
}

 

以上代码的实现分为三部分:

*向ENG对象中注册众多的处理对象;
*恶魔。repositories()。安装(ENG)实现了向ENG对象注册多个与图像相关的处理程序,安装的实现位于。/码头/图/ service.go
* eng.hack_setglobalvar(“httpapi。守护进程,守护进程)实现向ENG对象中地图类型的黑客对象中添加一条记录,关键为”httpapi。守护”,价值为守护。

5.5.3运行acceptconnections的工作

在goroutine里内部最后运行名为”acceptconnections”的工作,主要作用是通知init守护进程,Docker守护可以开始接受请求了。

这是源码分析系列中第一次涉及具体工作的运行,以下简单分析”acceptconnections”这个工作的运行。

You can see the first implementation of the eng.Job ("acceptconnections"), the return of a Job, and then the implementation of eng.Job ("acceptconnections").Run (), that is, the implementation of the run Job function.

Eng.Job ("acceptconnections") is located in./docker/engine/engine.go, as follows:


Func (*Engine Eng) Job (string args,, string, name) *Job {
Job: = &Job{
Eng Eng,
Name Name,
Args Args,
NewInput Stdin: (),
NewOutput Stdout: (),
NewOutput Stderr: (),
&Env{} env,
}
Eng.Logging if {
Job.Stderr.Add (utils.NopWriteCloser (eng.Stderr))
}
Handler exists, if: = eng.handlers[name]; exists {
Job.handler = handler
Else if eng.catchall nil}! = = {& & name! "
Job.handler = eng.catchall
}
Job return
}

 

It can be seen from the above code, first create a type for the job of a job object, eng attributes in the object to the caller of the function of Eng, the name property "acceptconnections", no parameter afferents. Also in Eng object all handlers property for key "acceptconnections" recorded values, because in the loading operation builtins remote (Eng) has to eng registered a record, as the key "acceptconnections" and the value is apiserver.AcceptConnections. Therefore the handler object's job is apiserver.AcceptConnections. Finally returns the object that has been initialized job.

After the job object is created, the run () function of the job object is executed. The implementation of Run () function is located in./docker/engine/job.go, the function executes the specified job, and blocks the job before it is executed. For the job object named "acceptconnections", the running code isJob.status = job.handler (job), since the job.handler value is apiserver.AcceptConnections, the real implementation of the job.status = apiserver.AcceptConnections (job).

To enter the specific implementation of AcceptConnections, located in./docker/api/server/server.go, as follows:


AcceptConnections engine.Status (*engine.Job job) func {
Tell the init daemon we are / accepting requests
Systemd.SdNotify go ("READY=1")
ActivationLock if! = nil {
Close (activationLock)
}
Engine.StatusOK return
}

 

Focus on the implementation of systemd.SdNotify go ("READY=1"), located in./docker/pkg/system/sd_notify.go, the main role is to inform the init process Docker Daemon startup has been completed, the potential function is to make Daemon Docker start to accept Client API sent to the Docker request.

So far, it has been completed through the daemon to load the goroutine object and run.

5.6 print Docker version and drive information

Back to the mainDaemon () in the process of running, in the implementation of goroutine, mainDaemon () function of the internal other code will be executed concurrently.

The first implementation of the docker is shown as the version of the information, as well as the ExecDriver and GraphDriver of the two drivers of the specific information, the code is as follows:


Log.Printf ("daemon:%s%s docker;%s execdriver:;%s graphdriver",
Dockerversion.VERSION,
Dockerversion.GITCOMMIT,
DaemonCfg.ExecDriver,
DaemonCfg.GraphDriver,
)

 

5.7 serveapi Job creation and operation

After printing some of the Docker specific information, Daemon Docker immediately created and run called "serveapi" job, the main role for Daemon API to provide Docker access services. Implementation code is located in./docker/docker/daemon.go#L66, as follows:


Job: = eng.Job ("serveapi", flHosts...)
Job.SetenvBool ("Logging", true)
Job.SetenvBool ("EnableCors", *flEnableCors)
Job.Setenv ("Version", dockerversion.VERSION)
Job.Setenv ("SocketGroup", *flSocketGroup)
    
Job.SetenvBool ("Tls", *flTls)
Job.SetenvBool ("TlsVerify", *flTlsVerify)
Job.Setenv ("TlsCa", *flCa)
Job.Setenv ("TlsCert", *flCert)
Job.Setenv ("TlsKey", *flKey)
Job.SetenvBool ("BufferRequests", true)
Err if: = err (); job.Run! = nil {
Log.Fatal (ERR)
}

 

In the implementation process, the first to create a named "serveapi" job, and the value of flHosts to job.Args. The main role of flHost is to provide the Daemon Docker with the use of the address of the protocol. Subsequently, Daemon Docker set up a large number of environmental variables for the job, such as the environmental variables of the secure transport layer protocol, etc.. Finally through the job.Run () to run the job serveapi.

As in key eng for "serveapi" handler, value for apiserver.ServeApi, so the job runtime, the implementation of the apiserver.ServeApi function, is located in the./docker/api/server/server.go. The function of the ServeApi function is mainly for all the support protocols defined by the user, Docker Daemon all create a goroutine to start the corresponding http.Server, respectively, for different protocol services.

As the creation and start http.Server for the Docker architecture in the important content of the relevant Server Docker, "Docker source code analysis" series will be analyzed in fifth articles.

At this point, you can think that Daemon serveapi has completed the job initialization of the Docker. Once the acceptconnections is completed, the init will notify the job process Daemon Docker start up, you can begin to provide API services.

6 Summary

In this paper, from the source point of view of the analysis of the Daemon Docker start, focus on the analysis of the mainDaemon () to achieve.

Daemon Docker as the backbone of the Docker architecture, is responsible for the management of almost all operations within the Docker. Learning Daemon Docker of the specific implementation, you can have a more comprehensive understanding of the Docker architecture. In summary, the operation of the Docker, the carrier for the daemon, scheduling management by the engine, the task is performed by job.

7 introduction of the author

Sun Hongliang,DaoCloudNew team members, software engineers, Zhejiang University computer science graduates.

Graduate school during active in PAAS and docker open source community, in-depth study and enrich the practice of cloud foundry, good at analysis of the underlying platform code, on the platform of the distributed architecture has some experience, has written a lot of depth technology blog.

At the end of 2014 to join the DaoCloud partner to join the team, committed to the spread of Docker based container technology, to promote the pace of the application of the Internet in the container.

Welcome to exchange, mail:Allen.sun@daocloud.io

8 references

[Microsoft announced the next generation of Server Docker will introduce Windows primary support]
[sd_notify, sd_notifyf]
[analysis of Linux initialization init system, the third part: Systemd]
Os] [Package

Reference-Command Line] [Docker




Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 16:49:29 2014/9/11Text link
Read: 5547 comments: 0View comments
]]>
<![CDATA[[原]Docker源码分析(一):Docker架构]]> Http://prog3.com/sbdm/blog/shlazww/article/details/39178469 Http://prog3.com/sbdm/blog/shlazww/article/details/39178469 Shlazww 11:09:07 2014/9/10

1 background

1.1 Docker profile

Docker is an open source Docker company based on lightweight virtualization technology container engine project, the entire project is based on the Go language development, and to comply with the Apache 2 agreement. Currently, Docker can quickly automate the deployment of the container application, and can be used by the kernel virtualization technology (namespaces and cgroups, etc.) to provide the container's resource isolation and security, etc.. Due to the isolation docker through the operating system level virtualization implementations, so docker container at run time, do not need to similar virtual machine (VM) additional cost of operating system, improve the utilization rate of resources, and improve the performance such as io.

Due to open many new characteristics and the project itself and docker in less than two years time is rapidly gaining the favor of many manufacturers, which is including Google, Microsoft, VMware and other industry leaders.Google launched in June this year, Kubernetes, to provide Docker container scheduling services, and in August this yearMicrosoft announced support for Azure on KubernetesThenTraditional virtualization giant VMware announced strong cooperation with Docker. Mid September of this year,Docker is to get $40 million C round of financing, in order to promote the development of distributed applications.

Judging from the current situation, the prospect of Docker is excellent. This series of articles from the source point of view, detailing the structure of the Docker, Docker and the operation of the Docker excellence. This article is the first Docker source analysis series - Docker architecture.

1.2 Docker version information

In this paper, the analysis of the Docker architecture is based on the Docker source code and the corresponding version of the Docker operating results, which Docker for the latest version 1.2.

2 Docker architecture analysis content arrangement

The purpose of this paper is: to understand the Docker source code, based on the analysis of the Docker architecture. The process of analysis is mainly carried out according to the following three steps:

* Docker total frame composition display
* analysis of function and implementation of each module in Docker architecture diagram
* take the execution of the Docker command as an example, to explain the operation process of Docker.

3 Docker total architecture diagram

Learning Docker source code is not a boring process, but you can understand the design principles of Docker architecture. Docker in terms of users is a C / S mode of architecture, and at the rear end of the docker is a very loosely coupled architecture, module to carry out their duties, and organic combinations, docker support operation.

In this, the first Docker total structure, as shown in figure 3.1.

Docker-1-2
Figure 3.1 Docker total architecture

As shown in Figure 3.1, it is not difficult to see that the user is using Client Docker to establish communication with Daemon Docker, and send the request to the latter.

And docker daemon as part the docker architecture. First, provide the server function so that it can accept docker client's request; and engine execution within the docker a series of work, each are in the form of a job.

In the running process of the job, when the container image, from the docker registry download mirror, and the image management driven graphdriver will download the image is stored as a graph; when the network environment need to be created as a docker, through the network management driven networkdriver create and configure the docker container network environment; when the need to limit docker container resources to run or execute an instruction from the user operation, is through the execdriver to complete.

And libcontainer is an independent container management package, networkdriver and execdriver are through the libcontainer to achieve the specific operation of the container.

After executing the command of the running container, an actual Docker container is in the running state, the container has an independent file system, independent and safe operation environment, etc..

The function and implementation of each module in the 4 Docker architecture

Next, we will start with the Docker total frame composition, pumping out the various modules within the framework, and the various modules for a more detailed analysis of the structure and function of the. The main modules are: Client Docker, Daemon Docker, Registry Docker, Graph, Driver, libcontainer, and container Docker.

4.1 Client Docker

Client Docker is a client for Docker architecture to build communication with Daemon Docker. The user can use the executable file for the docker, through the docker command line tool can initiate a large number of management container request.

Client Docker can be established by the following three ways: tcp://host:port, unix://path_to_socket, Daemon and Docker. For the sake of simplicity, this article will use the first method as a prototype for the communication between the two. At the same time, with the docker daemon establishes a connection and transmission request, the docker client can be set through the command line flags parameter set security transmission layer protocol (TLS) parameters, to ensure the safety of the transmission.

Docker client container management request, the docker daemon accepts requests and processes, when docker client receives the return and the corresponding simple processing of the request, docker client a complete life cycle ends. When you need to continue to send the container management request, the user must once again through the docker executable file to create Client Docker.

4.2 Daemon Docker

Daemon Docker is a resident in the Docker architecture in the background of the system process, the function is: to accept and handle the request Client Docker. The process in the background to start a Server, Server is responsible for receiving Client Docker send the request; after receiving the request, Server through routing and distribution scheduling, find the corresponding Handler to perform the request.

Daemon Docker to start the use of the executable file is docker, and Client Docker to start using the same executable file docker. When the docker command is executed, the Daemon Docker and Client Docker are distinguished by the incoming parameters.

Daemon Docker architecture, can be roughly divided into the following three parts: Server Engine, Docker and Job. Daemon architecture as shown in figure 4.1.

Docker-1-2
Fig. 4.1 schematic diagram of Daemon Docker architecture

Docker Server 4.2.1

Server Docker in the Docker architecture is specifically designed to serve Client server Docker. The server function is: accept and dispatch the request to distribute Client Docker. The architecture of Server Docker is shown in Figure 4.2.

Docker-1-3
Fig. 4.2 schematic diagram of Server Docker architecture

During the startup of Docker, a mux.Router is created through the package gorilla/mux, which provides the requested routing function. In gorilla/mux, Golang is a powerful URL router as well as a dispatching distributor. The mux.Router adds a large number of routing entries, each of which is composed of a HTTP request method (PUT, POST, DELETE, or GET), URL, and Handler three parts.

If the docker client through HTTP access docker daemon, created after mux.Router. Docker will server listener address and mux.Router as parameters, to create a httpSrv=http.Server{}, final implementation httpSrv.Serve () to request the service.

In the process of Server service, Server on the listener to accept Client Docker access request, and create a new goroutine to service the request. In a goroutine first read in request content, and analytical work, then find the corresponding routing, then call the corresponding handler to handle the request, the handler to finish processing the request reply to the request.

Need to pay attention to: Server Docker running in the Docker startup process, is to rely on a named "job" of the serveapi to complete the operation. In principle, the docker server operation is many job in a, but to emphasize the importance of docker server and for the important characteristics of the follow-up job services, the "serveapi" of the job alone pumping out of the analysis, understood as a docker server.

Engine 4.2.2

Engine is the Docker architecture in the running engine, while also running the core module Docker. It plays the role of the container Docker storage warehouse, and manages the management of these containers by performing job.

In the design and implementation of Engine data structure, there is a handler object. The handler objects are stored on a number of specific handler job processing access. For example, handler Engine object has one for: {"create": daemon.ContainerCreate,}, then that when the name "create" job in the run, the implementation of the handler daemon.ContainerCreate.

Job 4.2.3

A Job can be considered as the most basic work execution unit within the Engine architecture of Docker. Docker can do every job, can be abstracted as a job. For example: a process is running in the interior of the container, which is a job; to create a new container, which is a job, a document downloaded from the Internet, this is a job; including before in docker server said, creating service server to the HTTP API, which is a job, and so on.

Job designers, the Job design process is similar to the Unix process. For example: Job has a name, there are parameters, there are environmental variables, there is a standard input and output, there are errors, there is a return to the state, etc..

4.3 Registry Docker

Registry Docker is a repository of storage containers. Container mirroring is the document schema and directory that is loaded to initialize the container when the container is created.

In the running process of the docker and docker daemon will communicate with the docker registry, and realize the mirror image search, image download, upload an image of three functions, corresponding to the three functional job name were "search", "pull" and "push".

Among them, in the Docker architecture, Docker can use public Registry Docker, which is known as the Hub Docker, so that Docker access to the container image files, you must access through the InternetDocker HubAt the same time, Docker also allows the user to build a local private Registry Docker, so that the image of the container can be guaranteed to be completed within the network.

4.4 Graph

Graph plays the role of the storage in the Docker architecture, as well as the record of the relationship between the downloaded container mirror image. On the one hand, Graph stores a local version of the information file system image, on the other hand, through the GraphDB records all the file system mirror the relationship between each other. The architecture of Graph is shown in figure 4.3.

Docker-1-4
Fig. 4.3 schematic diagram of Graph architecture

Among them, GraphDB is a small map database built on top of SQLite, which implements the naming of nodes and the relationship between the nodes. It implements only a small subset of most graph databases, but provides a simple interface that represents the relationship between nodes.

At the same time in a local directory for the graph, on every container mirror, specific storage information is: the metadata of the image of the container, container image size information, and represented by the image of the container specific rootfs.

4.5 Driver

Driver is the driver module in the Docker architecture. Through the Driver driver, Docker can be implemented on the Docker container execution environment. Due to the life cycle of the Docker operation, not all of the operations of the user are for the management of the Docker container, in addition to the information on the operation of Docker access, Graph storage and records, etc.. Therefore, in order to separate the management of the Docker container from the Daemon Docker internal business logic, the Driver layer driver is designed to take over all of this part of the request.

In the realization of Driver Docker, can be divided into the following three categories: graphdriver, networkdriver and execdriver.

Graphdriver is mainly used to complete the management of container image, including storage and access. That when users need to download the specified container mirror, graphdriver will container image storage in the specified local directory; at the same time when users need to use the specified container image to create the container rootfs, graphdriver from local mirror storage directory get specified container mirror like.

Before the graphdriver initialization process, there are 4 kinds of file system or class file system in its internal registration, they are aufs, Btrfs, VFS and devmapper. And Docker at the time of initialization, by obtaining the system environment variable "DOCKER_DRIVER" to extract the specified type of the use of driver. And after all the graph operation, the use of the driver to perform.

The architecture of graphdriver is shown in figure 4.4:

Docker-1-5
Fig. 4.4 schematic diagram of graphdriver architecture

Docker container network environment configuration is completed, including start docker docker environment create a bridge networkdriver use; docker container created to create exclusive virtual network device; and docker container allocation of IP, port, and with the host do port mapping, set container firewall policy etc.. The architecture of networkdriver is shown in figure 4.5:

Docker-1-6
Fig. 4.5 schematic diagram of networkdriver architecture

Docker as the execdriver container execution driven, responsible for the creation of the container run namespace, responsible for the statistics and restrictions on the use of container resources, responsible for the actual operation of the internal process of containers, etc.. In the implementation process of execdriver, the original can be used to call the LXC driver LXC interface, to control the configuration of the container as well as the life cycle, and now the default execdriver use native drive, do not rely on LXC. Embodied in the Daemon startup process load the ExecDriverflag parameters, the parameters in the configuration file has been set to native". This can be considered a big change in the 1.2 version of the Docker, or Docker to achieve a threatened cross platform. Execdriver architecture as shown in figure 4.6:

Docker-1-7
Fig. 4.6 schematic diagram of execdriver architecture

4.6 libcontainer

Docker is a libcontainer architecture in the use of Go language design and implementation of the library, the design is to hope that the library can not rely on any dependence, direct access to the kernel and the container related API.

It is because of the existence of Docker, libcontainer can directly call libcontainer, and the final control of the container namespace, cgroups, AppArmor, network equipment, as well as the rules of the firewall. The completion of this series of operations do not need to rely on LXC or other packages. Libcontainer architecture as shown in figure 4.7:

Docker-1-8
Fig. 4.7 schematic diagram of libcontainer

In addition, libcontainer provides a set of standard interfaces to meet the requirements of the upper layer for container management. Or, libcontainer shielded the Docker upper layer of the container's direct management. And due to the libcontainer using the go this cross platform language development to achieve and, in turn, may be accessed by multiple upper layer of different programming languages, so it is hard to say, future docker will tightly and Linux bundled together. While at the same time, Azure in its famous cloud computing platform Microsoft, also added support for Docker, the degree of openness of the industry and the industry's fiery degree Docker.

Don't talk docker, due to libcontainer and itself and the system of loose coupling characteristics, is likely to in other container for the prototype of the platform, but also may hasten the birth of cloud computing in the field of new projects.

4.7 container Docker

Container Docker (Docker container) is the final embodiment of service delivery in the Docker architecture.

Docker according to the needs of users and instructions, ordered the corresponding Docker container:

* the user can customize the rootfs and other file systems by specifying the container mirroring;
* the user makes the Docker container using the specified computing resource by specifying the quota for the computing resource;
* users through the configuration of the network and its security policy, so that the Docker container has an independent and secure network environment;
* the user performs the specified job by specifying the run command to make the Docker container.

The schematic diagram of the Docker container is shown in figure 4.8:

Docker-1-9
Fig. 4.8 schematic diagram of Docker container

5 Docker operation case analysis

The last chapter focuses on the introduction of the various parts of the Docker architecture. The contents of this chapter will be based on a series of Docker modules to brief analysis, analysis of the prototype for the docker pull docker and run Docker two commands.

5.1 pull docker

The role of the pull docker command is to download the specified container image from the Registry Docker and store it in the local Graph to prepare for the subsequent creation of the Docker container. Pull docker command execution process as shown in figure 5.1.

Docker-1-10-1
Fig. 5.1 schematic diagram of pull docker command execution process

As shown in the figure, the red arrow marked in the graph indicates that the pull docker command is initiated, and the Docker is running a series of operations. One by one analysis of these steps.

(1) Client docker accepts pull Docker command, after analyzing the request and the collection of the request parameters, send a HTTP request to Server Docker, HTTP request method for POST, request /images/create for "URL" + "XXX"";

(2) Server Docker accepts the above HTTP request, and hand over to mux.Router, mux.Router through URL and request method to determine the implementation of the request of the specific handler;

(3) mux.Router will request routing distribution to the corresponding handler, specific to PostImagesCreate;

(4) in the PostImageCreate of the handler, a pull called "job" was created and started to perform;

(5) the "pull" of the job in the implementation process, the implementation of the pullRepository operation, that is, from the Registry Docker to download the corresponding one or more image;

(6) named "pull" job will download the image to the graphdriver;

(7) graphdriver is responsible for the storage of image, one party to create graph objects, on the other hand in the relationship between image records GraphDB.

5.2 run docker

The role of the run docker command is to run an instruction within a completely new Docker container. Docker in the implementation of this order, the work can be divided into two parts: first, to create the Docker container required rootfs; second, to create a network of containers and other operating environment, and the actual operation of the user instructions. Therefore, in the entire implementation process, Client Docker to Server Docker to send a two HTTP request, the second request is initiated by the first request to return the state. Docker Run command execution process as shown in figure 5.2.

Docker-1-11-1
Fig. 5.2 schematic diagram of run docker command execution process

As shown in the figure, the red arrow marked in the graph indicates that the run docker command is initiated, and the Docker is running a series of operations. One by one analysis of these steps.

(1) after docker client accept docker the run command to and analysis after the request and collected after the request parameters and send an HTTP request to docker server, HTTP request method is post, the request URL as "/containers/create? + the XXX;

(2) Server Docker accepts the above HTTP request, and hand over to mux.Router, mux.Router through URL and request method to determine the implementation of the request of the specific handler;

(3) mux.Router will request routing distribution to the corresponding handler, specific to PostContainersCreate;

(4) in the PostImageCreate of this handler, a named "job" create was created, and began to make the job run;

(5) called "create" job in the running process, the implementation of the Container.Create operation, the operation needs to obtain the container image to create a Docker for the rootfs container, that is called graphdriver;

(6) graphdriver from Graph to get all the mirrors that are needed to create the Docker container rootfs;

(7) graphdriver will rootfs all images, loaded into the Docker container specified file directory;

(8) if the above operations are all normal, no return error or exception, then Client Docker received Server Docker return state, initiated the second HTTP request. Request method for "POST", request /containers/ for "+container_ID+" /start "URL"";

(9) Server Docker accepts the above HTTP request, and hand over to mux.Router, mux.Router through URL and request method to determine the implementation of the request of the specific handler;

(10) mux.Router will request routing distribution to the corresponding handler, specific to PostContainersStart;

(11) in the PostContainersStart of this handler, called "job" start was created and started to perform;

(12) a start named "job" after the implementation of the initial configuration of the work, began to configure and create a network environment, call networkdriver;

(13) networkdriver needs to create a network interface device for the specified Docker container, and assign it to IP, port, and set firewall rules, and the corresponding operation is referred to the netlink package in libcontainer;

(14) netlink completion of the Docker container network environment configuration and creation;

(15) to return to the name "start" of the job, after the implementation of some of the auxiliary operations, job began to execute the user instructions, call execdriver;

(16) execdriver is called to initialize the Docker container internal running environment, such as namespace, resource control and isolation, as well as the execution of the user commands, the corresponding operation to libcontainer to complete;

(17) libcontainer is called to complete the operation environment within the Docker container initialization, and the final implementation of the user requirements to start the command.

6 Summary

The from docker 1.2 source of analysis and abstract docker's chart, and each module in the architecture diagram of function and analysis of the implementation, the two docker command shows the docker's internal operation.

Through the study of Docker architecture, we can comprehensively deepen the understanding of Docker design, function and value. At the same time in the use of Docker to achieve the user customized distributed system, but also to better find the existing platform and Docker more ideal fit point. In addition, familiar with the existing Docker architecture and design ideas, but also can bring more inspiration to the field of cloud computing PaaS, gave birth to more practice and innovation.

7 introduction of the author

Sun Hongliang,DaoCloudNew team members, software engineers, Zhejiang University computer science graduates.

Graduate school during active in PAAS and docker open source community, in-depth study and enrich the practice of cloud foundry, good at analysis of the underlying platform code, on the platform of the distributed architecture has some experience, has written a lot of depth technology blog.

At the end of 2014 to join the DaoCloud partner to join the team, committed to the spread of Docker based container technology, to promote the pace of the application of the Internet in the container.

Welcome to exchange, mail:Allen.sun@daocloud.io

8 references

[Docker (software) Wikipedia] -From [Docker Architecture]
Libcontainer [Docker]
[simple Docker (1): Docker core technology preview]
0.9: introducing execution drivers and [Docker libcontainer]
Lost packages of docker] [The


Welcome to pay attention to the Docker source code analysis of the public number

Author: shlazww published in 11:09:07 2014/9/10Text link
Read: 5855 comments: 0View comments
]]>
<![CDATA[[译]开源的服务发现项目Zookeeper,Doozer,Etcd]]> Http://prog3.com/sbdm/blog/shlazww/article/details/38736511 Http://prog3.com/sbdm/blog/shlazww/article/details/38736511 Shlazww 0:29:45 2014/8/22

This article is Wilder Jason for common service discovery projectZookeeper,Doozer,EtcdWrite a blog, the original address is as follows:Open-Source Discovery Service.


Service discovery is a core component of most distributed systems and service oriented architecture (SOA). This problem, simply speaking, can be considered: when a service exists in a number of host nodes, the client side of the decision to get the appropriate IP and port.


In the traditional case, when a service exists in a number of host nodes, it will use the static configuration method to realize the registration of service information. But when you need to deploy more services in large systems, it's much more complicated. In a real-time system, due to the expansion of automatic or manual service, or service of the newly added deployment and the host downtime or replaced, the location information of the service may will be very frequent changes.


In such a scenario, dynamic service registration and discovery are especially important in order to avoid unnecessary service interruptions.


About the topic of service discovery, has been mentioned many times, but also in the development of. Now, the author introduces some of the open-source in the field or is often widely discussed by the world's solutions, trying to understand how they work. Special is that we will focused more on each solution consistency algorithm, in the end is strong consistency, or weak consistency; run-time dependence; client integration selection; after the characteristics of these compromises.


This article first from several strong consistency of the project at the beginning, such as Zookeeper, Doozer, Etcd, these projects are mainly used for the coordination of services, and can be used for the registration of services.


Subsequently, this article will discuss some of the more interesting items in the service registration and discovery, such as: SmartStack Netflix, Eureka Airbnb, NSQ Bitly, Serf, and DNS Spotify, and finally SkyDNS.



Problem statement


When positioning services, in fact, there will be two aspects of the problem: service registration (Registration Service) and service discovery (Discovery Service).
  • Service registration: a service to register its location information at the center of a registered node. The service generally will host its IP address and port number for registration, and sometimes there will be service access authentication information, the use of the agreement, version number, and some details about the environment.
  • Service discovery - client end of the application of an instance of the query center to learn the location of the location of the registration process.
The service registration and service discovery of each service will need to consider some problems about development and operation:
  • Monitor - how to deal with the failure of a registered service. In some cases, the service is cancelled immediately after a set of timeout timer (timeout), which is registered at the center by a number of other processes. In this case, the service is usually required to perform a heartbeat mechanism to ensure its own survival; and the client will need to be able to reliably handle the failure of the service.
  • Load balancing - how to balance the load of all client requests in these services, if more than one service is registered? If there is a master node, then, if you can properly handle the location of client access services.
  • Integration mode - does the information registered node need to provide support for some language bindings, for example, only supports Java? Does the integration process need to embed the registration process and code into your application, or to use a process that is similar to an integrated assistant?
  • Run time dependent - does it require JVM, ruby, or any other runtime that is not compatible in your environment?
  • Availability - if the system loses a node, is it still working? Can the system be updated or upgraded in real time without causing any paralysis of the system? Since the cluster information is the central part of the structure, the module will be a single point of failure?


Strong consistency of Registries

First, the three service registration systems are introduced. The strong consistency protocol is used to achieve the general effect. Although we see them as a service registration system, they can also be used to coordinate services to assist leader elections, as well as to do locking centralized in a distributed clients collection.


Zookeeper


Zookeeper is a centralized service that can maintain service configuration information, namespace, provide distributed synchronization, as well as provide a group of services. Zookeeper is achieved by the Java language, to achieve a strong consistency (CP), and is to useZab protocolCoordination of service information change between ensemble clusters.


Zookeeper runs 3, 5 or 7 members in a ensemble cluster. Many client ends in order to be able to access ensemble, you need to use a specific language binding. This type of access is explicitly embedded in the application instance of client and the service.


The implementation of service registration is mainly through the command space (namespace) under theNodes ephemeral. Nodes ephemeral only after the establishment of the connection client. When the client where the node is started, the client will use a background process to get the location of the client information, and complete its own registration. If the client fails or loses the connection, the ephemeral Node message from the tree.


Service discovery is done by listing and viewing the namespace of the specific service. Client side receives the information of all the registered services, whether a service is not available or the system has added a new kind of service. Client side also need to handle all the load balancing work, as well as the failure of the service work.


API Zookeeper may not be so convenient, because the language of the binding may cause some small differences between. If you are using a language based on JVM,Service Discovery Extension CuratorMay be helpful to you.


Because the zookeeper is a CP strong consistency of the system, so when network partition (partition) fault, part of your system may will can not be registered, may also appear to be unable to find existing registration information, even though they may be present during the normal work of the partition. Special is that in any one of the non-quorum side, any read and write will return an error message.


Doozer


Doozer is a consistent distributed data storage system, Go language implementation, throughPaxos algorithmStrong consistency system to achieve consensus. After several years of development, the project has been stalled for some time, and now has shut down some of the fork, which has reduced the number of fork to 160. Unfortunately, it is difficult to know the actual state of development of the project, and whether it is suitable for use in the production environment.


Doozer runs 3, 5 or 7 nodes in a cluster. Similar to Client, the Zookeeper is bound to use special language in its own applications or services, in order to access the cluster.


Doozer service registration is not so directly Zookeeper, because Doozer does not have the concept of those node ephemeral. A service can register itself in a path, and it will not automatically be removed if the service is not available.


There are many ways to solve this problem. A choice is to a registered process to add a timestamp and heartbeat mechanism, and subsequently in the service discovery process to deal with the timeout of the path is the registration information, of course, can also be achieved through another cleanup process.


Service discovery is very similar to Doozer, Zookeeper can list all the entrances under the specified path, then you can wait for any changes in the path. If you use a time stamp and heartbeat during the registration period, you can ignore or delete any expired entries during service discovery.


Like Doozer, Zookeeper is a CP strong consistency system, which can lead to the same result when a network partitioning failure occurs.


Etcd


        EtcdIs a highly available K-V storage system, mainly used in shared configuration, service discovery, etc.. Etcd can be said to be the birth of Zookeeper and Doozer and out. The whole system using Go language, using the Raft algorithm to achieve the election, while having a API based HTTP+JSON.


Etcd, similar to Doozer and Zookeeper, usually run in clusters of 3, 5 or 7 nodes. Client client can use a specific language binding, but also can be achieved through the use of HTTP client to achieve a.


Service registration is mainly dependent on the use of a TTL key to ensure the availability of key, the TTL key and the server will be tied to the heart. If a service fails to update TTL's key, the Etcd will have to deal with it over time. If a service becomes unavailable, client will have to deal with such a connection failure, and then try to connect to a service instance.


Service discovery link is designed to list all the key values in a directory, and then wait for all the changes in the directory information. Since the API interface is based on HTTP, the client application will maintain a Etcd connection to the long-polling cluster.


Due to the use of EtcdRaft consistency protocol, so it should be a strong consistency system. Raft needs a leader to be elected, and then all the client requests will be processed by the leader. However, Etcd also seems to support reading information from the non-leaders, using the method is in the case of reading to improve the availability of non disclosure of the consistency of the parameter. During the network partition fault, the write operation will be handled by leader, and the same will be the case of failure.    



About the author:

Sun Hongliang,DAOCLOUDSoftware engineer. In the past two years, the main research areas of PaaS related knowledge and technology in the field of cloud computing. Firmly believe that the technology of lightweight virtual container, will bring the depth of the impact of the PaaS field, and even determine the future direction of PaaS technology.


Reproduced please indicate the source.

This article is more out of my own understanding, in some places, there are some deficiencies and errors. I hope this article will be able to contact the service found that some help, if you are interested in this area, and have better ideas and suggestions, please contact me.

My email address: allen.sun@daocloud.io
Sina weibo:Fu Ruqing lotus seed


Welcome to pay attention to the Docker source code analysis of the public number
Author: shlazww published in 0:29:45 2014/8/22Text link
Read: 9172 comments: 1View comments
]]>
<![CDATA[[原]Cloud Foundry中warden的网络设计实现——iptable规则配置]]> Http://prog3.com/sbdm/blog/shlazww/article/details/38687113 Http://prog3.com/sbdm/blog/shlazww/article/details/38687113 Shlazww 13:37:07 2014/8/20        

In the Foundry V2 Cloud version, the platform uses warden technology to implement the resource control and isolation of the user application instance.


Brief introduction warden is DEA ng if need to run user applications (this temporarily do not consider the warden container provides the staging package environment), send the corresponding request to the warden server, by the warden server to create the warden container, and warden container internal operation and application examples, and the warden container implementation using cgroups kernel virtualization technology, to ensure that the container process group of resource control and isolation. Warden architecture and implementation can refer to my blog:Cloud Architecture and implementation of warden in Foundry.



Warden network architecture diagram


Warden container function can be considered similar to the traditional virtual machine, is a traditional virtual machine through the hypervisor technology to realize the control of resources and isolation, and the warden container through virtualization kernel to achieve the purpose. And in the network, the warden container technology create a virtual NIC, specifically for the warden container internal use, also as warden container within the virtual network card in the warden server where the host also matched a virtual NIC as container exterior gateway. Just create two virtual network card, the principle can ensure physical "connected", but it is difficult to achieve network communication between "China Unicom", so the physical resources and complete physical and virtual resources. The warden Server in the host machine through the iptables design and add a number of rules, to ensure that the entire network of communication can meet the requirements of container warden, while not affecting the host computer communication.


The following is the physical environment of the host host server iptables where warden is located in the network layer, operating system, user application layer diagram:


Container warden network communication mode


In Foundry Cloud, because container warden is used to run the user application example, and the application of the user instance and the external communication in Foundry Cloud at present, there are no more than two kinds of:
  1. User application examples as a server web, providing HTTP access services;
  2. User application examples using service services, the establishment of the connection with the instance service.
Of course, some Foundry Cloud platform developers will certainly think that the user application examples, can be used as a client side, through the URL access to other application examples or access to resources outside the cloud. Here need to affirm is, first of all, cloud foundry cluster default of an applied example is not exposed IP; secondly, assuming the cloud foundry internal does not exist or is unable to connect a powerful DNS server to resolve external resource URL.

This paper will be more than two points as the main research content, the host warden host network analysis, focusing on the iptables one.


Iptables warden configuration of the net.sh file

       
In the realization process of warden, the configuration of iptables mainly includes two parts:
  1. When starting server warden, call the fileWarden/warden/root/linux/net.sh, to develop the server warden host host parts of the iptables rules;
  2. When you create a container warden, call the fileWarden/warden/root/linux/skeleton/net.sh, make the iptables rule that you need to add since container warden is created (including just create a warden Iptables container settings, as well as a container iptables to do when the port mapping warden settings.

Server net.sh warden

       

Setup_filter

       
aboutWarden/warden/root/linux/net.sh, you can see the shell script is the most critical of the two methods setup_filter and setup_nat. The following is the setup_filter source code to achieve:
Setup_filter function () {
Teardown_filter

# Create or flush forward chain
Iptables -N ${filter_forward_chain} 2> /dev/null iptables -F ${filter_forward_chain} ||
-A ${filter_forward_chain} -j DROP iptables

# Create or flush default chain
Iptables -N ${filter_default_chain} 2> /dev/null iptables -F ${filter_default_chain} ||

Always allow established connections to warden # containers
iptables -美元filter_default_chain } { m连接跟踪-- ctstate建立,相关-j ACCEPT

N $ { allow_networks };做
如果[美元] =“”
然后
打破
FI

iptables -美元filter_default_chain } -目的地“{ $ N”--跳回来
完成

N $ { deny_networks };做
如果[美元] =“”
然后
打破
FI

iptables -美元filter_default_chain } -目的地“{ $ N”--跳落
完成

iptables -美元filter_default_chain } {拒绝--跳

#接受数据包与先前建立的连接
iptables -我输入M州成立,相关--跳接受M评论评论相关交通

#拒绝交通从容器到主机
如果[“allow_host_access美元”!=“真的”,然后
iptables -输入的pool_network } {美元--跳拒绝M评论评论阻塞主机
FI

#提出对外交通filter_forward_chain通过$ { }
iptables -了我- + -跳转$ { filter_forward_chain }

#入境交通立即向前
default_interface = $(IP路由显示| grep默认|割D’F5 |头- 1)
我filter_forward_chain } { iptables -美元-我default_interface美元--跳接受
}


以下首先逐步分析每个部分iptables的制定的意义,随后将各iptables个则串联起来分析其功能在内核中的简要流程图如下图关于iptables:


以下逐步分析filter_setup方法:

1。在该净。SH文件中,teardown_filter方法所做的工作是:清除某些区长相关的iptable链以及规则。随后的即创建两条链:filter_forward_chain以及filter_forward_chain,加入这两条链先前存在的话,清楚该两条链之后再创建。

2。对于已经和看守集装箱建立完毕的连接,iptables都执行接受操作,代码即:
#总是允许建立连接管理员的容器
iptables -美元filter_default_chain } { m连接跟踪-- ctstate建立,相关-j ACCEPT
由注释可以发现,该规则添加在filter_default_chain链中,当匹配条件为:该数据包表示为是在已建立的连接上传输时,对该数据包采取接受操作。该规则从功能的角度很好理解,也就是:假如看守集装箱内部发起一个请求,向外建立一个连接,则在该连接上返回数据包时,始终接受这样的数据包。然而,我始终对该规则的底层实现,抱有很大的疑惑。待下文分析了更多的区长网络背景知识之后,再进行进一步的阐述。

3。在filter_default_chain中,对于allow_networks中的网络主机地址,始终采取接受操作;而对于deny_networks中的网络主机地址,使用采取滴操作。在此,可以简要说明一下在iptables中滴与拒绝的区别。滴:直接采取丢弃数据包的操作;拒绝:对于原来的数据包采取丢弃措施,随后向数据包的发送方,返回一个类似于ICMP错误的信息包。

4。之后的壳代码为:iptables - { }——美元filter_default_chain跳拒绝,由于iptables中一个数<BR>
据包在同一个链中的规则匹配将从第一条开始匹配,遇到匹配成功则执行相应操作,否则继续向下执行,因此该规则表明这条脸中之前都匹配不成的数据包,内核会采取拒绝操作,将数据包丢弃,并返回一个错误数据包。到此,filter_default_chain中的规则设置基本完毕。

5。在输入链中添加规则,所谓输入链,即当网卡发现接收到的网络数据包的目的与网卡的IP,IP一致时,将该数据包放入输入链执行规则处理,此处的代码如下:
#接受数据包与先前建立的连接
iptables -我输入M州成立,相关--跳接受M评论评论相关交通

#拒绝交通从容器到主机
如果[“allow_host_access美元”!=“真的”,然后
iptables -输入的pool_network } {美元--跳拒绝M评论评论阻塞主机
FI
Set the rules in the INPUT chain, to ensure that the warden host on the original and external to establish the connection, the data sent to the package, will take the ACCEPT operation. Followed by allow host access variables to determine whether to allow the warden container and warden server where the host between communication, if the variable is false, for from sending packets in pool networks is taken to reject operation, ensure the warden the internal container can't access the warden server where the host asked. Here, the rules for the INPUT chain has been completed.

6 the development of FORWARD in the iptables chain, the so-called FOWARD
Create the warden container chains of net.sh, that when the received network packet's destination IP network discovery, are inconsistent with the network card IP is considered need for the data packets forwarded (forward) operation, the data packet into the forward chain rule processing is performed, where the code is as follows:
# Forward outbound traffic via ${filter_forward_chain}
-A FORWARD -i w-+ --jump iptables ${filter_forward_chain}

Forward inbound traffic immediately #
Default_interface=$(route show ip grep default cut '-d' head '-f5 -1)
-I ${filter_forward_chain} -i $default_interface --jump iptables ACCEPT
The first rule said: for from the network device interface name for 'w-+' (regular expressions, which is the warden container and virtual virtual NIC device name) to send, and it also needs to perform forwarding data packets, the packet jump to filter forward chain chain. This ensures that all from the container warden issued, it is not sent to the host host's data packets, enter the FORWARD chain directly into the filter_forward_chain chain.
 
The latter rule indicates that the data packet in the filter_forward_chain, as long as it is from the default_interface, will be taken by the ACCEPT operation. That is, when the data packet is found in the server warden host filter_forward_chain host physical network card, immediately to the data package to take ACCEPT operation.

So far, the net.sh file filter setup method have steps analysis is completed, then about the execution of the entire flow, the reader may still will have no small doubts, such as when, binding filter default chain chain, making the data packets enter the chain, and so on. After the analysis of another net.sh file, and then unified exposition.


Setup_nat

      
The following simple analysis of the setup_nat method:
Setup_nat function () {
Teardown_nat

# Create prerouting chain
Iptables -t NAT -N ${nat_prerouting_chain} 2> /dev/null true ||

# Bind chain to PREROUTING
(iptables -t NAT -S PREROUTING grep -q | "\-j ${nat_prerouting_chain}\b") ||
Iptables -t NAT -A PREROUTING.
--jump ${nat_prerouting_chain}

# Bind chain to OUTPUT (for traffic originating from same host)
(iptables -t NAT -S OUTPUT grep -q | "\-j ${nat_prerouting_chain}\b") ||
Iptables -t NAT -A OUTPUT.
--out-interface \ "Lo"
--jump ${nat_prerouting_chain}

# Create postrouting chain
Iptables -t NAT -N ${nat_postrouting_chain} 2> /dev/null true ||
# Bind chain to POSTROUTING
(iptables -t NAT -S POSTROUTING grep -q | "\-j ${nat_postrouting_chain}\b") ||
Iptables -t NAT -A POSTROUTING.
--jump ${nat_postrouting_chain}

# Enable NAT for traffic coming from containers
(iptables -t NAT -S ${nat_postrouting_chain} grep -q | "\-j SNAT\b") ||
Iptables -t NAT -A ${nat_postrouting_chain}.
--source \ ${POOL_NETWORK}
--jump \ SNAT
--to ($external_ip)
}

The content of this part is relatively easy to understand:

1 first create the nat_prerouting_chain chain, and then all the data packets in the PREROUTING chain are to jump to nat_prerouting_chain;

2 then the chain is bound on the nat_prerouting_chain, to ensure that the data packets through the lo network equipment, have to jump to the chain;

3 create the nat_postrouting_chain chain, which ensures that all packets in the default POSTROUTING chain are jumping to the creation of the chain;

4 for the data packets sent from container SNAT are taken warden processing, so that the source of the data package IP are replaced by server warden host IP.


In fact, after the completion of the above two steps, but also the implementation of the following code:

# Enable forwarding
Echo 1 > /proc/sys/net/ipv4/ip_forward

To ensure that the forwarding work can be effective, the specific content can be viewed:The role of /proc/sys/net/ipv4/* in various parts.



Create container net.sh warden

       

The first analysis is that, when server warden start, the host of the server warden host iptbales settings, in the whole process, does not involve any of the container. And this chapter will introduce the analysis of server warden in the start of a specific container warden, and then server warden host host set iptables rules. The file address is as follows:Warden/warden/root/linux/skeleton/net.sh.


Setup_filter


The first analysis of the setup_filter method, the source code is as follows:

Setup_filter function () {
Teardown_filter

# Create instance chain
Iptables -N ${filter_instance_chain}
Iptables -A \ ${filter_instance_chain}
--goto ${filter_default_chain}

# Bind instance chain to forward chain
Iptables -I ${filter_forward_chain} \ 2
--in-interface \ ${network_host_iface}
--goto ${filter_instance_chain}

# Create instance log chain
Iptables -N ${filter_instance_log_chain}
Iptables -A \ ${filter_instance_log_chain}
-p TCP -m conntrack --ctstate NEW, UNTRACKED INVALID, -j LOG --log-prefix ${filter_instance_chain} ""

Iptables -A \ ${filter_instance_log_chain}
--jump RETURN
}

1 this method creates a chain of instance, and then, all packets in the container instance warden chain jumped to filter_default_chain, which is the filter_default_chain mentioned in the previous chapter;

Binding. The warden container instance of the forward chain to filter foward chain, that is, all data packets entering the filter foward chain, according to the data packet from which network interface device, enter the appropriate filter instance chain chain. That is, from the network_host_iface network device"Receive"To the data package (network_host_iface is theNetwork_container_iface="W-${id}-1"), all go to filter_instance_chain.

3 create chain log.



Setup_nat

       

When you create a container warden, you will also set the NAT, the source code is as follows:

Setup_nat function () {
Teardown_nat
# Create instance chain
Iptables -t NAT -N ${nat_instance_chain}
# Bind instance chain to prerouting chain
Iptables -t NAT -A ${nat_prerouting_chain}.
--jump ${nat_instance_chain}
}

A brief analysis is to create the corresponding nat_instance_chain, and then the data packets in the nat_prerouting_chain will jump to the nat_instance_chain.


Port mapping implementation of net_in

       

The cloud foundry warden container user application examples for external web service to provide, then the warden container and the warden server where the host a port mapping operations, is the warden server provides the net interface, real implementation part is creating a container of the net.sh file in parameters of execution.


The following is the net_in specific operation of the source code to achieve:

The "in")
[if -z then] "${HOST_PORT:-}";
Echo "Please specify HOST_PORT 1>&2..."
Exit 1
Fi
[if -z then] "${CONTAINER_PORT:-}";
Echo "Please specify CONTAINER_PORT 1>&2..."
Exit 1
Fi
Iptables -t NAT -A ${nat_instance_chain}.
--protocol \ TCP
--destination \ "${external_ip}"
--destination-port \ "${HOST_PORT}"
--jump \ DNAT
--to-destination "${network_container_ip}: ${CONTAINER_PORT}"
;;

Shows that the most important part of the code block is the part that creates the DNAT rule transformation. Is in the corresponding instance rule chain, for the TCP data package, if the packet destination IP address and destination port where the warden server host IP and mapping of the port, the implementation of DNAT conversion, conversion for the warden container IP and the warden of container port.


summary

      

Above is the Foundry V2 warden in the Cloud network design of the iptables rules, made a brief analysis. However, in this, there are a lot of design is simply to leave the interface, did not really realize.



On the other, thanks to the VLIS Laboratory of Zhejiang University joint research interns from the high.


About the author:

Sun Hongliang,DAOCLOUDSoftware engineer. In the past two years, the main research areas of PaaS related knowledge and technology in the field of cloud computing. Firmly believe that the technology of lightweight virtual container, will bring the depth of the impact of the PaaS field, and even determine the future direction of PaaS technology.


Reproduced please indicate the source.

This article is more out of my own understanding, in some places, there are some deficiencies and errors. I hope this article will be able to contact the warden network configuration of the people some help, if you are interested in this area, and have better ideas and suggestions, please contact me.

My email address: allen.sun@daocloud.io


Author: shlazww published in 13:37:07 2014/8/20Text link
Read: 1690 comments: 2View comments
]]>
<![CDATA[[原]Cloud Foundry中DEA启动应用实例时环境变量的使用]]> Http://prog3.com/sbdm/blog/shlazww/article/details/38037595 Http://prog3.com/sbdm/blog/shlazww/article/details/38037595 Shlazww 13:31:48 2014/7/22 In Foundry V2 Cloud, when the application users need to start the application example, the user through the CLI cloud to controller CF to send a request, and controller cloud to DEA through to forward the request to start NATS. Implementation of the real start matters is DEA, the DEA is mainly doing the work for starting a warden container, and copy the contents of the droplet into the interior of the container, finally finished configuring the specified environment variables, under these environmental variables start application startup scripts.


This article will explain how to use the Foundry DEA as an example of the startup configuration environment variable Cloud.


DEA receive application startup request and its execution process


In this part, the DEA is used to illustrate the execution flow of the application startup request.

  1. First DEA subscription to the corresponding theme of the message, the theme of "dea.#{bootstrap.uuid}.start", the meaning of the application of its own DEA start message":
    Subscribe ("dea.#{bootstrap.uuid}.start") |message| do
    Bootstrap.handle_dea_directed_start (message)
    End
  2. After receiving the subscription, the implementation of bootstrap.handle_dea_directed_start (message), meaning "through the bootstrap class instance to handle the application of the start request":
    Handle_dea_directed_start def (message)
    Start_app (message.data)
    End
  3. It can be considered that the processing of the inlet, that is, the above code in the start_app method:
    Start_app def (data)
    Instance = instance_manager.create_instance (data)
    Unless instance return
    
    Instance.start
    End
  4. In the app start method, first of all through the instance manager instance to create an instance object, by executing instance instance method of the class start, it can be seen from the beginning to the end, the parameters of the transfer, the original source is through NATs message to the message, which is 1 in the message:
    Start def (&callback)
    P = do Promise.new
    ......
    [
    Promise_droplet,
    Promise_container
    ].each (& run).Each (& resolve)
    [
    Promise_extract_droplet,
    Promise_exec_hook_script ('before_start'),
    Promise_start
    ].each (&: resolve)
    ......
    P.deliver
    End
  5. Among them, the implementation of the real application startup in promise_start method is implemented:
    Promise_start def
    Do |p| Promise.new
    Env = Env.new (StartMessage.new (@raw_attributes), self)
    Staged_info if
    Command = start_command staged_info['start_command'] ||
    Command unless
    P.fail (MissingStartCommand.new)
    Next
    End
    Start_script =
    Dea:: StartupScriptGenerator.new (
    Command,
    Env.exported_user_environment_variables,
    Env.exported_system_environment_variables
    )。
    其他的
    start_script = env.exported_environment_variables +”。/启动;\ nexit”
    结束
    反应容器(start_script产卵=,
    容器。resource_limits(self.file_descriptor_limit,nproc_limit))
    [’] = response.job_id 'warden_job_id属性
    container.update_path_and_ip
    bootstrap.snapshot.save
    p.deliver
    结束
    结束

可以看到在第5步中,DEA涉及到了应用的env环境变量等信息,最后通过产卵方法实现了应用的启动容器。


DEA环境变量的配置


在以上步骤的第5步,首先创建了环境变量env = env。新(startmessage。新(@ raw_attributes),自我),环境类的初始化方法如下:

初始化(消息,instance_or_staging_task = nil)
“strategy_env =如果message.is_a?stagingmessage
stagingenv新(消息,instance_or_staging_task)。
其他的
runningenv新(消息,instance_or_staging_task)。
结束
结束

可见,实际是创建了一个runningenv类的实例,参数主要为云控制器发送来的信息。


在promise_start方法中,创建env变量之后,通过判断staged_info来选择start_script变量的构建。


现在分析staged_info的代码实现:

DEF staged_info
“staged_info | | =开始
dir.mktmpdir做| destination_dir |
staging_file_name =“staging_info吗”。
copied_file_name =“# { } { } destination_dir / # staging_file_name”
copy_out_request(“/家/粒/ # { staging_file_name }”,destination_dir)
YAML。load_file(copied_file_name)如果file.exists?(copied_file_name)
结束
结束
结束

主要是通过指定路径,然后从路径中提取出变量。下面以一个红宝石的应用为例,其staging_info YML文件的内容为:

---
detected_buildpack:红宝石/架
start_command:束exec rackup config.ru P $港

因此,最终@ staged_info的内容如上,在实例。开始方法中,命令为束exec rackup config.ru - P端口。有了命令变量之后,接着是构建start_script变量:

start_script =
DEA::新(startupscriptgenerator。
命令,
env.exported_user_environment_variables,
env.exported_system_environment_variables
)。

可以看到,DEA通过startupscriptgenerator类来创建start_script,其中参数为三个,第一个为刚才涉及到的命令,后两个均需要通过env变量来生成。


现在看exported_user_environment_variables方法的实现:

DEF exported_user_environment_variables
to_export(translate_env(消息。env))
结束

该方法实现从消息中提取中属性为env的信息,作为用户的环境变量。

       

进入exported_system_environment_variables的方法实现env:

DEF exported_system_environment_variables
env = [
[“vcap_application”,yajl::编码器编码(vcap_application)],
[“vcap_services”,yajl::编码器编码(vcap_services)],
[“memory_limit”、“# {消息。mem_limit } m”]
]
env << [“database_url”,databaseurigenerator。新(信息服务)。database_uri ]如果message.services.any?

to_export(信封+ strategy_env。exported_system_environment_variables)
结束

可见在生成系统的环境变量的时候,首先创建一个env数组变量,其中有信息vcap_application,vcap_services,memory_limit三种,其中vcap_application的信息如下:

DEF vcap_application
“vcap_application | | =
开始
strategy_env.vcap_application hash =

哈希[“限制”] = message.limits
哈希[“application_version”] = message.version
哈希[“application_name”] = message.name
哈希[“application_uris”] = message.uris
#翻译键向后兼容性
哈希[“版本”] =哈希[“application_version”]
哈希[“name”] =哈希[“application_name”]
URIs "hash[" = application_uris "hash["]
Users "hash[" = application_users "hash["]

Hash
End
End
 
This section contains information about the application of name, URIs, users, version and a series of content. Which requires special attention is the code hash = strategy_env.vcap_application, the role of the code to call the vcap_application class in the RunningEnv method, as follows:

Vcap_application def
Hash = {}
Instance_id "hash[" = instance_id "instance.attributes["]
Instance_index "hash[" = message.index
Host "hash[" = HOSTStartupScriptGenerator
Port "hash[" = instance.instance_container_port
Started_at = Time.at (instance.state_starting_timestamp)
Started_at "hash[" = started_at
Started_at_timestamp "hash[" = started_at.to_i
Start "hash[" = started_at "hash["]
State_timestamp "hash[" = started_at_timestamp "hash["]
Hash
End

Visible in the above code, Vcap application information recorded a lot of information about the application, including the instance ID, instance index, host, port and started at and started at timestamp start state timestamp.

VCAP_SERVICES information is as follows:

WHITELIST_SERVICE_KEYS label tags plan plan_option =%W[name credentials syslog_drain_url].freeze
Vcap_services def
@vcap_services ||=
Begin
Services_hash = Hash.new h[k] = {|h, k|} []

Do |service| message.services.each
Service_hash = {}
Do |key| WHITELIST_SERVICE_KEYS.each
Service_hash[key] = if service[key] service[key]
End

Services_hash[service["label" "service_hash"
End

Services_hash
End
End

This part of the main content from the message to find whether the existence and the value of WHITELIST_SERVICES_KEYS as a key value, if there is, to join the variable services_hash.

Subsequently, the DEA in running the code env ["database URL. DatabaseUriGenerator.new message.services. Database..database_uri] if message.services.any, this part of the code mainly to understand the DatabaseUriGenerator meaning. In this part, the author is still not very clear.


Then, data envelopment analysis (DEA) to execute code to export (Env + strategy Strategy_env.exported_system_environment_variables system environment variables, this part of the content is very important, mainly to enter higher-level env where the object class view exported system environment variables method:

Exported_system_environment_variables def
Env = [
["HOME", "$PWD/app"],
["TMPDIR", "$PWD/tmp"],
["VCAP_APP_HOST", HOST],
["VCAP_APP_PORT", instance.instance_container_port],
]
Env "[" PORT "," $VCAP_APP_PORT "]
ENV
End

You can see, here is mainly contains information on the operation of the environment variables, such as the HOME directory, TMP temporary directory, application running host address, application examples to run the port number. One of the most important is the application example of the operation of the port number, in my another blog post.Foundry DEA in Cloud and warden communication to complete the application port monitoringIn the middle, it is related to how to open up the port through the server warden, the final DEA is used, and through the form of environmental variables to pass to the application example of the startup script. Where PORT and warden are VCAP_APP_PORT Container opens the port number.


Analysis of the three parameters of the StartupScriptGenerator, the need to enter the generate class StartupScriptGenerator method:

Generate def
Script = []
Script "" umask 077"
@system_envs "script"
EXPORT_BUILDPACK_ENV_VARIABLES_SCRIPT "script"
@user_envs "script"
Script < < env > logs/env.log"
Script "START_SCRIPT% @start_command
Script.join ("\n")
End

The code above is the process of creating a startup script. Where @system_envs for the analysis of the previous env.exported_system_environment_variables, @user_envs for env.exported_user_environment_variables. There are two scripts that are EXPORT_BUILDPACK_ENV_VARIABLES_SCRIPT and START_SCRIPT, and the EXPORT_BUILDPACK_ENV_VARIABLES_SCRIPT script is as follows, which means all the SH scripts in a certain path:

EXPORT_BUILDPACK_ENV_VARIABLES_SCRIPT = strip_heredoc (<<-BASH).Freeze
设置gem_path
如果[ -三维应用程序/。
为我在应用程序/。配置文件。
如果[ - [ - ]
。我的
FI
完成
撤消我
FI
bash

而start_script代码如下:

start_script = strip_heredoc(<< - bash)。冻结
droplet_base_dir = $ pwd
光盘应用程序
(%s)> >(TEE droplet_base_dir美元/日志/ stdout。日志)2 > >(TEE droplet_base_dir美元/日志/ stderr.log > 2)&
开始= $!
回声“$开始“> > droplet_base_dir美元/ run.pid

等待$开始
bash

以上即创建完了start_script,回到实例。Rb中的promise_start方法中,即执行
反应容器(start_script产卵=,
容器。resource_limits(self.file_descriptor_limit,nproc_limit))

即完成应用实例的启动工作详情可以进入类中的产卵方法实现容器。


关于作者:

孙宏亮,daocloud软件工程师。两年来在云计算方面主要研究PaaS领域的相关知识与技术。坚信轻量级虚拟化容器的技术,会给PaaS领域带来深度影响,甚至决定未来PaaS技术的走向。


转载请注明出处。

本文更多出于我本人的理解,肯定在一些地方存在不足和错误。希望本文能够对接触DEA环境变量的人有些帮助,如果你对这方面感兴趣,并有更好的想法和建议,也请联系我。

我的邮箱:allen.sun@daocloud.io
新浪微博:“莲子弗如清


       

作者:shlazww发表于2014 / 7 / 22 13:31:48原文链接
阅读:1680评论:0查看评论
]]>
<![CDATA[[原]Cloud Foundry中gorouter对StickySession的支持]]> http://prog3.com/sbdm/blog/shlazww/article/details/37817547 http://prog3.com/sbdm/blog/shlazww/article/details/37817547 shlazww 2014 / 7 / 15 20:00:18 云作为业界出众的PaaS平台,在应用的可扩展性方面做得非常优秀。


具体来讲,在一个应用需要横向伸展的时候,云可以轻松地帮助用户做好伸展工作,也就是创建出一个应用的多个实例,多个实例地位相等,多个实例共同为用户服务,多个实例共同分担访问压力。


大致来说,可以认为是共同分担访问压力,但是也不是针对所有该应用的访问,都进行均衡,分发到不同的应用实例处。譬如:当云的访问用户访问应用时,第一次的访问,gorouter会将请求分发到应用的某个实例处,但是如果该用户之后的访问都是有状态的,不希望之后的访问会被分发到该应用的其他实例处。针对以上这种情况,云提供了自己的解决方案,使用stickysession的方式,保证请求依旧分发给指定的应用实例。


本文即分析云中gorouter关于stickysession的实现方式。


该部分内容需要对gorouter有一定的了解,可以参见笔者之前的博文:云中gorouter源码分析


关于stickysession的信息,gorouter所做的工作,主要分为两个部分:如何给HTTP请求添加stickysession、如何通过stickysession辨别应用的具体实例。


如何给HTTP请求添加stickysession

        

在分析这个问题的时候,首先我们需要提出另一个问题:什么情况下需要给HTTP请求添加stickysession?


首先,来看这样的一个方法setupstickysession的去语言实现:

函数(H *请求处理程序)setupstickysession(endpointresponse * http.response,终点*路线。端点){
needsticky:= false
对于_,V =范围endpointresponse。cookies() {
如果诉的名字= = stickycookiekey {
needsticky =真
打破
}
}

如果needsticky & endpoint.privateinstanceid!=“”
饼干:饼干{ =和HTTP。
名称:vcapcookieid,
价值:endpoint.privateinstanceid,
路径:“/”,
}

HTTP。setcookie(h.response,饼干)
}
}
      

紧接着,查看setupstickysession方法何时被调用的代码:

函数(H *请求处理程序)handlehttprequest(运输* http.transport,终点*路线。端点)(* http.response,错误){
h.transport =运输

h.setuprequest(终点)
H. setupconnection()

endpointresponse,错误:=(h.request)往返运输。
如果犯错!=无{
返回endpointresponse,呃
}

h.forwardresponseheaders(endpointresponse)

h.setupstickysession(endpointresponse,终点)

返回endpointresponse,呃
}


在setupstickysession方法中,可以看到:首先进入一个循环语句块中,当endpointresponse中的饼干中有名为stickycookiekey的话,将needsticky字段置为真实,跳出循环。这里也就回答了什么时候需要给HTTP请求添加stickysession的问题。关于stickycookiekey的值,可以先看一下gorouter的设置:

const(
vcapcookieid =“__vcap_id__”
stickycookiekey =“JSESSIONID”
)

可以看到stickycookiekey的值为JSESSIONID,而JSESSIONID是Tomcat对会话ID的称呼,在其他容器中就不一定叫JSESSIONID了。因此,如果平台运维者自定义了一种容器的buildpack,而这个容器中对于会话ID的称呼不为JSESSIONID的话,那么粘性会话在gorouter中将不能被实现,除非将这部分内容自行进行改写,或者修改该容器对会话ID的称呼。


紧接着在setupstickysession中,通过一个判断,来给响应创建一个饼干,饼干有创建的名字字段,价值字段以及路径字段。最后通过HTTP。setcookie(h.response,饼干)来实现对响应的设置添加饼干。


读完setupstickysession方法的实现,现在进入调用该方法的handlehttprequest方法,该方法的主要工作是:将HAProxy代理来的请求,转发给具体相应的DEA上的应用实例,最后构建该请求的响应信息,并返回该响应信息。在返回响应响应信息的之前,gorouter为该响应信息设置了stickysession。


以上便是如何给HTTP请求添加stickysession,以下分析如何通过stickysession辨别应用的具体实例。


如何通过stickysession辨别应用的具体实例

        
当一个请求到达gorouter的时候,gorouter需要首先辨别该请求中是否带有stickysession的信息,如果有的话,,gorouter分析该请求中的相应信息,最终得到指定应用实例的信息,并将请求转发到该指定应用实例。具体实现代码如下:
功能(P *代理)查找(请求* HTTP请求)(* route.endpoint,bool){
uri:=路线。URI(hostwithoutport(要求))

/试着用粘性的会话选择一个后端
如果_,错误:=请求。饼干(stickycookiekey);错误= = nil {
如果粘,错误:=请求。饼干(vcapcookieid);错误= = nil {
routeendpoint,好:= p.registry。lookupbyprivateinstanceid(URI,粘粘的,值)
如果可以
返回routeendpoint,OK
}
}
}

/ /选择后端使用主机单独
返回p.registry查找(URI)。
}

从源码中可以看到,首先从请求中提取出URI,随后分析请求中是否带有stickycookiekey,也就是JSESSIONID,若有的话,继续分析是否带有vcapcookieid,也就是__vcap_id__,若有的话,那说明是gorouter支持的stickysession,从粘中找出价值属性对应的值,也就是应用privateinstanceid,通过该ID寻找出具体对应的是应用的哪个实例,最后返回该应用实例的具体信息,当然包括最终该实例的IP:端口。如果以上这些stickycookiekey或者vcapcookieid不存在的话,也就是说该请求不支持stickysession,那么将直接通过URI,寻找某一个应用实例来为该请求服务。

以上便是云中gorouter对stickysession的支持与实现。


关于作者:

Sun Hongliang,DAOCLOUDSoftware engineer. In the past two years, the main research areas of PaaS related knowledge and technology in the field of cloud computing. Firmly believe that the technology of lightweight virtual container, will bring the depth of the impact of the PaaS field, and even determine the future direction of PaaS technology.


Reproduced please indicate the source.

This article is more out of my own understanding, in some places, there are some deficiencies and errors. I hope this article will be able to contact the gorouter and StickySession people some help, if you are interested in this area, and have better ideas and suggestions, please contact me.

My email address: allen.sun@daocloud.io





Author: shlazww published in 20:00:18 2014/7/15Text link
Read: 882 comments: 0View comments
]]>
<![CDATA[[原]Cloud Foundry中DEA与warden通信完成应用端口监听]]> Http://prog3.com/sbdm/blog/shlazww/article/details/37757587 Http://prog3.com/sbdm/blog/shlazww/article/details/37757587 Shlazww 12:09:01 2014/7/14 In the Foundry V2 version of DEA, Cloud for a user application running control module, and the real operation of the application is attached to the warden. More specifically speaking, cloud controller request is received by the DEA; DEA sends a request to the warden server; warden server to create a warden container and droplet of user applications such as environment configuration; DEA send application startup request to the warden serve; last warden container execution startup script to start the application.


This paper mainly describes how warden interacts with DEA to ensure that the application of the end user can be successfully bound to a certain port, and to provide services to the users.


Data envelopment analysis (DEA) in the implementation of the start of an application, mainly do these parts: promise droplet, promise container, which finished the two partially concurrent; promise extract droplet promise exec hook script ("before start") promise start and. Code as follows:

[
Promise_droplet,
Promise_container
].each (& run).Each (& resolve)

[
Promise_extract_droplet,
Promise_exec_hook_script ('before_start'),
Promise_start
].each (&: resolve)


Promise_droplet:

In this link, the DEA is mainly to do the work is the droplet the downloaded, through droplet URI, the basic path in /config/dea.yml. As the base Base_dir: /tmp/dea_ng ng, so final DEA to download droplet stored on DEA components where the host machine.

 

Promise_container:

The work of the link to complete the creation of a container warden, and then can provide a suitable environment for the operation of the application. Promise_container source code to achieve as follows:

Promise_container def
Do |p| Promise.new
Bind_mounts = [{'src_path'= droplet.droplet_dirname,'dst_path' = droplet.droplet_dirname}]
With_network = true
Container.create_container (
Bind_mounts bind_mounts: + config['bind_mounts'],
Config['instance']['cpu_limit_shares'] limit_cpu,
Disk_limit_in_bytes byte,
Config.instance_disk_inode_limit inode,
Memory_limit_in_bytes limit_memory,
With_network setup_network:)
Attributes['warden_handle'] = container.handle
Create_container promise_setup_def (params)
Bind_mounts,: limit_cpu,: byte,: inode,: limit_memory,: do |param| setup_network].each
ArgumentError raise, "#{param.to_s} parameter to create container expecting if" params[param].nil?
End

Do with_em
New_container_with_bind_mounts (params[: bind_mounts])
Limit_cpu (params[: limit_cpu])
Limit_disk (params[byte:: byte], params[inode:: inode])
Limit_memory (params[: limit_memory])
If params[setup_network: setup_network]
End
Endenvironment.resolve
P.deliver
End
End


Can see the main parameters of the incoming:
Bind_mounts: the path to the host file directory mount to container inside;
Limit_cpu: CPU resource allocation for restricted container;
Byte: disk quota;
Innode: disk innode limit
Limit_memory: memory limit;
Setup_network: network configuration items.

 

Which setup_network has been set to true.


In the implementation of the container.create_container method, there are the following methods, as follows:

Create_container def (params)
[:bind_mounts,:::limit_cpu,字节,limit_memory inode,:,:setup_network ]。每做|参数|
提高argumenterror,期望# {参数。to_s }参数createdef create_container(参数)
[:bind_mounts,:::limit_cpu,字节,limit_memory inode,:,:setup_network ]。每做|参数|
提高argumenterror,期望# {参数。to_s }参数创建容器”如果参数[参数]。零?
结束

with_em做
new_container_with_bind_mounts(params [:bind_mounts ])
limit_cpu(params [:limit_cpu ])
limit_disk(字节:参数[:字节],[:]:参数inode节点)
limit_memory(params [:limit_memory ])
setup_network如果参数[:setup_network ]
结束
“如果最终容器参数[参数]。零?
结束

with_em做
new_container_with_bind_mounts(params [:bind_mounts ])
limit_cpu(params [:limit_cpu ])
limit_disk(字节:参数[:字节],[:]:参数inode节点)
limit_memory(params [:limit_memory ])
setup_network如果参数[:setup_network ]
结束
结束

 

主要关注一下setup_network方法,如下:

DEF setup_network
要求::::=典狱长协议::netinrequest新(手柄:手柄)。
响应=调用(:应用程序,请求)
network_ports [ 'host_port’] = response.host_port
network_ports [ 'container_port’] = response.container_port

要求::::=典狱长协议::netinrequest新(手柄:手柄)。
响应=调用(:应用程序,请求)
network_ports [ 'console_host_port’] = response.host_port
network_ports [ 'console_container_port’] = response.container_port
结束

 

从代码中可以看到,在setup_network中,主要完成了两次网操作。对于网操作,需要说明的是,完成的工作是将主机主机上的端口映射到集装箱内部的端口。换言之,将host_ip:1映射到container_ip:P2,也就是说如果集装箱在container_ip上监听的是端口P2,则主机机器外部的请求访问主机机器,并且端口为port1的时候,主机的内核网络栈,会将请求转发给集装箱的PORT2端口,其中使用的协议为DNAT协议。


因此,在以上的代码中实现了两次网操作,也就是说将集装箱的两个端口映射到了主机宿主机,第一个端口用于集装箱内应用的正常占用端口,第二个端口是用来为应用的控制台功能做服务。虽然集装箱也分配了第二个端口,但是在而后的应用启动等中,该console_port都没有使用过,可见云在这里只是预留了接口,但是没有真正利用起来。


以上主要描述了网的功能,以下进入操作的源码实现网。网的源码实现,主要为管理员服务器的部分。其中,是由DEA进程通过狱长袜子和管理员服务器建立通信,随后DEA进程发送网请求给典狱长典狱长服务器,服务器最终处理该请求。

 

现在进入区长范畴,研究区长如何接收请求,并实现端口的映射。
在管理员/ lib /管理员/服务器。Rb中,大部分代码都是为了完成管理员服务器的运行,在跑!方法中,可以看到管理员服务器另外还启动了一个Unix域服务器,代码如下:

服务器::em.start_unix_domain_server(unix_domain_path,clientconnection)

 

也就是说,典狱长服务器会通过整个Unix域服务器接收从DEA进程发送来的关于看守集装箱的一系列请求,在clientconnection类中定义,关于这部分请求如何处理的方法。


当Unix域服务器中clientconnection类通过receive_data(数据)方法来实现接收请求,代码如下:

DEF receive_data(数据)
“缓冲区”
@buffer.each_request做|请求|
开始
receive_request(请求)
救援=
close_connection_after_writing
记录器。警告(“断开客户端后错误”)
记录器。log_exception(E)
结束
结束
结束

 

Can be seen from the code, when there is a request in the receive_request, through the buffer (request) method to further extract the request. Then enter the receive_request (request) method, you can see through the process (request) to deal with the request.

 

Then enters the real request processing section, also when process (request) realizes:

Process def (request)
Request case
Protocol: when: PingRequest
Response = request.create_response
Send_response (response)

Protocol: when: ListRequest
Response = request.create_response
Response.handles = Server.container_klass.registry.keys.map (& to_s)
Send_response (response)

Protocol: when: EchoRequest
Response = request.create_response
Response.message = request.message
Send_response (response)

Protocol: when: CreateRequest
Container = Server.container_klass.new
Container.register_connection (self)
Response = container.dispatch (request)
Send_response (response)

Else
Request.respond_to if? (: handle)
Container = find_container (request.handle)
Process_container_request (request, container)
Else
WardenError.new raise ("request: #{request.class.name.split Unknown (": ").Last}")
End
End
Rescue WardenError = e
Send_error (E)
Rescue = > e
Logger.log_exception (E)
Send_error (E)
End

 

Visible, in the warden server request type can be simply divided into five: PingRequest, ListRequest, EchoRequest, CreateRequest and other requests, like request NetIn is belong to other requests in a program execution into the case statement block the else branch, is:

Request.respond_to if? (: handle)
Container = find_container (request.handle)
Process_container_request (request, container)
Else
WardenError.new raise ("request: #{request.class.name.split Unknown (": ").Last}")
End

        

Code clearly visible, server warden first through the handle to find the specific which is to send a request to container warden, and then call process_container_request (request, container) method. Enter process_container_request (request, container) method can see: join request type is not as StopRequest as well as StreamRequest, then enter the case block else branch, the implementation of the code:

Response = container.dispatch (request)
Send_response (response)

 

Can be seen, is called the container.dispatch (request) method to return to the response.

 

The following entry into the warden/lib/warden/container/base.rb file, the dispatch method of the file to achieve the main server warden to receive requests and pre processed, how to distribute the implementation of specific requests, code as follows:

Dispatch def (request, &blk)
Klass_name = request.class.name.split ("::").Last
Klass_name = klass_name.gsub (/Request$/, "")
Klass_name = klass_name.gsub (/ (.) ([A-Z]) /) {#{m[0]}_#{m[1]} "|m|"}
Klass_name = klass_name.downcase

Response = request.create_response

T1 = Time.now

Before_method = "before_%s"% klass_name
Hook (before_method, request, response)
Emit (before_method.to_sym)

Around_method = "around_%s"% klass_name
Hook (around_method, request, response) do
Do_method = "do_%s"% klass_name
Send (do_method, request, response, &blk)
End

After_method = "after_%s"% klass_name
Emit (after_method.to_sym)
Hook (after_method, request, response)

T2 = dispatch Time.ndef (request, &blk)
Klass_name = request.class.name.split ("::").Last
Klass_name = klass_name.gsub (/Request$/, "")
Klass_name = klass_name.gsub (/ (.) ([A-Z]) /) {#{m[0]}_#{m[1]} "|m|"}
Klass_name = klass_name.downcase

Response = request.create_response

T1 = Time.now

Before_method = "before_%s"% klass_name
Hook (before_method, request, response)
Emit (before_method.to_sym)

Around_method = "around_%s"% klass_name
钩(around_method,请求做响应)
do_method =“do_ %“% klass_name
发送(do_method,请求,响应,及黑色)
结束

after_method =“after_ %“% klass_name
发出(after_method。to_sym)
钩(after_method,请求,响应)

T2 =时间

记录器的信息(“%s(带%。6F)“% [ klass_name,T2 - T1 ],
:请求= > request.to_hash,
:反应= >响应to_hash)。

响应
赋予

记录器的信息(“%s(带%。6F)“% [ klass_name,T2 - T1 ],
:请求= > request.to_hash,
:反应= >响应to_hash)。

响应
结束

 

首先提取出请求的类型名,如果是网请求的话,提取出来的请求的类型名称为net_in,随后构建出方法明do_method,也就是do_net_in,接着就通过发送(do_method,请求,响应和BLK)方法,将参数发送给do_net_in方法。

 

现在就是进入管理员/ lib /管理员/容器/功能/净。Rb文件中,do_net_in方法实现如下:
 

DEF do_net_in(请求、响应)
如果request.host_port.nil?
host_port = self.class.port_pool.acquire

#使用相同的端口在容器侧边如果未指定主机
container_port = request.container_port | | host_port

#端口可能被重新使用后容器已被破坏
@资源[端口] << host_port
“后天的[端口] << host_port
其他的
host_port = request.host_port
container_port = request.container_port | | host_port
结束

_net_in(host_port,container_port)

“资源”net_in [“] | | = []
“资源”net_in [“] << [ host_port,container_port ]

response.host_port = host_port
response.container_port = container_port
救援wardenerror
自我。类。port_pool释放(除非request.host_port host_port)。
提高
结束


可见,如果请求端口没有指定的话,那么就使用代码host_port =自我。类。port_pool。获得来获取端口号,默认情况下,集装箱端口号与主机端口号保持一致,有了这两个端口号之后,执行代码_net_in(host_port,container_port),真正实现端口映射,如下:

DEF _net_in(host_port,container_port)
sh文件。加入(container_path,“净。SH”),“在”:环境= > {
“host_port”= > host_port,
“container_port”= > container_port,
}
结束

 

可以清晰的看到是,使用了容器内部的净。SH脚本来实现端口映射。现在进入监狱长/根/ Linux /骨架/净。SH脚本,进入参数为在的执行部分:

“在”
如果[ Z $ { host_port:- }”];然后
echo“请指定host_port…“1 > 2
退出1
FI
如果[ Z $ { container_port:- }”];然后
echo“请指定container_port…“1 > 2
退出1
FI
iptables - T的NAT -美元nat_instance_chain }、{
——协议\
目的地”——美元external_ip } {”
——目的港“$ { host_port }”
——跳DNAT \
--目的地“$ { network_container_ip }:$ { container_port }”
;;

 

可见,该脚本这部分的功能是在主机主机创建一条DNAT规则,使得主机主机上所有host_port端口上的网络请求,都转发至network_container_ip:container_port上,也就是完成了目标地址IP转变。

 

promise_extract_droplet:

该环节主要完成的是让集装箱运行脚本,使得集装箱容器将位于主机主机的滴文件,解压至集装箱内部,代码内容如下:

DEF promise_extract_droplet
promise.new做| P |
脚本=“CD /家/粒/和焦油ZXF # droplet_path } {滴。”
容器。run_script(:应用程序、脚本)
p.deliver
结束
结束

promise_exec_hook_script('before_start”):

这部分主要完成的功能是让容器运行名为before_start的脚本,在老的版本中,该部分的设置默认为空。


promise_start:

This part is mainly to complete the application of the start. When you create a container, return the port number, will be saved by DEA. Eventually, when DEA started the application, due to the DEA will port number is passed as a parameter to the application startup script, so when you start the application will automatically to listen for it has been set the port and port monitor.

 

 

About the author:

Sun Hongliang,DAOCLOUDSoftware engineer. In the past two years, the main research areas of PaaS related knowledge and technology in the field of cloud computing. Firmly believe that the technology of lightweight virtual container, will bring the depth of the impact of the PaaS field, and even determine the future direction of PaaS technology.


Reproduced please indicate the source.

This article is more out of my own understanding, in some places, there are some deficiencies and errors. I hope this article will be able to contact the warden port mapping people some help, if you are interested in this area, and have better ideas and suggestions, please contact me.

My email address: allen.sun@daocloud.io

Author: shlazww published in 12:09:01 2014/7/14Text link
Read: 1521 comments: 3View comments
]]>