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 有两种主要的镜像构建方式:
- 兼容 Dockerfile 模式(最容易上手,适合迁移旧项目)
- Buildah 原生命令行模式(最灵活,不需要 Dockerfile,可以像写 Bash 脚本一样构建镜像)
示例 1:使用传统的 Dockerfile 构建镜像
如果你已经有了一个项目,这是最快的迁移方式。buildah build(旧版本中叫 buildah bud)的用法和 docker build 几乎一模一样。
可以直接运行的 Shell 脚本:
# 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 脚本:
#!/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 示例配置:
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>:推送到远程仓库。