如何使用Buildah构建OCI和Docker容器镜像

时间:2020-02-23 14:31:31  来源:igfitidea点击:

在我们开始使用Buildah构建图像之前,我认为有必要进行一些清理工作,因为在大多数文章的开头几段中,容器化领域可能会成为术语的迷宫。
首先,让我们了解OCI,Buildah和Docker的全部含义。

开放式容器倡议(OCI)

嗯,由OCI官方站点引用,由Docker,CoreOS和其他合作伙伴于2014年6月22日发起的开放容器计划(OCI)是一个轻量级项目,其明确目的是围绕容器格式和运行时创建开放行业标准。

OCI当前包含两个规范:运行时规范(runtime-spec)和镜像规范(image-spec)。
运行时规范概述了如何运行在磁盘上解压缩的"文件系统包"。
"文件系统包"是一组以某种方式组织的文件,并包含所有符合条件的运行时(例如Docker和CRI-O)必需的所有数据和元数据,以对其执行所有标准操作。

在较高级别上,OCI实施将下载OCI镜像,然后将该镜像解压缩到OCI运行时文件系统捆绑包中。
此时,OCI运行时捆绑包将由OCI运行时(例如Docker和CRI-O)运行。
现在移至Buildah。

Buildah

Buildah是一个命令行工具,可用于构建符合打开容器计划(OCI)的图像。
它可以与Docker,Podman,Kubernetes或者任何我们喜欢的容器工具一起使用.Buildah的命令与我们可以在dockerfile中找到的所有命令类似。
Buildah的目标也是提供一个较低级Coreutils界面来构建容器图像,允许人们在不需要Dockerfile的情况下构建容器。
最强大的使用方法是编写Bash脚本,以创建图像 - 以类似的方式,我们将在不需要守护程序的情况下编写Dockerfile。

我们可以通过Buildah命令实现以下几点,更重要

从DockerFile(使用Buildah Bud)构建一个容器图像.Build从另一个基础图像(来自墓地)或者从划痕(使用刮擦)检查容器或者图像(使用Buildah检查)安装容器:安装a容器的根文件系统添加或者更改内容(Buildah Mount)。
创建一个新的容器层(使用buildah提交).unmount一个容器:卸载挂载的容器(buildah umount).delete容器(使用buildah rm)或者图像(在普通的英语中使用Buildah RMI),OCI列出了构建图像的规则以及如何消耗IT Whild Buildah将其设置并用于构建容器图像的规则。
现在码头是什么?

Docker.

很难保持简要介绍,但阅读概念肯定会帮助码头1.11 of Docker,实现是一款单片守护进程。
Monolith Dit As作为一个包,例如下载容器图像,启动容器进程,开启远程API,并充当日志收集守护程序,所有内容都在作为root(源核心)运行的集中进程中。
这种集中式架构在部署时具有一些好处,但却无法解决其他基本问题。
一个例子是它不遵循UNIX进程和特权分离的最佳实践。
此外,整体实施使Docker难以与Linux Init系统进行适当集成,例如Upstart和Systemd https://coreos.com/rkt/docs/latest/rkt-vs-ot-projects.html#rkt-vs-docker。
这导致Docker分成了不同的部件,可以在推出Docker 1.11之后在下面的开头段落中所示。
"我们很高兴推出Docker引擎1.11,我们的第一个在RunC™和ContainTD™内置的版本。
通过此版本,Docker是第一个根据OCI技术运行运行时的运行时,展示团队自2014年6月在Linux基金会下捐赠行业标准的集装箱格式和运行时的进展。
源码码头".According对他们来说(Docker),将Docker拆卸到聚焦的独立工具意味着更具专注的维护者,最终更好的质量软件.Since然后Containtn现在处理以前由Docker守护程序本身完成的容器的执行。
这是精确的流量,用户从Docker-CLI运行命令。
Docker-CLI与Docker守护程序交谈。
Docker守护程序(Dockerd)侦听请求,并通过IT与其接触的Contains管理容器的生命周期。
ContainerD获取请求并通过RUNC启动容器,并在主机内完成所有容器寿命。
RONC简单的是根据OCI规范的用于产卵和运行容器的CLI工具。

安装buildah.

在CentOS 8盒上运行下面的命令以安装Buildah。
我们将在它旁边安装Podman,以便我们可以使用它来从头开始运行我们的图像。

sudo dnf update
sudo dnf -y install buildah podman

检查它是否已成功安装

$rpm -q buildah
buildah-1.11.6-4.module_el8.1.0+272+3e64ee36.x86_64

使用Buildah从头开始创建OCI镜像

其中我们将构建一个仅包含少量容器元数据的镜像,然后添加运行简单的Apache Web服务器所需的所有内容。
这样做可以使我们逐块构建容器镜像。
正如前面所解释的,我们使用buildah scratch命令来实现此目的。
为了避免出现问题,我们将使用" root"用户帐户从此处开始。

brandnewcontainer=$(buildah from scratch)
$buildah containers
CONTAINER ID  BUILDER  IMAGE ID     IMAGE NAME                       CONTAINER NAME   
e6c2f7b0b567     *                  scratch                          working-container
-- You can also use podamn
$ podman images

上面的命令创建一个空容器(无图像)。
如下安装空容器:

scratchmnt=$(buildah mount $brandnewcontainer)
echo $scratchmnt
/var/lib/containers/storage/overlay/40e7215211b47e8de47991d0dc7be07e0b1b4f48eda25ebaf6ff8ff46c466be5/merged

通过Buildah mount命令,我们可以挂载容器的根文件系统,从而可以从主机对其进行访问。
接下来,将软件包安装到暂存镜像中。

yum -y group install "Minimal Install" --releasever=8 --installroot=$scratchmnt

安装软件包之后。
现在,我们可以卸载镜像并将其作为独立的容器运行,因为它具有需要独立的所有内容。

$buildah umount $brandnewcontainer
e6c2f7b0b5679133ad6e0ad6bd74164dac7f357f0076cf6cc819f9ed664236d5

要将图像作为连续图像运行,请在下面提供以下命令,我们应该能够直接进入从头创建的新容器的怀抱中。
我们可以其中安装其他应用程序。

$buildah run $brandnewcontainer bash
[Hyman@theitroad /]# ls 
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr

从上面可以看到,所有目录在标准容器中都可以使用。
我们可以安装Apache来测试一切是否正常。

[Hyman@theitroad /]# yum install httpd -y

在默认的Apache文档根目录中添加一个简单的html页面,然后从容器中退出

[Hyman@theitroad /]# echo "Testing Apache." > /var/www/html/index.html
[Hyman@theitroad /]# exit

回到我们的主机系统,而不是将httpd作为初始化服务运行,而是设置一些buildah config选项来直接从容器中运行httpd守护程序:

$buildah config --cmd "/usr/sbin/httpd -DFOREGROUND" working-container
$buildah config --port 80/tcp working-container
$buildah commit working-container localhost/firstapache:latest
Getting image source signatures
Copying blob b34ab2705c68 done
Copying config a0c546bc39 done
Writing manifest to image destination
Storing signatures
a0c546bc39271565946d11a843979e017aae73e2b792cc5d9ca589661f427543

在buildah提交完镜像之后,现在让我们挥舞Podman来按以下方式运行它:首先,检查系统中所有可用的镜像并获取我们感兴趣的镜像的ID。

$podman images
REPOSITORY              TAG      IMAGE ID       CREATED         SIZE   
localhost/firstapache   latest   a0c546bc3927   8 minutes ago   1.68 GB

现在运行图像

$podman run -p 8080:80 -d --name apache-server a0c546bc3927
b1d29603542c8f91a289127cee4fa9157962f8fcdda9baa82b335e08a94c0992

为了确保我们的Apache网络服务器正在提供我们之前添加的页面,我们必须做一些事情。
我们猜对了,我们可以卷曲甚至可以使用浏览器查看结果。
请记住,容器中的端口80已绑定到系统上的端口8080。
我们可以使用curl进行如下所示的测试。

curl -ik "localhost:8080"
HTTP/1.1 200 OK
Date: Thu, 23 Apr 2017 22:21:54 GMT
Server: Apache/2.4.37 (centos)
Last-Modified: Thu, 23 Apr 2017 22:02:43 GMT
ETag: "f-5a3fc6872e6c0"
Accept-Ranges: bytes
Content-Length: 15
Content-Type: text/html; charset=UTF-8      
Testing Apache.

我们可以清楚地看到,Web服务器正在侦听并返回了我们期望的响应。
它正在运行。
Buildah附带了许多可供我们使用的工具。
我们可以删除图像和容器,还可以检查图像和容器。
以检查为例,使用" buildah images"命令列出所有图像以获取其ID,然后获取要检查的图像的ID,然后运行:

$buildah inspect a0c546bc3927
{
    "Type": "buildah 0.0.1",
    "FromImage": "localhost/firstapache:latest",
    "FromImageID": "a0c546bc39271565946d11a843979e017aae73e2b792cc5d9ca589661f427543",
    "FromImageDigest": "sha256:2060eb441d905934f0aa1749b0d9ed065fd464b30483a963e5719b27836c844d",
    "Config": "{\"created\":\"2017-04-23T22:09:50.515019063Z\",\"architecture\":\"amd64\",\"os\":\"linux\",\"config\":{\"ExposedPorts\":{\"80/tcp\":{}},\"Cmd\":[\"/usr/sbin/httpd\",\"-DFOREGROUND\"],\"Labels\":{\"io.buildah.version\":\"1.11.6\"}},\"rootfs\":{\"type\":\"layers\",\"diff_ids\":[\"sha256:b34ab2705c68989b396dfc33dd5174f34b14890242aae93397d628787d2a6a94\"]},\"history\":[{\"created\":\"2017-04-23T22:09:50.515019063Z\",\"created_by\":\"/bin/sh\"}]}",
    "Manifest": "{\"schemaVersion\":2,\"config\":{\"mediaType\":\"application/vnd.oci.image.config.v1+json\",\"digest\":\"sha256:a0c546bc39271565946d11a843979e017aae73e2b792cc5d9ca589661f427543\",\"size\":396},\"layers\":[{\"mediaType\":\"application/vnd.oci.image.layer.v1.tar\",\"digest\":\"sha256:b34ab2705c68989b396dfc33dd5174f34b14890242aae93397d628787d2a6a94\",\"size\":1684295168}]}",  
    "Container": "",
    "ContainerID": "",
    "MountPoint": "",
    "ProcessLabel": "",
    "MountLabel": "",
    "ImageAnnotations": null,
    "ImageCreatedBy": "",
    "OCIv1": {
        "created": "2017-04-23T22:09:50.515019063Z",
        "architecture": "amd64",
        "os": "linux",
        "config": {
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Cmd": [
                "/usr/sbin/httpd",
                "-DFOREGROUND"
            ],
            "Labels": {
                "io.buildah.version": "1.11.6"
            }
        },
        "rootfs": {
            "type": "layers",
            "diff_ids": [
                "sha256:b34ab2705c68989b396dfc33dd5174f34b14890242aae93397d628787d2a6a94"
            ]
        },
        "history": [
            {
                "created": "2017-04-23T22:09:50.515019063Z",
                "created_by": "/bin/sh"
            }
        ]
    },
    "Docker": {
        "created": "2017-04-23T22:09:50.515019063Z",
        "container_config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "80/tcp": {}
            },