リモート開発メインのソフトウェア開発企業のエンジニアブログです

Podman と Docker の異なる点(Build secrets 編)

Docker Desktop から完全撤退して Podman Desktop 一本で行くことにした (macOS) という記事を少し前に書きましたが、あれからしばらく使っていて、Podman (および Podman Compose) の Build secrets 周りの挙動(というか実装状況)が Docker と異なる点を発見したので、その対処法を今回紹介します。他にもありそうなので Build secrets 編としましたが続編があるかは不明です。

なお、検証時のバージョンはそれぞれ

podman-compose version 1.5.0
podman version 5.8.0

です。

免責事項 (Disclaimer)

一応セキュリティに絡む話題なので、書かれた内容を実践する際は自己責任でお願いいたします。

使っていた Dockerfile, compose.yaml

ビルド時にある API key を必要とするコマンドの実行をする為に、それぞれ次のような構成になっていました:

# Dockerfile

FROM amazon/aws-cli
RUN --mount=type=secret,id=aws-access-key-id,env=AWS_ACCESS_KEY_ID \
    --mount=type=secret,id=aws-secret-access-key,env=AWS_ACCESS_KEY_ID \ 
    --mount=type=secret,id=aws-session-token,env=AWS_SESSION_TOKEN \ 
    aws ...
# compose.yaml

services:
  app:
    build:
      secrets:
        - aws-access-key-id
        - aws-secret-access-key
        - aws-session-token
    # ...

secrets:
  aws-access-key-id:     { environment: 'AWS_ACCESS_KEY_ID' }
  aws-secret-access-key: { environment: 'AWS_SECRET_ACCESS_KEY' }
  aws-session-token:     { environment: 'AWS_SESSION_TOKEN' }

本題から逸れてしまうのでざっくりとした説明になりますが、podman build 時に、あらかじめターミナルに露出させておいた AWS_ACCESS_KEY_ID などの環境変数を、Build secrets 経由で Dockerfile の RUN に、同じ名前の環境変数で安全に渡しています。こうする事でビルド時に特定の aws コマンドを実行できる様にしています。
これらの機密情報を ENV 使って Dockerfile に直接記述するのは論外ですが、--build-arg でビルダーに渡すのも好ましくありません。Build secrets を使いましょう。(詳しくは https://docs.docker.com/build/building/secrets/ を参照)

Moba Pro

実際にビルドしてみると

podman-compose build app

次のようなエラーが発生しました:

ERROR: unparsable secret: "aws-access-key-id", service: "app"

実際には Python の Stack trace も出ていたので、podman-compose の段階でエラーが起きている様です。なので直接 podman build を実行してみました。

podman build --no-cache \                                              
  --tag test-app \
  --secret id=aws-access-key-id,env=AWS_ACCESS_KEY_ID \
  --secret id=aws-secret-access-key,env=AWS_SECRET_ACCESS_KEY \
  --secret id=aws-session-token,env=AWS_SESSION_TOKEN \
  .

こちらもエラーが発生します。

(略)
secret should have syntax id=id[,target=path,required=bool,mode=uint,uid=uint,gid=uint

Podman, Podman Compose 双方で対応していなさそうです。

公式リポジトリでの対応状況は…

podman build によるイメージビルドは Buildah と言うツールによって行われるんですが、まさにこの問題に対処する PR がマージされていました: https://github.com/containers/buildah/pull/6285
ただし、Podman 5.8.0 にバンドルされている Buildah 1.43.0 (執筆日 2026/03/23 時点) ではまだ実装されておらず、おそらく次のリリースになるんじゃないかなと思います。

また、 Podman Compose については実装自体がなかったので、本体に PR を投げておきました。おそらくマージされるんじゃないかなーと思います: https://github.com/containers/podman-compose/pull/1424
Secrets には Runtime secrets もあるんですが、パッチが大きくなりそうなので今回は Build secrets のみ対応しています。
(余談ですが、Podman Compose のプロジェクトは初参加ですが Claude Code のおかげですごく簡単にパッチを送れました。便利な時代になりましたが、CONTRIBUTING.md などのガイドには必ず目を通し、コードの内容もセルフレビューして AI Slop にならないよう注意しましょう。当たり前のことですが。)

応急処置として

いずれも公式でサポートがされそうではありますが、 (執筆日 2026/03/23 時点) ではまだどちらも使えません。応急処置として、以下のように対応しました。

まずは Dockerfile を更新します:

RUN --mount=type=secret,id=aws-access-key-id \
    --mount=type=secret,id=aws-secret-access-key \
    --mount=type=secret,id=aws-session-token \
    AWS_ACCESS_KEY_ID=$(cat /run/secrets/aws-access-key-id) \
    AWS_SECRET_ACCESS_KEY=$(cat /run/secrets/aws-secret-access-key) \
    AWS_SESSION_TOKEN=$(cat /run/secrets/aws-session-token) \
    aws ...

やってる事は元の状態とほぼ同じで、 Build secrets は /run/secrets/{secret_name} と言うファイルにデフォルトでマウントされるので、env= は使わず Shell で自前で環境変数にセットしてから aws コマンドを呼び出しています。この方式はDocker 側の公式ドキュメントでも紹介されている手法です。

また、Podman (or Docker) Compose は、デフォルトで <project_name>_<service_name> と言う tag でサービスコンテナのイメージをビルドするので、ちょっと面倒ですが Compose を経由せず podman build --tag <project_name>_<service_name> で事前にビルドしておけば起動できます。

まとめ

  • 執筆日 (2026/03/23) 時点で Build secrets の扱いが Docker と Podman (また Compose) で異なる
  • Dockerfile 側は書き方を変えればとりあえず同じ事はできる
  • 指定のイメージ名で podman build すればとりあえず Podman Compose でサービスを起動できる
  • Podman, Podman Compose 共に元の書き方をサポートする可能性が高いので今後はこのテクニックは不要になりそう

← 前の投稿

npx でフォークしたレポジトリを実行すると command not found となる場合の対処方法

次の投稿 →

コメントを残す