6、Containerizing an app

containerizing,有时也叫Dockerizing,is the process of taking an application and configuring it to run as a container.java

容器一般是关于apps,特别是,它们使得app的构建、传送(将image推送到Docker仓库)、运行变的简单。node

将应用程序装箱的过程以下:git

一、编写应用程序代码;github

二、建立Dockerfile描述app、它的依赖以及如何运行它;web

三、将Dockerfile输入到docker image 构建命令;docker

四、Docker将应用程序构建成Docker image。npm

上述过程的图示以下:浏览器

 

接下来,将以一个简单的单容器 Node.js web app为例来进行装箱,主要包含以下步骤:缓存

• 获取app代码
• 检查Dockerfile
• 装箱app
• 运行app
• 测试app
• 使用多阶段构建转移到生产环境
• 一些最佳实践网络

注:使用网上环境,地址:https://labs.play-with-docker.com/

一、获取app代码

从GitHubs上将https://github.com/nigelpoulton/psweb.git克隆到本地,psweb目录下包含了全部的应用程序源代码。以下图所示:

二、检查Dockerfile

psweb目录下有一个文件叫Dockerfile,这个文件描述了应用程序,并告诉Docker如何把应用程序构建进镜像。

包含应用程序的目录被称之为构建上下文,将Dockerfile放在构建上下文的根目录是一个通用实践。

注意 Dockerfile以大写字母D开始,是一个单词,dockerfile和Docker file都是无效的。

Dockerfile的主要目的有两个:描述应用程序和告诉Docker如何将应用程序装箱(建立一个包含应用程序的镜像)。此外,还能够弥合开发和运营之间的鸿沟!

上述Dockerfile文件里的内容可解释为:以alpine镜像开始,增长nigelpoulton@hotmail.com做为维护者(设置元数据,不会产生新的层),安装Node.js和NPM,拷贝应用程序代码,设置工做目录(设置元数据,不会产生新的层),安装依赖,记录app网络端口(设置元数据,不会产生新的层),设置app.js做为运行的缺省应用程序。以下图所示:

全部的Dockerfile都是以 FROM开始,这个是镜像的基础层,其余的做为附加层。

三、装箱app

Dockerfile编写完成后,就能够开始构建镜像。  构建完成后,用docker image ls查看构建的镜像,应用程序已被装箱。

能够将镜像推送到Docker Hub仓库。前提是你必须得有一个Docker Hub帐号.

在推送镜像到仓库前,必须以特定的方式来对镜像进行打标签。当推送镜像时,Docker须要下列全部信息:Registry、 Repository、Tag

通常状况下,不须要指定Registry(默认docker.io)和Tag(默认latest),然而,Docker对于Repository也不须要一个缺省值,它从推送的镜像中获取“REPOSITORY”值。

对于上述构建的镜像,docker image push将尝试和 推送镜像到docker.io/web:latest,但因为没有访问web仓库的权限,全部的镜像都存在于二级命名空间,所以须要从新打标签,命令为 docker image tag <current-tag> <new-tag> ,这将会额外增长一个标签,并不会覆盖原始的。

四、运行app

输入命令:docker container run -d --name c1 -p 80:8080 web:latest,来运行app,以下图所示:

五、测试app

在浏览器输入地址,出现以下界面,则app启动成功,正在运行。

六、使用多阶段构建转移到生产环境

对于Docker镜像来讲,大是糟糕的。大意味着更多潜在的脆弱性和可能更大的攻击面。

Docker镜像应该小,它的目的是传送仅包含所需原料的生产镜像在生产环境运行app。
编写Dockerfile的方式会影响镜像的大小,由于每个RUN指令都会在镜像里增长一层。所以最佳实践是在每个RUN指令里包含多个命令。

另外一个问题是,咱们不会清除咱们本身。针对镜像,咱们会运行一些命令在拉取build-time工具,当咱们传送镜像到生产环境时,这些工具遗留在镜像里,这不是理想的。

对于上述问题,大多数状况下使用 builder pattern,但大多数都须要行为准则而且增长了复杂度。

builder pattern要求至少两个Dockerfile:一个生产环境,一个开发环境。在开发环境中,编写Dockerfile.dev,能够从一个大的基础镜像开始拉取任何须要的构建工具,而后构建app。而后从Dockerfile.dev构建镜像,建立容器并运行它。在生产环境中,编写Dockerfile.prod,从一个较小的基础镜像构建新镜像,仅拷贝应用程序。全部的任何事都须要使用脚原本进行粘合。

这个方法是可行的,可是以复杂度为代价的。

多阶段构建能够解决上述问题。

多阶段构建是关于在不增长复杂性的状况下优化构建的。

在多阶段构建中,咱们须要一个单一的Dockerfile,包含多个FROM指令。每个FROM指令是一个新的构建阶段 ,能够轻松复制前述阶段的产物。

Dockerfile文件内容以下:

从上述Dockerfile看,有3个FROM指令,每个FROM指令构成一个独特的构建阶段,好比 阶段 0 叫storefront,阶段 1 叫appserver,阶段 2叫production。

storefront阶段:拉取node:latest镜像,设置工做目录,拷贝APP代码,使用两个RUN指令执行npm,此镜像有3个层,且size大。由于包含了大量的构建东西而非代码。

appserver阶段:拉取maven:latest镜像,经过两个COPY和两个RUN指令增长了4个层,这产生了很是多的构建工具和不多的实际生产 代码。

production阶段:拉取java:8-jdk-alpine镜像,此比node和maven镜像小不少。它增长了用户,设置工做目录,从storefront阶段产生的镜像里拷贝一些app代码。此外,设置了一个不一样的工做目录,从appserver阶段产生的镜像里拷贝一些应用程序代码,最后,给镜像设置了当它做为容器启动时的主运行程序。

对上述的Dockerfile进行构建,在上图中输入:"docker image build -t multi:stage .",完成后,输入 docker image ls查看,以下:

其中node:latest是由storefront阶段拉取的,maven:latest是由appserver阶段拉取的,两个<none>:<none>镜像分别由storefront阶段和appserver阶段产生的(分别增长Dockerfile里描述的层所组成)。java:8-jdk-alpine是multi:stage阶段拉取的,multi:stage是由最后的构建阶段所产生的镜像,从上述看,此两个镜像比storefront阶段和appserver阶段产生的镜像大小小不少。
七、 一些最佳实践

  • 利用构建缓存(Leverage the build cache)
  • 压缩镜像(Squash the image,Docker遵循一个正常的过程来构建镜像,最后增长了一个步骤将全部的东西压缩成单一层)

  • 使用no-install-recommends(Use no-install-recommends)【使用apt包管理器时,须要在apt-get install命令后使用no-install-recommends标志,这使得apt仅安装主要依赖,其余的不安装】
  • 在Windows下,不要从MSI包进行安装(Do not install from MSI packages (Windows))

 

• docker image build :读取Dockerfile文件,将应用程序装箱,-t 标签标记镜像,能够声明Dockerfile文件中的名称和位置。• FROM 指令:为新镜像声明base镜像。  • RUN指令:容许在运行镜像中的指令,其建立了一个新层。每个RUN指令建立一个单一新层。 • COPY指令:向镜像中添加文件,并做为一个新层。一般向镜像中拷贝应用程序。 • EXPOSE指令:记录应用程序使用的网络端口。 • ENTRYPOINT指令:当镜像做为容器启动时,将默认应用程序设置为运行。 • 其余的Dockerfile指令包括LABEL, ENV, ONBUILD, HEALTHCHECK, CMD灯。

相关文章
相关标签/搜索