MENU

Buildahデーモンレスビルドへ移行するCI本番パイプライン設計|Skopeoイメージ署名検証

CIパイプラインにDockerデーモンを組み込む構成は長年の標準でしたが、/var/run/docker.sockをジョブコンテナにマウントする手法はホストのroot相当の権限をジョブに渡すことになり、セキュリティ上の懸念として広く認識されています。BuildahはDockerデーモンを必要とせずにOCIイメージを構築できるツールで、rootlessモードでの動作を前提として設計されています。本記事では、既存のDocker依存パイプラインからBuildahへ移行する手順と、SkopeoおよびCosign/Sigstoreを組み合わせたイメージ署名検証を本番CIパイプラインへ組み込む設計を解説します。

目次

Dockerデーモン依存が抱えるリスクと移行の動機

従来のCI構成でよく使われるDocker-in-Docker(DinD)は、--privilegedフラグを要求します。これはコンテナ内からホストのすべてのLinuxケーパビリティへアクセスできる状態であり、KubernetesのデフォルトセキュリティポリシーであるPod Security Standardsのrestrictedプロファイルでは禁止されています。docker.sockを直接マウントする手法も同様に問題があり、ソケットへのアクセス権限はDockerデーモン経由でホストrootへのエスカレーションパスを開くため、CIジョブが侵害された場合の影響範囲が広くなります。

Buildahはこれらの問題を次の設計で解決しています。

  • Dockerデーモンへの依存ゼロ:デーモンプロセスを起動せずにOCIイメージをビルド可能
  • rootlessモード:ユーザ名前空間(user namespace)を使い、rootなしでoverlayfsを操作
  • OCI準拠:生成するイメージはOCI Image Spec準拠であり既存のDockerレジストリとの互換性を維持
  • Containerfileの完全サポート:既存のDockerfileをそのまま利用可能

Buildahのセットアップとrootlessモードの前提条件

Buildahをrootlessで動作させるにはユーザ名前空間のサポートが必要です。現代的なディストリビューション(RHEL 9・Ubuntu 22.04以降など)ではカーネルレベルでの対応が済んでいますが、/etc/subuidと/etc/subgidへのエントリ追加が必要です。

# CIサービスアカウント用のsubuid/subgidを設定(想定例)
echo "ci-runner:100000:65536" | sudo tee -a /etc/subuid
echo "ci-runner:100000:65536" | sudo tee -a /etc/subgid

コンテナ内でBuildahをrootlessで動かす場合(GitHub ActionsやGitLab CIのコンテナジョブなど)は、ホストのoverlayfsが使えないケースがあります。このような環境ではfuse-overlayfsをインストールして--storage-driver=overlayを利用するか、パフォーマンスを妥協して--storage-driver=vfsをフォールバックとして使います。

# fuse-overlayfsが利用できる環境でのstorage.conf設定
# $HOME/.config/containers/storage.conf
[storage]
driver = "overlay"

[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"

GitHub ActionsへのBuildah組み込み

GitHub ActionsでBuildahを使う場合、redhat-actions/buildah-buildアクションを利用するか、直接インストールする方法があります。以下はubuntu-24.04ランナーで直接インストールする想定例です。

name: Build and Push Image
on: [push]

jobs:
  build:
    runs-on: ubuntu-24.04
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4

      - name: Install Buildah and fuse-overlayfs
        run: |
          sudo apt-get update -qq
          sudo apt-get install -y buildah fuse-overlayfs

      - name: Build image with Buildah
        run: |
          buildah build \
            --storage-driver=overlay \
            --tag ghcr.io/${{ github.repository }}:${{ github.sha }} \
            .

      - name: Push image
        run: |
          buildah push \
            --creds ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} \
            ghcr.io/${{ github.repository }}:${{ github.sha }}

GitLab CIへの組み込み

GitLab CIではquay.io/buildah/stableイメージをベースにしたジョブが一般的です。--privileged不要で動作させるには、ランナーホストで/proc/sys/user/max_user_namespacesが0になっていないか事前に確認してください。

build-image:
  image: quay.io/buildah/stable
  variables:
    STORAGE_DRIVER: overlay
    BUILDAH_FORMAT: docker
  script:
    - buildah build
        --storage-driver=$STORAGE_DRIVER
        --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
        .
    - buildah push
        --creds $CI_REGISTRY_USER:$CI_REGISTRY_PASSWORD
        $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

Skopeoによるイメージ操作と署名検証の組み込み

Skopeoは、コンテナイメージをローカルにプルせずにレジストリ間でコピー・検査・署名検証できるツールです。Buildahがビルドを担うのに対し、Skopeoはビルド後のイメージの安全な取り回しを担います。主な用途は次のとおりです。

  • レジストリ間のイメージコピー(docker://からoci:形式への変換含む)
  • マルチアーキテクチャイメージのダイジェスト確認
  • policy.jsonに基づく署名検証ポリシーの適用
  • Cosign/Sigstoreで署名されたイメージのデプロイ前検証

Cosign/Sigstoreを使ったキーレス署名と検証

SigstoreプロジェクトのCosignは、OIDCトークンを使ったキーレス署名に対応しています。GitHub ActionsやGitLab CIではIDトークンを自動取得できるため、秘密鍵を管理せずに署名が完結します。署名はRekorの公開透明性ログに記録されます。

# GitHub Actionsでのキーレス署名(想定例)
# permissionsブロックに id-token: write が必要
- name: Install Cosign
  uses: sigstore/cosign-installer@v3

- name: Sign image (keyless)
  run: |
    cosign sign \
      --yes \
      ghcr.io/${{ github.repository }}:${{ github.sha }}

デプロイ時やCI後段ステージでの検証は次のように実行します。--certificate-identityにはCIのOIDCクレームから発行されるワークフローのURLを指定します。

# 検証コマンド(想定例)
cosign verify \
  --certificate-identity \
    "https://github.com/${GITHUB_REPOSITORY}/.github/workflows/build.yml@refs/heads/main" \
  --certificate-oidc-issuer \
    "https://token.actions.githubusercontent.com" \
  ghcr.io/${IMAGE_REPO}:${IMAGE_TAG}

SkopeoのPolicy.jsonによる検証ポリシーの適用

Skopeoは/etc/containers/policy.json(またはユーザ単位の$HOME/.config/containers/policy.json)に記述したポリシーに基づいてイメージの取得・コピーを制御できます。特定のレジストリからのイメージに署名を義務付ける設定例は次のとおりです。

{
  "default": [{"type": "reject"}],
  "transports": {
    "docker": {
      "registry.example.internal": [
        {
          "type": "sigstoreSigned",
          "keyPath": "/etc/containers/cosign.pub",
          "signedIdentity": {"type": "matchRepository"}
        }
      ],
      "ghcr.io/your-org": [
        {"type": "insecureAcceptAnything"}
      ]
    }
  }
}

この設定ではregistry.example.internalからのイメージは署名なしには取得できず、未署名のイメージが本番環境に流入するリスクを構造的に排除できます。skopeo copyやskopeo inspectはこのポリシーを参照して動作するため、CI後段のイメージコピーステップにそのまま組み込めます。

パイプライン全体の動作検証とよくあるつまずき

移行後にまず確認すべき検証項目を以下に挙げます。

  • ストレージドライバの確認:buildah infoでGraphDriverが想定どおり(overlayまたはvfs)になっているか確認する
  • ビルドキャッシュの挙動:BuildahのレイヤーキャッシュはDockerのものとは独立しているため、CIキャッシュ戦略の再設計が必要になることがある
  • マルチステージビルドの動作:BuildahはFROM ... AS構文に対応しているが、Dockerfileを読み込む際はbuildah bud(build-using-dockerfile)サブコマンドを使う
  • Skopeoの接続確認:skopeo inspect docker://IMAGE:TAGでレジストリへの疎通と認証を事前確認する

一般的なつまずきとして、コンテナ内でfuse-overlayfsが見つからない(パッケージが未インストール)ケース、/proc/sys/user/max_user_namespacesが0に設定されていてuser namespaceが無効になっているケース、CI実行ユーザに/etc/subuidのエントリがないケースが挙げられます。

# user namespaceの有効確認
cat /proc/sys/user/max_user_namespaces
# 0の場合はカーネルパラメータを変更する
echo 65536 | sudo tee /proc/sys/user/max_user_namespaces

# rootlessモードでのストレージ状態確認
buildah info --debug 2>&1 | grep -iE "graphdriver|runroot|imagestore"

切り戻し計画と運用時の注意点

Buildahへの移行は段階的に進めることが現実的です。最初はサイドバイサイドで並走させ、既存のDocker/DinD構成をフォールバックとして残しておくと安全です。

  • CI変数による切り替え:USE_BUILDAH=trueのようなフラグでビルドバックエンドを切り替えられるようにしておくと、問題発生時に即座に戻せる
  • イメージダイジェストの記録:移行前後でビルド結果のダイジェストが一致することを確認し、差異が出た場合の原因調査フローを用意する
  • Rekorへのメタデータ書き込み:Cosignのキーレス署名はRekorの公開透明性ログへの書き込みを伴う。機密性の高い内部イメージのリポジトリ情報が公開ログに残ることを把握した上で、必要であれば自己ホストのRekorインスタンスを検討する
  • policy.jsonの段階適用:いきなり"type": "reject"をデフォルトにすると未署名イメージがすべて取得不可になる。まずinsecureAcceptAnythingで動作確認し、署名済みイメージの割合を高めてから切り替える

2026年現行環境での差分と選択肢

2026年時点では、Buildah・Skopeo・Cosignを取り巻く状況がいくつかの点で変化しています。

BuildahとPodman 5.xの統合:BuildahのコアコードはPodman 5.x系に取り込まれる形で開発が進んでおり、podman buildがBuildahのラッパーとして機能します。コンテナ型CIではpodman buildとbuildah buildはほぼ同等に使えますが、ランナー環境にどちらのバイナリが入るかは事前に確認が必要です。

OCI Image Spec 1.1とアテステーション:OCI Image Spec 1.1ではイメージアテステーション(SBOM・来歴情報)をReferrers APIで付与する仕組みが標準化されました。CosignはすでにSBOMと署名を同一イメージに付与できますが、Skopeoのpolicy.jsonによるアテステーション単体への検証は対応が限定的です。SBOMの検証まで含めるなら、CosignとともにOCI Referrers対応ツール(例:notation)との組み合わせを検討する価値があります。

GitHub ActionsのOIDC統合の成熟:permissions: id-token: writeを付与するだけでOIDCトークンが発行されるため、Cosignのキーレス署名がCI設定の数行で完結します。2026年時点ではこのフローが多くのプロジェクトで標準的な署名方法となっており、追加のシークレット管理が不要な点がメリットです。

BuildKitとの棲み分け:containerd/BuildKitはDockerfileのビルド高速化とリモートキャッシュで広く使われていますが、rootlessでのCI動作にはbuildkitdデーモンプロセスが必要な点でBuildahと設計哲学が異なります。デーモンレスを最優先にする環境ではBuildah、マルチプラットフォームビルドのキャッシュ効率を優先する場合はBuildKit、という使い分けが実態に近い選択です。どちらのツールも同一のOCIイメージを出力できるため、後からの切り替えはビルド設定の変更だけで対応できます。

「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。

ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。

>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)

※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。

PR・広告

新しいLinuxの教科書 第2版(Amazon)

コマンド操作から基本運用までを手を動かして学べる定番書。記事で触れた技術の土台固めに。

Amazonで見る

※ Amazonのアソシエイトとして、当サイトは適格販売により収入を得ています。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

目次