buildah
Buildah是一个命令行工具,用于快速,轻松地构建兼容Open Container Initiative的映像(也意味着Docker和Kubernetes兼容)。 它可以代替Docker守护进程的docker build
命令(即,使用传统的Dockerfile生成映像),但具有足够的灵活性以允许您使用喜欢使用的任何工具来生成映像。 Buildah易于集成到脚本和构建管道中,最重要的是,它不需要运行中的容器守护程序即可构建其映像。
您可以立即开始使用Buildah,将其放到当前使用Dockerfile和docker docker build
映像的位置。 Buildah的build-using-dockerfile
或bud
参数使它的行为build-using-dockerfile
docker build
一样,因此很容易将其合并到现有脚本或构建管道中。
与我以前撰写的有关Buildah的文章一样 ,我喜欢使用从源代码安装“ GNU Hello”的示例。 考虑以下Dockerfile:
FROM fedora:28
LABEL maintainer Chris Collins <collins.christopher@gmail.com>
RUN dnf install -y tar gzip gcc make \
&& dnf clean all
ADD http://ftpmirror.gnu.org/hello/hello-2.10.tar.gz /tmp/hello-2.10.tar.gz
RUN tar xvzf /tmp/hello-2.10.tar.gz -C /opt
WORKDIR /opt/hello-2.10
RUN ./configure
RUN make
RUN make install
RUN hello -v
ENTRYPOINT "/usr/local/bin/hello"
Buildah可以像buildah bud -t hello .
一样轻松地从该Dockerfile创建映像buildah bud -t hello .
,替换docker build -t hello .
:
[chris@krang] $ sudo buildah bud -t hello .
STEP 1: FROM fedora:28
Getting image source signatures
Copying blob sha256:e06fd16225608e5b92ebe226185edb7422c3f581755deadf1312c6b14041fe73
81.48 MiB / 81.48 MiB [====================================================] 8s
Copying config sha256:30190780b56e33521971b0213810005a69051d720b73154c6e473c1a07ebd609
2.29 KiB / 2.29 KiB [======================================================] 0s
Writing manifest to image destination
Storing signatures
STEP 2: LABEL maintainer Chris Collins <collins.christopher@gmail.com>
STEP 3: RUN dnf install -y tar gzip gcc make && dnf clean all
<snip>
构建完成后,您可以使用buildah images
命令查看新图像:
[chris@krang] $ sudo buildah images
IMAGE ID IMAGE NAME CREATED AT SIZE
30190780b56e docker.io/library/fedora:28 Mar 7, 2018 16:53 247 MB
6d54bef73e63 docker.io/library/hello:latest May 3, 2018 15:24 391.8 MB
标记为hello:latest
的新映像可以推送到远程映像注册表,或者使用CRI-O或其他Kubernetes CRI兼容的运行时运行,也可以推送到远程注册表。 如果要测试它作为Docker构建的替代品,则可能需要将映像复制到Docker守护程序的本地映像存储中,以便它可以由Docker运行。 这可以通过buildah push
命令轻松完成:
[chris@krang] $ sudo buildah push hello:latest docker-daemon:hello:latest
Getting image source signatures
Copying blob sha256:72fcdba8cff9f105a61370d930d7f184702eeea634ac986da0105d8422a17028
247.02 MiB / 247.02 MiB [==================================================] 2s
Copying blob sha256:e567905cf805891b514af250400cc75db3cb47d61219750e0db047c5308bd916
144.75 MiB / 144.75 MiB [==================================================] 1s
Copying config sha256:6d54bef73e638f2e2dd8b7bf1c4dfa26e7ed1188f1113ee787893e23151ff3ff
1.59 KiB / 1.59 KiB [======================================================] 0s
Writing manifest to image destination
Storing signatures
[chris@krang] $ sudo docker images | head -n2
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/hello latest 6d54bef73e63 2 minutes ago 398 MB
[chris@krang] $ sudo docker run -t hello:latest
Hello, world!
与Docker构建不同,Buildah不会针对Dockerfile中的每条指令自动将更改提交到层,而是每次都从上到下构建所有内容。 从积极的方面来说,这意味着非缓存的构建(例如,您将使用自动化或构建管道进行的构建)最终会比其Docker构建对等的构建更快,尤其是在有大量指令的情况下。 从自动化部署或连续交付的角度来看,这对于快速将新更改投入生产非常有用。
但是,实际上,缺少缓存对于图像开发可能不是那么有用,因为当进行一遍又一遍的构建时,缓存层可以节省大量时间。 但是,这仅适用于build-using-dockerfile
命令。 当使用Buildah本机命令时,如下所示,您可以选择何时将更改提交到磁盘,从而实现更灵活的开发。
Buildah 真正令人瞩目的地方在于其本机命令,您可以使用它与容器构建进行交互。 Buildah的命令不是与每个构建都使用build-using-dockerfile/bud
,而是与构建过程中创建的临时容器进行实际交互的命令。 (Docker也使用临时或中间容器,但是在构建映像时,您实际上并没有与它们进行交互。)
再次使用“ GNU Hello”示例,考虑使用Buildah命令构建此映像:
#!/usr/bin/env bash
set
-o errexit
# Create a container
container =$
( buildah from fedora:
28
)
# Labels are part of the "buildah config" command
buildah config
--label
maintainer =
"Chris Collins <collins.christopher@gmail.com>"
$container
# Grab the source code outside of the container
curl
-sSL http:
// ftpmirror.gnu.org
/ hello
/ hello-
2.10 .tar.gz
-o hello-
2.10 .tar.gz
buildah copy
$container hello-
2.10 .tar.gz
/ tmp
/ hello-
2.10 .tar.gz
buildah run
$container dnf
install
-y
tar
gzip
gcc
make
Buildah run
$container dnf clean all
buildah run
$container
tar xvzf
/ tmp
/ hello-
2.10 .tar.gz
-C
/ opt
# Workingdir is also a "buildah config" command
buildah config
--workingdir
/ opt
/ hello-
2.10
$container
buildah run
$container .
/ configure
buildah run
$container
make
buildah run
$container
make
install
buildah run
$container hello
-v
# Entrypoint, too, is a “buildah config” command
buildah config
--entrypoint
/ usr
/ local
/ bin
/ hello
$container
# Finally saves the running container to an image
buildah commit
--format docker
$container hello:latest
应该立即显而易见的一件事是,这是一个Bash脚本而不是一个Dockerfile。 使用Buildah的本机命令可以轻松编写脚本,无论您使用哪种语言或自动化上下文。 这可以是一个makefile,一个Python脚本或您想要使用的任何工具。
那么这是怎么回事? 第一个Buildah命令container=$(buildah from fedora:28)
,从fedora:28映像中创建一个正在运行的容器,并将容器名称(命令的输出)存储为变量,以备后用。 其余所有Buildah命令都使用$container
变量来说明要对哪个容器进行操作。 这些命令在大多数情况下是不言自明的: buildah copy
将文件移入容器, buildah run
在容器中执行命令。 将它们与它们的Dockerfile等效项进行匹配很容易。
最后buildah commit
命令buildah commit
,将容器提交到磁盘上的映像。 在使用Buildah命令而不是从Dockerfile构建映像时,可以使用commit
命令来决定何时保存更改。 在上面的示例中,所有更改都被一次提交,但也可以包括中间提交,从而使您可以选择从中开始的缓存点。 (例如,在dnf install
之后将其缓存到磁盘将特别有用,因为这可能需要很长时间,但每次可靠地相同。)
另一个有用的Buildah命令为构建映像提供了很大的灵活性。 buildah mount
将容器的根目录安装到主机上的安装点。 例如:
[ chris
@ krang
] $
container =$
(
sudo buildah from fedora:
28
)
[ chris
@ krang
] $
mountpoint =$
(
sudo buildah
mount
${container}
)
[ chris
@ krang
] $
echo
$mountpoint
/ var
/ lib
/ containers
/ storage
/ overlay2
/ 463eda71ec74713d8cebbe41ee07da5f6df41c636f65139a7bd17b24a0e845e3
/ merged
[ chris
@ krang
] $
cat
${mountpoint}
/ etc
/ redhat-release
Fedora release
28
( Twenty Eight
)
[ chris
@ krang
] $
ls
${mountpoint}
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,并制作软件包以在容器内编译“ GNU Hello”。 使用安装点,我们可以使用相同的软件构建映像,但是下载的tarball和tar,Gzip等RPM都在主机上,而不是在容器和生成的映像中:
#!/usr/bin/env bash
set
-o errexit
# Create a container
container =$
( buildah from fedora:
28
)
mountpoint =$
( buildah
mount
$container
)
buildah config
--label
maintainer =
"Chris Collins <collins.christopher@gmail.com>"
$container
curl
-sSL http:
// ftpmirror.gnu.org
/ hello
/ hello-
2.10 .tar.gz \
-o
/ tmp
/ hello-
2.10 .tar.gz
tar xvzf src
/ hello-
2.10 .tar.gz
-C
${mountpoint}
/ opt
pushd
${mountpoint}
/ opt
/ hello-
2.10
.
/ configure
make
make
install
DESTDIR =
${mountpoint}
popd
chroot
$mountpoint
bash
-c
"/usr/local/bin/hello -v"
buildah config
--entrypoint
"/usr/local/bin/hello"
$container
buildah commit
--format docker
$container hello
buildah unmount
$container
注意上面脚本中的几件事:
curl
命令将压缩文件下载到主机,而不是映像
tar
命令(从主机本身运行)将tarball的源代码提取到容器内的/opt
中。
Configure
, make
和make install
都从安装点内部的目录运行,安装到主机上,而不是在容器本身内部运行。
此处的chroot
命令用于将root本身更改为安装点,并测试“ hello”是否正常工作,类似于先前示例中使用的buildah run
命令。
该脚本更短,使用了大多数Linux人士已经熟悉的工具,并且生成的映像更小(没有压缩包,没有额外的软件包等)。 您甚至可以使用主机系统的软件包管理器将软件安装到容器中。 例如,假设您想通过GNU Hello将NGINX安装到容器中(无论出于何种原因):
[chris@krang] $ mountpoint=$(sudo buildah mount ${container})
[chris@krang] $ sudo dnf install nginx --installroot $mountpoint
[chris@krang] $ sudo chroot $mountpoint nginx -v
nginx version: nginx/1.12.1
在上面的示例中,DNF与--installroot
标志一起用于将NGINX安装到容器中,可以使用chroot进行验证。
Buildah是创建容器映像的轻量级且灵活的方法,而无需在主机上运行完整的Docker守护程序。 除了提供从Dockerfiles进行构建的开箱即用支持外,Buildah还易于与脚本或您选择的构建工具一起使用,并且可以帮助您使用构建主机上的现有工具来构建容器映像。 结果是更精简的图像,这些图像使用较少的带宽来传送,需要较少的存储空间,并且对于潜在的攻击者而言具有较小的表面积。 试试看!
[请参阅我们的相关故事, 使用Buildah创建小容器 ]
翻译自: https://opensource.com/article/18/6/getting-started-buildah
buildah