烂翻译系列之Kubernetes实战——构建应用

With the general overview of the application behind us, it’s time to start building the application. Instead of going straight to the full-blown version of the application, we’ll take things slow and build the application iteratively throughout the book.

对应用做了总体概述之后,现在是时候开始构建应用了。我们将放慢速度并迭代应用的构建,而不是直奔包含所有特性的应用版本。

Introducing the initial version of the application  应用初始版本介绍

The initial version of the application that you’ll run in this chapter, while supporting both HTML and plain-text modes, will not display the quote and pop quiz, but merely the information about the application and the request. This includes the version of the application, the network hostname of the server that processed the client’s request, and the IP of the client. Here’s the plain-text response that it sends:

在本章中,你将运行应用的初始版本,它同时支持HTML和纯文本模式,不显示引述和快速测验,仅显示应用信息和请求信息。这包含应用的版本,处理客户端请求的服务的网络宿主名称,客户端IP。这里是应用返回的纯文本响应:

Kiada version 0.1. Request processed by "<server-hostname>". Client IP: <client-IP>

The application source code is available in the book’s code repository on GitHub. You’ll find the code of the initial version in the directory Chapter02/kiada-0.1. The JavaScript code is in the app.js file and the HTML and other resources are in the html subdirectory. The template for the HTML response is in index.html. For the plain-text response it’s in index.txt.

应用的源代码可以在GitHub上本书的代码仓库中获取。你可以在Chapter02/kiada-0.1文件夹中找到初始版本的代码。JavaScript代码在app.js文件里并且HTML和其它资源在html子文件夹中。HTML响应模板在index.html文件中。纯文本响应在index.txt文件中。

You could now download and install Node.js locally and test the application directly on your computer, but that’s not necessary. Since you already have Docker installed, it’s easier to package the application into a container image and run it in a container. This way, you don’t need to install anything, and you’ll be able to run the same image on any other Docker-enabled host without installing anything there either.

你现在可以在你的计算机上下载并安装Node.js并测试应用,但不是必要的。因为你已经安装了Docker,可以轻而易举地打包应用到容器镜像并在容器中运行应用。这样,你无需安装任何东西,并且你将可以在任何其它启用Docker的主机(主机上无需安装其他软件)上运行相同的镜像。

Creating the Dockerfile for the container image  为构建容器镜像创建Dockerfile

To package your app into an image, you need a file called Dockerfile, which contains a list of instructions that Docker performs when building the image. The following listing shows the contents of the file, which you’ll find in Chapter02/kiada-0.1/Dockerfile.

要将应用打包到镜像中,你需要一个名为Dockerfile的文件,该文件包含Docker在构建镜像时应该执行的指令列表。以下清单显示了Dockerfile文件的内容,你可以在Chapter02/kiada-0.1/Dockerfile找到此文件。

FROM node:12
COPY app.js /app.js
COPY html/ /html
ENTRYPOINT ["node", "app.js"]

The FROM line defines the container image that you’ll use as the starting point (the base image you’re building on top of). The base image used in the listing is the node container image with the tag 12. In the second line, the app.js file is copied from your local directory into the root directory of the image. Likewise, the third line copies the html directory into the image. Finally, the last line specifies the command that Docker should run when you start the container. In the listing, the command is node app.js.

FROM行定义了你将其作为起点的容器镜像(构建镜像的基础镜像)。清单中使用标签为12的node容器镜像作为基础镜像。在第二行中,将app.js文件从本地目录复制到镜像的根目录中。同样地,第三行将html文件夹复制到镜像。最后,最后一行指定在启动容器时,Docker应该运行的命令。在清单中,Docker应该运行的命令是node app.js。

CHOOSING A BASE IMAGE
选择一个基础镜像 You may wonder why use this specific image as your base. Because your app is a Node.js app, you need your image to contain the node binary file to run the app. You could have used any image containing this binary, or you could have even used a Linux distribution base image such as fedora or ubuntu and installed Node.js into the container when building the image. But since the node image already contains everything needed to run Node.js apps, it doesn’t make sense to build the image from scratch. In some organizations, however, the use of a specific base image and adding software to it at build-time may be mandatory.
你可能想知道为什么使用这个特定的镜像作为基础镜像。因为你的应用是一个node.js应用,需要镜像包含node二进制文件,以运行应用。你可以使用包含此二进制文件的任何镜像,或者甚至可以使用Linux发行版基础镜像,比如fedora或者ubuntu,并在构建镜像时将Node.js安装到容器中。但是由于node镜像已经包含了运行node.js应用所需的所有内容,所以从头构建镜像没有意义。然而,在一些组织中,使用特定的基础镜像并在构建时向其添加软件可能是强制性的。

Building the container image  构建容器镜像

The Dockerfile, the app.js file, and the files in the html directory is all you need to build your image. With the following command, you’ll build the image and tag it as kiada:latest:

Dockerfile文件,app.js文件和html文件夹是你构建镜像时所需的全部文件。使用下面的命令,你将构建名为kiada:latest的镜像:

$ docker build -t kiada:latest .
Sending build context to Docker daemon  3.072kB
Step 1/4 : FROM node:12
12: Pulling from library/node
092586df9206: Pull complete
ef599477fae0: Pull complete
...
89e674ac3af7: Pull complete
08df71ec9bb0: Pull complete
Digest: sha256:a919d679dd773a56acce15afa0f436055c9b9f20e1f28b4469a4bee69e0...
Status: Downloaded newer image for node:12
 ---> e498dabfee1c
Step 2/4 : COPY app.js /app.js
 ---> 28d67701d6d9
Step 3/4 : COPY html/ /html
 ---> 1d4de446f0f0
Step 4/4 : ENTRYPOINT ["node", "app.js"]
 ---> Running in a01d42eda116
Removing intermediate container a01d42eda116
 ---> b0ecc49d7a1d
Successfully built b0ecc49d7a1d
Successfully tagged kiada:latest

The -t option specifies the desired image name and tag, and the dot at the end specifies that Dockerfile and the artefacts needed to build the image are in the current directory. This is the so-called build context.

-t选项指定所需的镜像名称和标记,末尾的点指定包含Dockerfile和构建上下文(构建过程所需的所有工件)的目录路径为当前文件夹。

When the build process is complete, the newly created image is available in your computer’s local image store. You can see it by listing local images with the following command:

当构建过程完成后,可以在计算机的本地镜像存储中使用新创建的镜像。可以通过下面的命令列出本地镜像来查看它。

$ docker images
REPOSITORY   TAG      IMAGE ID           CREATED             VIRTUAL SIZE
kiada        latest   b0ecc49d7a1d       1 minute ago        908 MB
...

Understanding how the image is built  理解镜像是如何构建的

The following figure shows what happens during the build process. You tell Docker to build an image called kiada based on the contents of the current directory. Docker reads the Dockerfile in the directory and builds the image based on the directives in the file.

下图显示了构建过程中发生的事情。你指示Docker基于当前目录中的内容构建一个名为kiada的镜像。Docker读取目录中的Dockerfile文件,并基于Dockerfile文件中的指令构建镜像。

 

The build itself isn’t performed by the docker CLI tool. Instead, the contents of the entire directory are uploaded to the Docker daemon and the image is built by it. You’ve already learned that the CLI tool and the daemon aren’t necessarily on the same computer. If you’re using Docker on a non-Linux system such as macOS or Windows, the client is in your host OS, but the daemon runs inside a Linux VM. But it could also run on a remote computer.

构建本身不是由docker 命令行工具执行的。相反,整个文件夹的内容被上传到Docker daemon中,镜像也由Docker daemon构建。你已经了解到命令行工具和daemon不一定在同一台计算机上。如果你在非Linux系统(如macOS或Windows)上使用Docker,那么客户端在你的主机操作系统中,但是daemon在Linux虚拟机中运行。但daemon也可以在远程计算机上运行。

TIP
提示 Don’t add unnecessary files to the build directory, as they will slow down the build process—especially if the Docker daemon is located on a remote system.
不要向构建目录中添加不必要的文件,因为它们会减慢构建进程——尤其是当Docker daemon位于远程系统上时。

To build the image, Docker first pulls the base image (node:12) from the public image repository (Docker Hub in this case), unless the image is already stored locally. It then creates a new container from the image and executes the next directive from the Dockerfile. The container’s final state yields a new image with its own ID. The build process continues by processing the remaining directives in the Dockerfile. Each one creates a new image. The final image is then tagged with the tag you specified with the -t flag in the docker build command.

要构建镜像,Docker首先从公共镜像存储库(本例中是Docker Hub)中提取基础镜像(node:12),除非镜像已经存储在本地。然后,它根据镜像创建一个新的容器,并执行Dockerfile中的下一个指令。容器的最终状态是产生一个具有自己ID的新镜像。构建过程继续处理Dockerfile中的剩余指令。每一个指令都会创建一个新镜像。最后的镜像被标记为你在docker build命令中使用-t标记指定的标记。

Understanding the image layers  理解镜像中的层

Some pages ago, you learned that images consist of several layers. One might think that each image consists of only the layers of the base image and a single new layer on top, but that’s not the case. When building an image, a new layer is created for each individual directive in the Dockerfile.

通过前面的内容,了解到镜像由几个层组成。人们可能会认为,每个镜像只包含基础镜像的层和上面的一个新层,但事实并非如此。当构建一个镜像时,Dockerfile中的每个指令都会创建一个新的层。

During the build of the kiada image, after it pulls all the layers of the base image, Docker creates a new layer and adds the app.js file into it. It then adds another layer with the files from the html directory and finally creates the last layer, which specifies the command to run when the container is started. This last layer is then tagged as kiada:latest.

在构建kubia镜像的过程中,在它拉取基础镜像的所有层之后,Docker创建一个新层,并将app.js文件复制到其中。然后创建另一个层,将html文件夹中复制到其中,最终再创建最后一层,指定在启动容器时要执行的命令。最后一层被标记为kubia:latest。

You can see the layers of an image and their size by running docker history. The command and its output are shown next (note that the top-most layers are printed first):

通过运行docker history,可以看到镜像的层及其大小,命令和输出如下所示(注意:最顶层首先输出)。

$ docker history kiada:latest
IMAGE         CREATED     CREATED BY                            SIZE 
b0ecc49d7a1d  7 min ago   /bin/sh -c #(nop) ENTRYPOINT ["n...   0B
1d4de446f0f0  7 min ago   /bin/sh -c #(nop) COPY dir:6ecee...   534kB
28d67701d6d9  7 min ago   /bin/sh -c #(nop) COPY file:2ed5...   2.8kB
e498dabfee1c  2 days ago  /bin/sh -c #(nop) CMD ["node"]        0B
<missing>     2 days ago  /bin/sh -c #(nop) ENTRYPOINT ["d...   0B
<missing>     2 days ago  /bin/sh -c #(nop) COPY file:2387...   116B
<missing>     2 days ago  /bin/sh -c set -ex && for key in...   5.4MB
<missing>     2 days ago  /bin/sh -c #(nop)  ENV YARN_VERS...   0B
<missing>     2 days ago  /bin/sh -c ARCH= && dpkgArch="$(...   67MB
<missing>     2 days ago  /bin/sh -c #(nop)  ENV NODE_VERS...   0B
<missing>     3 weeks ago /bin/sh -c groupadd --gid 1000 n...   333kB
<missing>     3 weeks ago /bin/sh -c set -ex;  apt-get upd...   562MB
<missing>     3 weeks ago /bin/sh -c apt-get update && apt...   142MB
<missing>     3 weeks ago /bin/sh -c set -ex;  if ! comman...   7.8MB
<missing>     3 weeks ago /bin/sh -c apt-get update && apt...   23.2MB
<missing>     3 weeks ago /bin/sh -c #(nop)  CMD ["bash"]       0B
<missing>     3 weeks ago /bin/sh -c #(nop) ADD file:9788b...   101MB

Most of the layers you see come from the node:12 image (they also include layers of that image’s own base image). The three uppermost layers correspond to the COPY and ENTRYPOINT directives in the Dockerfile.

你看到的大多数层来自于node:12镜像(它们还包括基础镜像的层)。最上面的三个层对应Dockerfile中的COPY指令和ENTRYPOINT指令。

As you can see in the CREATED BY column, each layer is created by executing a command in the container. In addition to adding files with the COPY directive, you can also use other directives in the Dockerfile. For example, the RUN directive executes a command in the container during the build. In the listing above, you’ll find a layer where the apt-get update and some additional apt-get commands were executed. apt-get is part of the Ubuntu package manager used to install software packages. The command shown in the listing installs some packages onto the image’s filesystem.

正如你在CREATED BY列中看到的,每一层都是通过在容器中执行一个指令创建的。除了使用COPY指令添加文件之外,你还可以在Dockerfile中使用其他指令。例如,RUN指令用于构建期间在容器中执行一个命令。在上面的清单中,你将发现在一个层中执行 apt-get update 和一些其他的apt-get指令。apt-get是Ubuntu软件包管理器的一部分,用于安装软件包。清单中显示的指令将一些包安装到镜像的文件系统中。

To learn about RUN and other directives you can use in a Dockerfile, refer to the Dockerfile reference at https://docs.docker.com/engine/reference/builder/.

要了解RUN和其他可以在Dockerfile中使用的指令,请参阅Dockerfile的指南:https://docs.docker.com/engine/reference/builder/

TIP
提示 Each directive creates a new layer. I have already mentioned that when you delete a file, it is only marked as deleted in the new layer and is not removed from the layers below. Therefore, deleting a file with a subsequent directive won’t reduce the size of the image. If you use the RUN directive, make sure that the command it executes deletes all temporary files it creates before it terminates.
每个指令都创建一个新层。我已经提到过,当你删除一个文件时,它只在新层中被标记为已删除,而不会从下面的层中删除。因此,用后续指令删除文件不会减少镜像的大小。如果使用RUN指令,请确保它执行的命令在终止之前删除它创建的所有临时文件。

 

posted @ 2021-12-22 17:24  菜鸟吊思  阅读(75)  评论(0)    收藏  举报