Buildah: Docker 镜像构建工具

发布时间: 更新时间: 总字数:1464 阅读时间:3m 作者:IP:上海 网址

Buildah 是 Red Hat 开源的一款专门用于构建 OCI(Open Container Initiative)和 Docker 兼容镜像的工具。本文详细介绍 Buildah 的使用方法。

介绍

Buildah的最大特色是:没有守护进程(Daemonless)不需要 Root 权限(Rootless),并且除了支持传统的 Dockerfile 构建外,还支持一种无需 Dockerfile 的纯脚本命令构建模式。这使得它在 CI/CD 环境中非常灵活和安全。

安装 Buildah

在使用下面的示例前,请确保系统已安装 Buildah。

  • CentOS/RHEL/Fedora: sudo dnf install buildah
  • Ubuntu/Debian: sudo apt update && sudo apt install buildah
  • macOS: 可以通过 brew install podman (Podman 内置了 Buildah 核心功能) 或在 Linux 虚拟机/容器中运行。

核心构建方式与示例

Buildah 有两种主要的镜像构建方式:

  1. 兼容 Dockerfile 模式(最容易上手,适合迁移旧项目)
  2. Buildah 原生命令行模式(最灵活,不需要 Dockerfile,可以像写 Bash 脚本一样构建镜像)

示例 1:使用传统的 Dockerfile 构建镜像

如果你已经有了一个项目,这是最快的迁移方式。buildah build(旧版本中叫 buildah bud)的用法和 docker build 几乎一模一样。

可以直接运行的 Shell 脚本:

bash
# 1. 创建一个测试目录并进入
mkdir buildah-test && cd buildah-test

# 2. 准备一个简单的 Dockerfile
cat <<EOF > Dockerfile
FROM alpine:latest
RUN echo "Hello Buildah!" > /hello.txt
ENTRYPOINT ["cat", "/hello.txt"]
EOF

# 3. 使用 buildah 构建镜像 (用法和 docker build 一样)
# 注意:不需要 sudo!
buildah build -t my-alpine-app:v1 .

# 4. 查看构建好的镜像
buildah images

(注意:Buildah 仅负责“构建”。要运行这个镜像,你可以使用 podman run --rm my-alpine-app:v1 或将其推送到镜像仓库后用 Docker 运行。)

示例 2:Buildah 原生脚本构建(无需 Dockerfile,高级且极具特色!)

这是 Buildah 最强大的地方。你可以启动一个空的容器容器实例,然后在宿主机上直接挂载它的文件系统,或者用 buildah run 在里面执行命令,最后把它提交(commit)成一个镜像。这非常适合在 CI 脚本中按需动态生成镜像。

可以直接运行的 Shell 脚本:

bash
#!/bin/bash
set -e

echo "=== 开始使用 Buildah 原生命令构建镜像 ==="

# 1. 以 ubuntu 为基础创建一个工作容器,并获取它的容器 ID
# (相当于 Dockerfile 中的 FROM ubuntu)
container=$(buildah from ubuntu:22.04)
echo "创建的临时容器名称为: $container"

# 2. 在容器内运行命令:更新并安装 curl
# (相当于 Dockerfile 中的 RUN apt-get update ...)
# 注意: "--" 用于区分 buildah 参数和要在容器内执行的命令
buildah run $container -- apt-get update
buildah run $container -- apt-get install -y curl

# 3. 将宿主机上的内容写入容器内
# (相当于 Dockerfile 中的 COPY 或 ADD)
echo "这是一段在宿主机生成的内容" > host_file.txt
buildah copy $container host_file.txt /app/host_file.txt

# 4. 配置镜像的环境变量、工作目录和启动命令
# (相当于 Dockerfile 中的 ENV, WORKDIR, ENTRYPOINT)
buildah config --env MY_APP_ENV=production $container
buildah config --workingdir /app $container
buildah config --entrypoint '["cat", "/app/host_file.txt"]' $container

# 5. 将这个容器提交保存为一个新的 Docker/OCI 镜像
buildah commit $container my-custom-ubuntu:latest

# 6. (可选) 清理刚才使用的临时容器实例
buildah rm $container

echo "=== 构建完成!镜像列表如下: ==="
buildah images

结合 GitLab CI 的实战示例

这是直接应用在 GitLab CI 中替代 DinD (Docker-in-Docker) 的示例。我们将构建一个镜像并推送到 GitLab 自己的容器镜像库。

.gitlab-ci.yml 示例配置:

yaml
stages:
  - build

build-and-push:
  stage: build
  # 使用官方维护的 buildah 镜像
  image: quay.io/buildah/stable:latest
  variables:
    # 强制生成 Docker 兼容格式的镜像(默认为 OCI 格式,某些老旧仓库只认 Docker 格式)
    BUILDAH_FORMAT: docker
    # 在容器内运行 Buildah 时需要此隔离配置
    BUILDAH_ISOLATION: chroot
  before_script:
    # 登录到 GitLab 容器镜像库
    - echo "$CI_REGISTRY_PASSWORD" | buildah login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
  script:
    # 打印当前路径(包含项目源码和 Dockerfile)
    - pwd

    # 1. 构建镜像,使用 GitLab 提供的变量作为 Tag
    # $CI_REGISTRY_IMAGE 指向该项目的镜像库地址 (例如 registry.gitlab.com/group/project)
    - buildah build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .

    # 2. 给镜像打上 latest 标签(可选)
    - buildah tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:latest

    # 3. 将镜像推送到 Registry
    - buildah push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
    - buildah push $CI_REGISTRY_IMAGE:latest

常用 Buildah 命令速查

  • buildah images:查看本地已构建的镜像。
  • buildah containers:查看正在用于构建的中间容器(类似 Docker 的正在运行的容器,但仅用于构建)。
  • buildah build -t name .:通过 Dockerfile 构建。
  • buildah mount <container>神级功能! 直接把容器的文件系统挂载到宿主机的一个目录下,你可以直接在宿主机用 cp, vim, tar 操作容器内的文件,操作完 buildah unmount 然后 commit 即可。
  • buildah push <image> docker://<registry_url>:推送到远程仓库。