buildah 云原生时代的镜像打包利器

时间:2023-02-15 21:03:10

buildah 简介:

buildah 是一个命令行工具,可用于

  • 构建镜像
  • 通过 Dockerfile 构建镜像
  • 构建的 OCI 镜像格式,支持 docker 和其他镜像运行时使用
  • 可以将 work-container 的根文件系统挂载到宿主机
  • 可以卸载 work-container 的根文件系统
  • 无需新增额外的镜像层

官网地址:​​​​https://github.com/containers/buildah​​​


重要特性(一句话总结)

  1. 构建镜像不依赖 docker 等容器运行时,通过脚本化构建镜像,不会独立出镜像层,直接在原有镜像层修改。
  2. 构建的镜像不一定比 Dockerfile 构建的镜像小,正常构建的镜像是一般大。
  3. 适合流水线容器内构建镜像,脱离 docker-in-docker 的场景。
  4. 非常适合开发使用,脚本化构建方式,方便调整和使用。
  5. 构建的镜像,docker or podman 等其他容器运行时看不到。

buildah 构建镜像的三种方式

Dockerfile 构建

buildah 完全兼容 Dockerfile ,此种方式没有任何改造成本

​https://github.com/containers/buildah/blob/main/docs/buildah-build.1.md​

示例:

构建 centos-jdk-1.8.0_201 基础镜像

[root@docp2 java]# ls
Dockerfile jdk
[root@docp2 java]# cat Dockerfile
FROM docker.io/library/centos:centos7.9.2009
RUN mkdir -p /data && chown -R nobody:nobody /data
# 添加JDK包到/data目录
COPY --chown=nobody:nobody jdk /data/jdk
# 声明所需变量
ENV JAVA_HOME=/data/jdk \
PATH=$PATH:/data/jdk/bin

# 构建命令, 如果 FROM 的镜像是私有仓库的,可添加参数 --tls-verify=false
[root@docp2 java]# buildah build -t 10.0.2.196/test/centos:test-jdk
STEP 1: FROM docker.io/library/centos:centos7.9.2009
STEP 2: RUN mkdir -p /data && chown -R nobody:nobody /data
STEP 3: COPY --chown=nobody:nobody jdk /data/jdk
STEP 4: ENV JAVA_HOME=/data/jdk PATH=$PATH:/data/jdk/bin
STEP 5: COMMIT 10.0.2.196/test/centos:test-jdk
Getting image source signatures
Copying blob 174f56854903 skipped: already exists
Copying blob 822dfdc48d2c done
Copying config 69e8ee0cea done
Writing manifest to image destination
Storing signatures
69e8ee0cea7fd15989b1a99649ee1cf1c16deeac55b51ef97d2b5ae00d3ac0dc
69e8ee0cea7fd15989b1a99649ee1cf1c16deeac55b51ef97d2b5ae00d3ac0dc

# 查看本地镜像,
[root@docp2 java]# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.0.2.196/test/centos test-jdk 69e8ee0cea7f About a minute ago 611 MB
docker.io/library/centos centos7.9.2009 eeb6ee3f44bd 17 months ago 212 MB

# 登录私有仓库
[root@docp2 java]# buildah --tls-verify=false login 10.0.2.196
Username (admin): admin
Password:

# 推送镜像至私有仓库
[root@docp2 java]# buildah --tls-verify=false push 10.0.2.196/test/centos:test-jdk
Getting image source signatures
Copying blob 822dfdc48d2c done
Copying blob 174f56854903 done
Copying config 69e8ee0cea done
Writing manifest to image destination
Storing signatures

buildah 云原生时代的镜像打包利器

验证镜像

[root@docp2 java]# docker run -it --rm 10.0.2.196/test/centos:test-jdk java -version
Unable to find image '10.0.2.196/test/centos:test-jdk' locally
test-jdk: Pulling from test/centos
785a5225acb1: Already exists
dc20ff0d87a7: Pull complete
Digest: sha256:75c320da64e31d6bba202661fc37d89e0412bacecaa0e3146f9d53d4381224f6
Status: Downloaded newer image for 10.0.2.196/test/centos:test-jdk
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

脚本化构建(add + run)

我们需要了解 buildah 下边的几个简单命令

build from

构建 working-container,作为下边所有操作的工作容器、基础容器。

​https://github.com/containers/buildah/blob/main/docs/buildah-from.1.md​

示例:

# 常用
buildah from imagename

# 不常用,但是某些场景可能会用到
buildah from --pull docker://myregistry.example.com/imagename
buildah from docker-daemon:imagename:imagetag
buildah from --name mycontainer docker-archive:filename
buildah from oci-archive:filename
buildah from --name mycontainer dir:directoryname
buildah from --pull-always --name "mycontainer" myregistry.example.com/imagename
buildah from --tls-verify=false myregistry/myrepository/imagename:imagetag
buildah from --creds=myusername:mypassword --cert-dir ~/auth myregistry/myrepository/imagename:imagetag
buildah from --authfile=/tmp/auths/myauths.json myregistry/myrepository/imagename:imagetag
buildah from --memory 40m --cpu-shares 2 --cpuset-cpus 0,2 --security-opt label=level:s0:c100,c200 myregistry/myrepository/imagename:imagetag
buildah from --ulimit nofile=1024:1028 --cgroup-parent /path/to/cgroup/parent myregistry/myrepository/imagename:imagetag
buildah from --volume /home/test:/myvol:ro,Z myregistry/myrepository/imagename:imagetag
buildah from -v /home/test:/myvol:z,U myregistry/myrepository/imagename:imagetag
buildah from -v /var/lib/yum:/var/lib/yum:O myregistry/myrepository/imagename:imagetag
buildah from --arch=arm --variant v7 myregistry/myrepository/imagename:imagetag

查看工作容器

buildah containers

buildah add

将本地的文件 or 目录拷贝至工作容器中

​https://github.com/containers/buildah/blob/main/docs/buildah-add.1.md​

buildah add containerID '/myapp/app.conf' '/myapp/app.conf'
buildah add --chown myuser:mygroup containerID '/myapp/app.conf' '/myapp/app.conf'
buildah add --chmod 660 containerID '/myapp/app.conf' '/myapp/app.conf'
buildah add containerID '/home/myuser/myproject.go'
buildah add containerID '/home/myuser/myfiles.tar' '/tmp'
buildah add containerID '/tmp/workingdir' '/tmp/workingdir'
buildah add containerID 'https://github.com/containers/buildah/blob/main/README.md' '/tmp'
buildah add containerID 'passwd' 'certs.d' /etc

buildah config

修改工作容器的相关配置,比如环境变量,容器用户,标签等等

​https://github.com/containers/buildah/blob/main/docs/buildah-config.1.md​

buildah config --author='Jane Austen' --workingdir='/etc/mycontainers' containerID
buildah config --entrypoint /entrypoint.sh containerID
buildah config --entrypoint '[ "/entrypoint.sh", "dev" ]' containerID
buildah config --env foo=bar --env PATH=$PATH containerID
buildah config --env foo- containerID
buildah config --label Name=Mycontainer --label Version=1.0 containerID
buildah config --label Name- containerID
buildah config --annotation note=myNote containerID
# -表示将配置删除
buildah config --annotation note-
buildah config --volume /usr/myvol containerID
buildah config --volume /usr/myvol- containerID
buildah config --port 1234 --port 8080 containerID
buildah config --env 1234=5678 containerID
buildah config --env 1234- containerID
buildah config --os-version 10.0.19042.1645 containerID
buildah config --os-feature win32k containerID
buildah config --os-feature win32k- containerID

buildah run

工作容器内部运行命令,比如安装某个组件,或者创建目录等。

注意:多个命令执行,不可以使用 ​&&​​符号链接,这点和 Dockerfile 不一样,多个命令直接多行即可,不会新增新的镜像层。

​https://github.com/containers/buildah/blob/main/docs/buildah-run.1.md​

buildah run containerID -- ps -auxw
buildah run --hostname myhost containerID -- ps -auxw
buildah run containerID -- sh -c 'echo $PATH'
buildah run --runtime-flag log-format=json containerID /bin/bash
buildah run --runtime-flag debug containerID /bin/bash
buildah run --tty containerID /bin/bash
buildah run --tty=false containerID ls /
buildah run --volume /path/on/host:/path/in/container:ro,z containerID sh
buildah run -v /path/on/host:/path/in/container:z,U containerID sh
buildah run --mount type=bind,src=/tmp/on:host,dst=/in:container,ro containerID sh

buildah commit

将工作容器提交为容器镜像

​https://github.com/containers/buildah/blob/main/docs/buildah-commit.1.md​

buildah commit containerID newImageName

示例

和上边一样,用脚本构建 centos-jdk-1.8.0_201 基础镜像

package.sh 脚本内容:

#!/bin/bash

containerID=$(buildah from centos:centos7.9.2009)
buildah config --label MAINTAINER="centos-jdk buildah" $containerID
buildah run $containerID -- mkdir -p data
buildah add --chown nobody:nobody $containerID 'jdk' '/data/jdk'

buildah config --env JAVA_HOME=/data/jdk --env PATH=$PATH:/data/jdk/bin $containerID
buildah config -u nobody:nobody $containerID

buildah commit $containerID 10.0.2.196/test/centos:test-jdk-1
buildah push --tls-verify=false 10.0.2.196/test/centos:test-jdk-1

执行步骤:

[root@docp2 java]# ls
Dockerfile jdk package.sh

# debug 查看运行过程,实际使用不需要 -x 参数
[root@docp2 java]# bash -x package.sh
++ buildah from centos:centos7.9.2009
+ containerID=centos-working-container
+ buildah config --label 'MAINTAINER=centos-jdk buildah' centos-working-container
+ buildah run centos-working-container -- mkdir -p data
+ buildah add --chown nobody:nobody centos-working-container jdk /data/jdk
bbe72cabbcce735bf96673f124089e4da35d8a1a54864d6ab13d702c40ca0d20
+ buildah config --env JAVA_HOME=/data/jdk --env PATH=/opt/zookeeper/bin:/apps/httpd24/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/go/bin/:/usr/local/node-v15.8.0-linux-x64/bin/:/data/jdk/bin centos-working-container
+ buildah config -u nobody:nobody centos-working-container
+ buildah commit centos-working-container 10.0.2.196/test/centos:test-jdk-1
Getting image source signatures
Copying blob 174f56854903 skipped: already exists
Copying blob 012de7153f1b done
Copying config d3c27e17a4 done
Writing manifest to image destination
Storing signatures
d3c27e17a407ed7fcf0311bd151dc19594e59e4e010c98bd235f2b847d2447b3
+ buildah push --tls-verify=false 10.0.2.196/test/centos:test-jdk-1
Getting image source signatures
Copying blob 012de7153f1b done
Copying blob 174f56854903 skipped: already exists
Copying config d3c27e17a4 done
Writing manifest to image destination
Storing signatures

查看工作容器 和 生成的镜像,对比和 Dockerfile 生成的镜像大小

[root@docp2 java]# buildah containers 
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
d01dc2e33578 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container
[root@docp2 java]# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.0.2.196/test/centos test-jdk-1 d3c27e17a407 About a minute ago 611 MB
10.0.2.196/test/centos test-jdk 69e8ee0cea7f 33 minutes ago 611 MB
docker.io/library/centos centos7.9.2009 eeb6ee3f44bd 17 months ago 212 MB

通过 harbor 也能看到镜像大小是否一致。

buildah 云原生时代的镜像打包利器

验证镜像

通过 ​​java -version​​ 验证镜像是否构建成功,发现初次运行还需要拉取镜像,此时就说明构建的镜像  docker 看不到。

[root@docp2 java]# docker run -it --rm 10.0.2.196/test/centos:test-jdk-1 java -version
Unable to find image '10.0.2.196/test/centos:test-jdk-1' locally
test-jdk-1: Pulling from test/centos
785a5225acb1: Already exists
ca5adcd1d444: Pull complete
Digest: sha256:777cc7b3f5bdfaafe73a233180486a85f2e9a3fcee51d9cab1655bfd7fd33b48
Status: Downloaded newer image for 10.0.2.196/test/centos:test-jdk-1
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

脚本化构建(mount)

buildah mount

将工作容器挂载至宿主机目录,此特性可以规避掉 docker 中 cp 东西还需要依赖 tar 命令的问题,直接原生挂载,可以直接使用宿主机的命令,这样构建打包也方便了不少。

​https://github.com/containers/buildah/blob/main/docs/buildah-mount.1.md​

buildah mount working-container

buildah ummount

将挂载至宿主机目录的工作容器进行卸载。

buildah umount containerID

示例

和上边一样,用脚本构建 centos-jdk-1.8.0_201 基础镜像

package.sh 脚本内容:

#!/bin/bash

containerID=$(buildah from centos:centos7.9.2009)
buildah config --label MAINTAINER="centos-jdk buildah" $containerID

# 关键部分
containerDir=$(buildah mount $containerID)
mkdir -pv $containerDir/data
cp -a jdk $containerDir/data/jdk
buildah umount $containerID

buildah run $containerID -- chown -R nobody:nobody /data
buildah config --env JAVA_HOME=/data/jdk --env PATH=$PATH:/data/jdk/bin $containerID
buildah config -u nobody:nobody $containerID

buildah commit $containerID 10.0.2.196/test/centos:test-jdk-2
buildah push --tls-verify=false 10.0.2.196/test/centos:test-jdk-2

执行过程

[root@docp2 java]# bash -x package.sh 
++ buildah from centos:centos7.9.2009
+ containerID=centos-working-container-1
+ buildah config --label 'MAINTAINER=centos-jdk buildah' centos-working-container-1
++ buildah mount centos-working-container-1
+ containerDir=/var/lib/containers/storage/overlay/e69cc4957b7f3de3e4e2be5f7d90c29af760d17cdf7f8ecfe5eeaa01c3e0f215/merged
+ mkdir -pv /var/lib/containers/storage/overlay/e69cc4957b7f3de3e4e2be5f7d90c29af760d17cdf7f8ecfe5eeaa01c3e0f215/merged/data
mkdir: 已创建目录 "/var/lib/containers/storage/overlay/e69cc4957b7f3de3e4e2be5f7d90c29af760d17cdf7f8ecfe5eeaa01c3e0f215/merged/data"
+ cp -a jdk /var/lib/containers/storage/overlay/e69cc4957b7f3de3e4e2be5f7d90c29af760d17cdf7f8ecfe5eeaa01c3e0f215/merged/data/jdk
+ buildah umount centos-working-container-1
c8d2e33a4c8947b64620d6a39b5bacad2e7c523f26bc190391186b98f0ed0c9d
+ buildah run centos-working-container-1 -- chown -R nobody:nobody /data
+ buildah config --env JAVA_HOME=/data/jdk --env PATH=/opt/zookeeper/bin:/apps/httpd24/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/go/bin/:/usr/local/node-v15.8.0-linux-x64/bin/:/data/jdk/bin centos-working-container-1
+ buildah config -u nobody:nobody centos-working-container-1
+ buildah commit centos-working-container-1 10.0.2.196/test/centos:test-jdk-2
Getting image source signatures
Copying blob 174f56854903 skipped: already exists
Copying blob 7632fc3b770d done
Copying config 2f2fdf4bb8 done
Writing manifest to image destination
Storing signatures
2f2fdf4bb8fb06cc8d44573d92899da8cedd2086ed966198a2f5f3e2c394f22b
+ buildah push --tls-verify=false 10.0.2.196/test/centos:test-jdk-2
Getting image source signatures
Copying blob 7632fc3b770d done
Copying blob 174f56854903 skipped: already exists
Copying config 2f2fdf4bb8 done
Writing manifest to image destination
Storing signatures

查看工作容器和 生成的镜像

[root@docp2 java]# buildah containers 
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
d01dc2e33578 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container
c8d2e33a4c89 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container-1
[root@docp2 java]# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.0.2.196/test/centos test-jdk-2 2f2fdf4bb8fb About a minute ago 611 MB
10.0.2.196/test/centos test-jdk-1 d3c27e17a407 18 minutes ago 611 MB
10.0.2.196/test/centos test-jdk 69e8ee0cea7f 50 minutes ago 611 MB
docker.io/library/centos centos7.9.2009 eeb6ee3f44bd 17 months ago 212 MB

buildah 云原生时代的镜像打包利器

验证镜像

[root@docp2 java]# docker run -it --rm 10.0.2.196/test/centos:test-jdk-2 java -version
Unable to find image '10.0.2.196/test/centos:test-jdk-2' locally
test-jdk-2: Pulling from test/centos
785a5225acb1: Already exists
15b01d9a914a: Pull complete
Digest: sha256:ba119d8e116f34f4fbf43d840c39408afef47afe492deca8c6a4b95a4898adf2
Status: Downloaded newer image for 10.0.2.196/test/centos:test-jdk-2
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

其他常见命令

buildah login

登录镜像仓库

buildah --tls-verify=false login xxxxxxx

buildah containers

查看当前的 working container

buildah containers

buildah images

查看 buildah 中的镜像

buildah images

buildah copy

类似于 build add ,但是没有 add 拷贝tar包立即解压的功能

​https://github.com/containers/buildah/blob/main/docs/buildah-copy.1.md​

buildah copy containerID '/myapp/app.conf' '/myapp/app.conf'
buildah copy --chown myuser:mygroup containerID '/myapp/app.conf' '/myapp/app.conf'
buildah copy --chmod 660 containerID '/myapp/app.conf' '/myapp/app.conf'
buildah copy containerID '/home/myuser/myproject.go'
buildah copy containerID '/home/myuser/myfiles.tar' '/tmp'
buildah copy containerID '/tmp/workingdir' '/tmp/workingdir'
buildah copy containerID 'https://github.com/containers/buildah' '/tmp'
buildah copy containerID 'passwd' 'certs.d' /etc

buildah info

查看当前服务器节点的信息

buildah info

buildah inspect

查看容器的详细信息

buildah inspect containerID
buildah inspect --type container containerID
buildah inspect --type image imageID
buildah inspect --format '{{.OCIv1.Config.Env}}' alpine

buildah pull

拉取镜像

​https://github.com/containers/buildah/blob/main/docs/buildah-pull.1.md​

buildah pull imagename
buildah pull docker://myregistry.example.com/imagename
buildah pull docker-daemon:imagename:imagetag
buildah pull docker-archive:filename
buildah pull oci-archive:filename
buildah pull dir:directoryname
buildah pull --tls-verify=false myregistry/myrepository/imagename:imagetag
buildah pull --creds=myusername:mypassword --cert-dir ~/auth myregistry/myrepository/imagename:imagetag
buildah pull --authfile=/tmp/auths/myauths.json myregistry/myrepository/imagename:imagetag
buildah pull --arch=aarch64 myregistry/myrepository/imagename:imagetag
buildah pull --arch=arm --variant=v7 myregistry/myrepository/imagename:imagetag

buildah push

推送镜像至镜像仓库

​https://github.com/containers/buildah/blob/main/docs/buildah-push.1.md​

buildah push imageID dir:/path/to/image
buildah push imageID oci:/path/to/layout:image:tag
buildah push imageID oci-archive:/path/to/archive:image:tag
buildah push imageID docker://registry.example.com/repository:tag
buildah push --digestfile=/tmp/mydigest imageID docker://registry.example.com/repository:tag
buildah push registry.example.com/my_image
buildah push --authfile /tmp/auths/myauths.json imageID docker://registry.example.com/repository:tag
buildah push imageID docker-daemon:image:tag
buildah push --tls-verify=false imageID localhost:5000/my-imageID
buildah push --cert-dir ~/auth --tls-verify=true --creds=username:password imageID localhost:5000/my-imageID

buildah rename

本地 working container 进行改名

[root@docp2 java]#  buildah containers
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
d01dc2e33578 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container
c8d2e33a4c89 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container-1
[root@docp2 java]# buildah rename d01dc2e33578 centos-working-11111
[root@docp2 java]# buildah containers
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
d01dc2e33578 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-11111
c8d2e33a4c89 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container-1

buildah rm

删除 working container

[root@docp2 java]# buildah containers
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
d01dc2e33578 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-11111
c8d2e33a4c89 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container-1
[root@docp2 java]# buildah rm centos-working-11111
d01dc2e33578d3bf1f9eac0c89dde62f1e536a4a2ddf5de374a0035e30758ebb
[root@docp2 java]# buildah containers
CONTAINER ID BUILDER IMAGE ID IMAGE NAME CONTAINER NAME
c8d2e33a4c89 * eeb6ee3f44bd docker.io/library/centos:cent... centos-working-container-1

buildah rmi

删除镜像

[root@docp2 java]# buildah images 
REPOSITORY TAG IMAGE ID CREATED SIZE
10.0.2.196/test/centos test-jdk-2 2f2fdf4bb8fb 24 minutes ago 611 MB
10.0.2.196/test/centos test-jdk-1 d3c27e17a407 41 minutes ago 611 MB
10.0.2.196/test/centos test-jdk 69e8ee0cea7f About an hour ago 611 MB
docker.io/library/centos centos7.9.2009 eeb6ee3f44bd 17 months ago 212 MB
[root@docp2 java]# buildah rmi 10.0.2.196/test/centos:test-jdk
untagged: 10.0.2.196/test/centos:test-jdk
69e8ee0cea7fd15989b1a99649ee1cf1c16deeac55b51ef97d2b5ae00d3ac0dc
[root@docp2 java]# buildah images
REPOSITORY TAG IMAGE ID CREATED SIZE
10.0.2.196/test/centos test-jdk-2 2f2fdf4bb8fb 25 minutes ago 611 MB
10.0.2.196/test/centos test-jdk-1 d3c27e17a407 41 minutes ago 611 MB
docker.io/library/centos centos7.9.2009 eeb6ee3f44bd 17 months ago 212 MB


buildah tag

对已存在的镜像新生成一个 tag 号

buildah tag imageName firstNewName
buildah tag imageName firstNewName SecondNewName

buildah unshare

独立运行 mount 更安全

buildah unshare id
buildah unshare pwd
buildah unshare cat /proc/self/uid_map /proc/self/gid_map
buildah unshare rm -fr $HOME/.local/share/containers/storage /run/user/`id -u`/run
buildah unshare --mount containerID sh -c 'cat ${containerID}/etc/os-release'

buildah version

查看 buildah 版本

 buildah version