译者: Andy Song

提供一种灵活、可脚本编程的方式,来使用你熟悉的工具创建精简、高效的容器镜像。

是一个命令行工具,可以方便、快捷的构建与 开放容器标准 (Open )(OCI)兼容的容器镜像,这意味着其构建的镜像与 和 兼容。该工具可作为 守护进程 build 命令(即使用传统的 构建镜像)的一种 简单(drop-in)替换,而且更加灵活,允许构建镜像时使用你擅长的工具。 可以轻松与脚本集成并生成 流水线(),最好之处在于构建镜像不再需要运行容器守护进程(LCTT 译注:这里主要是指 守护进程)。

build 的简单替换

目前你可能使用 和 build 命令构建镜像,那么你可以马上使用 进行替代。 的 build-using- (或 bud)子命令与 build 基本等价,因此可以轻松的与已有脚本结合或构建流水线。

类似我的上一篇关于 的 文章 ,我也将以使用源码安装 “GNU Hello” 为例进行说明,对应的 文件如下:

FROM :28

LABEL Chris

RUN dnf -y tar gzip gcc make

&& dnf clean all

ADD /tmp/hello-2.10.tar.gz

RUN tar xvzf /tmp/hello-2.10.tar.gz -C /opt

/opt/hello-2.10

RUN ./

RUN make

RUN make

RUN hello -v

“/usr/local/bin/hello”

使用 从 构建镜像也很简单,使用 bud -t hello . 替换 build -t hello . 即可:

[chris@krang] $ sudo bud -t hello .

STEP 1: FROM :28

image

blob :fe73

81.48 MiB / 81.48 MiB [====================================================] 8s

:d609

2.29 KiB / 2.29 KiB [======================================================] 0s

to image

STEP 2: LABEL Chris

STEP 3: RUN dnf -y tar gzip gcc make && dnf clean all

镜像构建完毕后,可以使用 命令查看这个新镜像:

[chris@krang] $ sudo

IMAGE ID IMAGE NAME AT SIZE

.io//:28 Mar 7, 2018 16:53 247 MB

.io//hello: May 3, 2018 15:24 391.8 MB

新镜像的标签为 hello:,我们可以将其推送至远程镜像仓库,可以使用 CRI-O 或其它 CRI 兼容的运行时来运行该镜像,也可以推送到远程仓库。如果你要测试对 build 命令的替代性,你可以将镜像拷贝至 守护进程的本地镜像存储中,这样 也可以使用该镜像。使用 push 可以很容易的完成推送操作:

[chris@krang] $ sudo push hello: -:hello:

image

blob :7028

247.02 MiB / 247.02 MiB [==================================================] 2s

blob :d916

144.75 MiB / 144.75 MiB [==================================================] 1s

:f3ff

1.59 KiB / 1.59 KiB [======================================================] 0s

to image

[chris@krang] $ sudo | head -n2

TAG IMAGE ID SIZE

.io/hello 2 ago 398 MB

[chris@krang] $ sudo run -t hello:

Hello, world!

若干差异

与 build 不同, 不会自动的将 中的每条指令产生的变更提到新的 分层(layer)中,只是简单的每次从头到尾执行构建。类似于 自动化()和 流水线构建(build ),这种 无缓存构建(non-)方式的好处是可以提高构建速度,在指令较多时尤为明显。从 自动部署( )或 持续交付( )的视角来看,使用这种方式可以快速的将新变更落实到生产环境中。

但从实际角度出发,缓存机制的缺乏对镜像开发不利,毕竟缓存层可以避免一遍遍的执行构建,从而显著的节省时间。自动分层只在 build-using- 命令中生效。但我们在下面会看到, 原生命令允许我们选择将变更提交到硬盘的时间,提高了开发的灵活性。

原生命令

真正 有趣之处在于它的原生命令,你可以在容器构建过程中使用这些命令进行交互。相比与使用 build-using-/bud 命令执行每次构建, 提供命令让你可以与构建过程中的临时容器进行交互。( 也使用临时或 中间 ()容器,但你无法在镜像构建过程中与其交互。)

还是使用 “GNU Hello” 为例,考虑使用如下 命令构建的镜像:

#!/usr/bin/env bash

set -o

# a

=$( from :28)

# are part of the ” ”

–label =”Chris ” $

# Grab the code of the

curl -sSL -o hello-2.10.tar.gz

copy $ hello-2.10.tar.gz /tmp/hello-2.10.tar.gz

run $ dnf -y tar gzip gcc make

run $ dnf clean all

run $ tar xvzf /tmp/hello-2.10.tar.gz -C /opt

# is also a ” ”

— /opt/hello-2.10 $

run $ ./

run $ make

run $ make

run $ hello -v

# , too, is a “ ”

— /usr/local/bin/hello $

# saves the to an image

— $ hello:

我们可以一眼看出这是一个 Bash 脚本而不是 。基于 的原生命令,可以轻易的使用任何脚本语言或你擅长的自动化工具编写脚本。形式可以是 、 脚本或其它你擅长的类型。

这个脚本做了哪些工作呢?首先, 命令 =$( from :28) 基于 :28 镜像创建了一个正在运行的容器,将容器名( from 命令的返回值)保存到变量中,便于后续使用。后续所有命令都是有 $ 变量指明需要操作的容器。这些命令的功能大多可以从名称看出: copy 将文件拷贝至容器, run 会在容器中执行命令。可以很容易的将上述命令与 中的指令对应起来。

最后一条命令 将容器提交到硬盘上的镜像中。当不使用 而是使用 命令构建镜像时,你可以使用 命令决定何时保存变更。在上例中,所有的变更是一起提交的;但也可以增加中间提交,让你可以选择作为起点的 缓存点(cache point)。(例如,执行完 dnf 命令后将变更缓存到硬盘是特别有意义的,一方面因为该操作耗时较长,另一方面每次执行的结果也确实相同。)

挂载点,安装目录以及

另一个可以大大增加构建镜像灵活性的 命令是 mount,可以将容器的根目录挂载到你主机的一个挂载点上。例如:

[chris@krang] $ =$(sudo from :28)

[chris@krang] $ =$(sudo mount ${})

[chris@krang] $ echo $

/var/lib////45e3/

[chris@krang] $ cat ${}/etc/-

28 ( Eight)

[chris@krang] $ ls ${}

bin dev home lib64 media opt root sbin sys usr

boot etc lib lost+found mnt proc run srv tmp var

这太棒了,你可以通过与挂载点交互对容器镜像进行修改。这允许你使用主机上的工具进行构建和安装软件,不用将这些构建工具打包到容器镜像本身中。例如,在我们上面的 Bash 脚本中,我们需要安装 tar、Gzip、GCC 和 make,在容器内编译 “GNU Hello”。如果使用挂载点,我仍使用同样的工具进行构建,但下载的压缩包和 tar、Gzip 等 RPM 包都在主机而不是容器和生成的镜像内:

#!/usr/bin/env bash

set -o

# a

=$( from :28)

=$( mount $)

–label =”Chris ” $

curl -sSL

-o /tmp/hello-2.10.tar.gz

tar xvzf src/hello-2.10.tar.gz -C ${}/opt

pushd ${}/opt/hello-2.10

./

make

make =${}

popd

$ bash -c “/usr/local/bin/hello -v”

— “/usr/local/bin/hello” $

— $ hello

$

在上述脚本中,需要提到如下几点:

curl 命令将压缩包下载到主机中,而不是镜像中;(主机中的) tar 命令将压缩包中的源代码解压到容器的 /opt 目录;,make 和 make 命令都在主机的挂载点目录中执行,而不是在容器内;这里的 命令用于将挂载点本身当作根路径并测试 “hello” 是否正常工作;类似于前面例子中用到的 run 命令。

这个脚本更加短小,使用大多数 Linux 爱好者都很熟悉的工具,最后生成的镜像也更小(没有 tar 包,没有额外的软件包等)。你甚至可以使用主机系统上的包管理器为容器安装软件。例如,(出于某种原因)你希望安装 GNU Hello 的同时在容器中安装 NGINX :

[chris@krang] $ =$(sudo mount ${})

[chris@krang] $ sudo dnf nginx — $

[chris@krang] $ sudo $ nginx -v

nginx : nginx/1.12.1

在上面的例子中,DNF 使用 — 参数将 NGINX 安装到容器中,可以通过 进行校验。

快来试试吧!

是一种轻量级、灵活的容器镜像构建方法,不需要在主机上运行完整的 守护进程。除了提供基于 构建容器的开箱即用支持, 还可以很容易的与脚本或你喜欢的构建工具相结合,特别是可以使用主机上已有的工具构建容器镜像。 生成的容器体积更小,更便于网络传输,占用更小的存储空间,而且潜在的受攻击面更小。快来试试吧!

[阅读相关的故事, 使用 创建小体积的容器 ]

via:

作者: Chris 选题: 译者: 校对: wxy

本文由 LCTT 原创编译, Linux中国 荣誉推出

———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666

声明:1、本内容转载于网络,版权归原作者所有!2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!