在 Jenkins 容器中使用 buildah push 推送镜像时,设置登录认证主要有三种方式。将凭证硬编码在命令里会带来严重的安全风险,因此在实际的 CI/CD 实践中,更推荐采用"登录 (Login) + 配置文件 (Authfile)“的方式

1. 基本方法:使用 --creds 参数直接指定(不推荐)

这是最直接但不安全的方法。你可以在 push 命令中直接使用 --creds 标志提供凭证。

1# 基本的 --creds 用法
2buildah push --creds=用户名:密码 your-image docker://your-registry.com/your-image:tag
3
4# 一个完整的例子
5buildah push --creds=admin:MyP@ssw0rd my-local-image docker://docker.io/myuser/my-image:latest

安全风险:密码明文出现在命令行参数中,会被系统进程列表(ps aux)、Shell 历史、Jenkins 日志等记录,极易泄露。

2. 推荐方法:登录 (Login) + 配置文件 (Authfile)

这是更安全且更符合 CI/CD 实践的方法。buildah login 命令会生成一个认证文件(默认为 auth.json),之后的 buildah push 命令会自动读取该文件中的凭证。

交互式输入(适用于手动测试)

1buildah login docker.io

命令行直接提供(适用于脚本)

1buildah login -u admin -p MyP@ssw0rd docker.io

虽然比 --creds 略好,但密码仍会出现在命令行历史和进程列表中,建议仅在临时脚本中使用。

--password-stdin(最佳实践)

这是最安全的方式,能从标准输入读取密码,避免密码出现在命令行历史或进程列表中。

1# 通过管道从环境变量中读取密码
2echo $MY_PASSWORD | buildah login -u admin --password-stdin docker.io
3
4# 或者从文件读取
5buildah login -u admin --password-stdin < /path/to/password.txt

3. 进阶方法:使用 --authfile 控制认证文件路径

buildah 命令默认会按以下顺序查找认证文件:

  1. ${XDG_RUNTIME_DIR}/containers/auth.json(通常为 /run/user/$UID/containers/auth.json
  2. $HOME/.docker/config.json(兼容 Docker 的配置)

你可以使用 --authfile 标志来覆盖这个默认位置,这在需要为不同任务管理多个独立认证文件时非常有用。

1# 1. 登录并保存认证信息到指定文件
2buildah login --authfile /path/to/my-auth.json -u admin --password-stdin docker.io < password.txt
3
4# 2. push 时指定使用该认证文件
5buildah push --authfile /path/to/my-auth.json my-image docker://my-registry.com/my-image:tag

你也可以通过设置 REGISTRY_AUTH_FILE 环境变量来全局改变认证文件的位置,这样所有 buildah 命令都会使用它。

1export REGISTRY_AUTH_FILE=/path/to/my-auth.json
2buildah push ...  # 会自动使用上述文件中的认证信息

💡 总结与建议:在 Jenkins 中安全实践

1. 使用 Jenkins 凭证 (Credentials)

在 Jenkins 的 Web 界面(系统管理 > 凭证)中,为你的容器仓库添加 Username with password 类型的凭证,记录仓库地址、用户名和密码或令牌。

2. 在流水线中引用

Jenkinsfile 中,通过 credentials() 辅助函数安全地引用凭证,并配合 --password-stdin 方法使用。

 1pipeline {
 2    environment {
 3        // 假设凭证ID为 'my-registry-creds'
 4        REGISTRY_USER = credentials("my-registry-creds_USR")
 5        REGISTRY_PASS = credentials("my-registry-creds_PSW")
 6    }
 7    stages {
 8        stage('Push Image') {
 9            steps {
10                sh """
11                    # 使用 --password-stdin 进行安全登录
12                    echo ${REGISTRY_PASS} | buildah login \\
13                        -u ${REGISTRY_USER} \\
14                        --password-stdin \\
15                        my-registry.com
16
17                    # 登录成功后,push 命令会使用默认的 auth.json 文件
18                    buildah push my-image docker://my-registry.com/my-image:latest
19                """
20            }
21        }
22    }
23}

3. 处理自签名证书的私有仓库

如果私有仓库使用自签名或内部 CA 签发的 TLS 证书,需要确保 Jenkins 容器能信任它:

  • 推荐方案:将 CA 证书复制到容器内,并指定 --cert-dir 参数:

    1buildah --cert-dir /path/to/certs push ...
    
  • 临时方案:在测试或内部环境中临时跳过 TLS 验证(生产环境不推荐):

    1buildah push --tls-verify=false ...
    

buildah login 命令默认会将认证信息写入 auth.json 文件,该文件的权限仅为创建者所有,请确保 Jenkins 构建用户有权限访问该文件。