目录
应用的容器化简介
容器是为应用而生!具体来说,容器能够简化应用的构建、部署和运行过程。
完整的应用容器化过程主要分为以下几个步骤:
(1)编写应用代码。
(2)创建一个 Dockerfile
,其中包括当前应用的描述、依赖以及该如何运行这个应用。
(3)对该 Dockerfile
执行 docker image build
命令。
(4)等待 Docker
将应用程序构建到 Docker
镜像中。
一旦应用容器化完成(即应用被打包为一个 Docker
镜像),就能以镜像的形式交付并以容器的方式运行了。
单体应用容器化
如何将一个简单的单节点 Node.js Web
应用容器化。如果是 Windows
操作系统的话,处理过程也是大同小异。现在通过以下几个步骤,来介绍具体的过程:
(1)获取应用代码。
(2)分析 Dockerfile
。
(3)构建应用镜像。
(4)运行该应用。
(5)测试应用。
(6)容器应用化细节。
(7)生产环境中的多阶段构建。
(8)最佳实践。
获取应用代码
执行 git clone https://github.com/nigelpoulton/psweb
从 GitHub
将代码克隆到本地。克隆操作会创建一个名为 psweb
的文件夹。可以进入该文件夹,并查看其中的内容:
[user1@bogon MyDocker]$ sudo git clone https://github.com/nigelpoulton/psweb
正克隆到 'psweb'...
remote: Enumerating objects: 13, done.
remote: Counting objects: 100% (13/13), done.
remote: Compressing objects: 100% (12/12), done.
remote: Total 42 (delta 3), reused 1 (delta 0), pack-reused 29
Unpacking objects: 100% (42/42), done.
[user1@bogon MyDocker]$ cd psweb/
[user1@bogon psweb]$ ll
总用量 20
-rw-r--r--. 1 root root 341 12月 24 15:25 app.js
-rw-r--r--. 1 root root 216 12月 24 15:25 circle.yml
-rw-r--r--. 1 root root 338 12月 24 15:25 Dockerfile
-rw-r--r--. 1 root root 403 12月 24 15:25 package.json
-rw-r--r--. 1 root root 455 12月 24 15:25 README.md
drwxr-xr-x. 2 root root 39 12月 24 15:25 test
drwxr-xr-x. 2 root root 22 12月 24 15:25 views
该目录下包含了全部的应用源码,以及包含界面和单元测试的子目录。应用的代码已就绪,接下来分析一下 Dockerfile
的具体内容。
分析 Dockerfile
在代码目录当中,有个名称为 Dockerfile
的文件。这个文件包含了对当前应用的描述,并且能指导 Docker
完成镜像的构建。在 Docker
当中,包含应用文件的目录通常被称为构建上下文(Build Context
)。通常将 Dockerfile
放到构建上下文的根目录下。
另外很重要的一点是,文件开头字母是大写 D
,这里是一个单词。像“dockerfile”
或者“Docker file”
这种写法都是不允许的。接下来了解一下 Dockerfile
文件当中都包含哪些具体内容:
[user1@bogon psweb]$ nl Dockerfile
1 # Test web-app to use with Pluralsight courses and Docker Deep Dive book
2 # Linux x64
3 FROM alpine
4 LABEL maintainer="nigelpoulton@hotmail.com"
5 # Install Node and NPM
6 RUN apk add --update nodejs nodejs-npm
7 # Copy app to /src
8 COPY . /src
9 WORKDIR /src
10 # Install dependencies
11 RUN npm install
12 EXPOSE 8080
13 ENTRYPOINT ["node", "./app.js"]
[user1@bogon psweb]$
Dockerfile
主要包括两个用途:
- 对当前应用的描述。
- 指导
Docker
完成应用的容器化(创建一个包含当前应用的镜像)。
不要因 Dockerfile
就是一个描述文件而对其有所轻视!Dockerfile
能实现开发和部署两个过程的无缝切换。同时 Dockerfile
还能帮助新手快速熟悉这个项目。Dockerfile
对当前的应用及其依赖有一个清晰准确的描述,并且非常容易阅读和理解。因此,要像重视你的代码一样重视这个文件,并且将它纳入到源控制系统当中。
下面是这个文件中的一些关键步骤概述:
以 #
号开头的行是注释
第 3 行FROM alpine
:以 alpine
镜像作为当前镜像基础
第 4 行LABEL maintainer="nigelpoulton@hotmail.com"
:指定维护者(maintainer
)为 nigelpoultion@hotmail.com
第 6 行RUN apk add --update nodejs nodejs-npm
:安装 Node.js
和 NPM
第 8 行COPY . /src
:将应用的代码复制到镜像当中
第 9 行WORKDIR /src
:设置新的工作目录
第 11 行RUN npm install
:安装依赖包
第 12 行EXPOSE 8080
:记录应用的网络端口
第 13 行ENTRYPOINT ["node", "./app.js"]
:最后将 app.js
设置为默认运行的应用
具体分析一下每一步的作用。
除注释以外,每个 Dockerfile
文件第一行都是 FROM
指令。FROM
指令指定的镜像,会作为当前镜像的一个基础镜像层,当前应用的剩余内容会作为新增镜像层添加到基础镜像层之上。本例中的应用基于 Linux
操作系统,所以在 FROM
指令当中所引用的也是一个 Linux
基础镜像;如果要容器化的应用是一个基于 Windows
操作系统的应用,就需要指定一个像 microsoft/aspnetcore-build
这样的 Windows
基础镜像了。基础镜像的结构如下图所示:
接下来,Dockerfile
中通过标签(LABLE
)方式指定了当前镜像的维护者为“nigelpoulton@hotmail. com”
。每个标签其实是一个键值对(Key-Value
),在一个镜像当中可以通过增加标签的方式来为镜像添加自定义元数据。备注维护者信息有助于为该镜像的潜在使用者提供沟通途径,这是一种值得提倡的做法。
第 6 行 RUN apk add --update nodejs nodejs-npm
指令使用 alpine
的 apk
包管理器将 nodejs
和 nodejs-npm
安装到当前镜像之中。RUN
指令会在 FROM
指定的 alpine
基础镜像之上,新建一个镜像层来存储这些安装内容。当前镜像的结构如下图所示:
第 8 行 COPY . /src
指令将应用相关文件从构建上下文复制到了当前镜像中,并且新建一个镜像层来存储。COPY
执行结束之后,当前镜像共包含 3 层,如下图所示:
下一步,Dockerfile
通过 WORKDIR
指令,为 Dockerfile
中尚未执行的指令设置工作目录。该目录与镜像相关,并且会作为元数据记录到镜像配置中,但不会创建新的镜像层。
然后,RUN npm install
指令会根据 package.json
中的配置信息,使用 npm
来安装当前应用的相关依赖包。npm
命令会在前文设置的工作目录中执行,并且在镜像中新建镜像层来保存相应的依赖文件。目前镜像一共包含 4 层,如下图所示: