PR

Docker secretがパス文字列になる?PostgreSQLの_FILE対応をXServer VPSで実測

【PR】この記事にはA8.netのアフィリエイト広告を含みます。

先に結論:Docker Compose secretpathを通常のPOSTGRES_PASSWORDへ入れても、file内容には自動展開されません。XServer VPSPostgreSQL 17.10を実測すると、実secret値では0/5回失敗し、文字列/run/secrets/db_passwordでは5/5回認証成功しました。POSTGRES_PASSWORD_FILE版は正反対に実secret値で5/5回成功したため、判定は設定方法について解決です。

Docker secretpathを書くと中身が環境変数に入る?

入りません。Compose secretcontainer内へfileとしてmountされます。環境変数へ/run/secrets/my_secretと書いた場合、その値はpathを表すただの文字列です。applicationfileを開かなければsecret内容は使われません。

悩みの起点にしたRedditSecret assigned to ENV variable in docker-compose has the path as value」では、React/Vite appVITE_A: /run/secrets/vite_aを設定すると、画面にsecret内容ではなくpathが出たと報告されています。

Docker公式ではCompose secretをどう説明している?

Docker公式のCompose secrets docsでは、secretLinux container/run/secrets/<secret_name>fileとしてmountされると説明されています。

docsMYSQL_PASSWORD_FILEPOSTGRES_PASSWORD_FILEDocker共通機能ではなく、一部のDocker Official Imagesが実装している「_FILE conventionです。任意の環境変数名へ_FILEを付ければ動くわけではありません。

XServer VPSでどんな実験をした?

項目 実測条件
VPS XServer VPS、4 vCPU4GB RAM、150GB
OS Ubuntu 26.04
Docker Compose v5.5.0
DB postgres:17.10-alpineを2個
secret 実験ごとに生成した49文字の合成password
認証 TCPSCRAM-SHA-256
試行 4条件×5回、計20回
network Docker internal network、公開portなし
上限 DB 0.5 CPU256MiB RAMPID 128

本物のpasswordAPI keytokenは使っていません。raw合成passwordも結果へ残さず、49文字という長さとSHA-256だけを保存しました。

[PR]
Dockerを安全に試せるVPSなら『XServer VPS』

通常のPOSTGRES_PASSWORDへsecret pathを入れるとどうなった?

wrong版は次の設定です。

services:
  db:
    image: postgres:17.10-alpine
    environment:
      POSTGRES_PASSWORD: /run/secrets/db_password
    secrets:
      - db_password

secrets:
  db_password:
    file: ./db_password.txt

DBへ実secret値で5回loginすると0/5回で、すべてFATAL: password authentication failedでした。ところがliteral path/run/secrets/db_passwordpasswordとして使うと5/5回成功しました。

secret fileは正しくmountされていましたが、PostgreSQL entrypointは通常のPOSTGRES_PASSWORDを文字列として受け取ります。そのためpath自体がDB passwordとして初期設定されました。

POSTGRES_PASSWORD_FILEならどうなった?

correct版は変数名だけを変えました。

environment:
  POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
  - db_password

secret値で5/5回認証成功し、literal pathでは0/5回失敗しました。Official PostgreSQL imageentrypointPOSTGRES_PASSWORD_FILEを認識し、指定fileの内容を読み取った結果です。

4条件20回の認証結果は?

DB設定 login 成功 中央値
通常変数にpath secret 0/5 72.722ms
通常変数にpath literal path 5/5 88.772ms
_FILE変数 secret 5/5 66.375ms
_FILE変数 literal path 0/5 86.022ms

20/20回が期待結果と一致しました。Compose secretmount成否と、applicationがどの環境変数をどう解釈するかは別問題です。

docker compose configinspectには何が見えた?

docker compose configdocker inspectraw合成secret0件でした。一方、pathと変数名は確認できました。

inspectsecret値がない」ことと、「applicationが正しいpasswordを使った」ことも別です。raw値が隠れていても、wrong版は意図しないpath文字列をpasswordとして使っていました。

secret filecontainer内で本当に読めた?

DB/run/secrets/db_passwordを調べると、modeUIDGIDsize444 1000 1000 49でした。fileSHA-256も生成時の合成secretと一致しています。

つまり、今回の認証失敗は「fileがない」「mountできない」「hashが違う」ためではありません。application側がfile pathを内容へ変換しなかったことが原因です。

_FILE非対応アプリではどうすればよい?

  1. image公式docsで対象の_FILE変数を確認する。
  2. 対応していればAPP_PASSWORD_FILE=/run/secrets/...を使う。
  3. 非対応ならapplication codesecret fileを直接読む。
  4. 変更できない場合のみ、entrypoint shimfileを読みchild processへ渡す。
  5. 起動後に実際の認証またはAPI requestを行い、path文字列になっていないか検証する。

entrypointで環境変数へ展開すると、child processenvironmentから見える範囲が増えます。fileを直接読む設計のほうが、値を環境変数へ載せずに済みます。

Compose secretSwarm secretは同じ?

実装上の性質は同じではありません。今回使ったDocker Composeは、Docker公式docsの説明どおりhost fileLinux containerへ単一fileとしてbind mountします。

Docker Swarm secretsmanagerの暗号化Raft logcontainerin-memory filesystemを使います。Composesecret syntaxを書いただけでhostsource fileまで自動暗号化されるわけではありません。

実験中にどんな問題が起きた?

初回はpg_isreadyだけでDB開始を判定しました。Official imageは初期化用PostgreSQLを一時起動してからfinal serverへ切り替えるため、その途中のrequestが混ざりました。

開始条件を「PostgreSQL init process completelog」と「最終passwordによるTCP認証成功」の両方へ変更しました。

2回目は異なるpassword候補が両方通り、password比較として無効でした。最終runでは--auth-host=scram-sha-256を明示し、生成されたpg_hba.confの127.0.0.1、::1、all hostSCRAM-SHA-256であることも保存しました。

CPURAM・ストレージへの影響は?

DB data128MiB tmpfsに置きました。数値は2DBの初期化と20回のauthenticationを含み、大規模DB workloadbenchmarkではありません。

本番サービスと後片付けは?

公開/health/readyは開始前、実験中、終了後の全3回でHTTP 200でした。database=okartifact_storage=okも維持しています。

本番CaddyFastAPIPostgreSQLは前後restart 0でした。一時DB 2個、internal networktmpfsを削除し、dangling volumeは前後0件、公開portも0件です。

初心者が迷いそうなポイントは?

XServer VPSでこの悩みはどこまで解決した?

設定方法について解決です。通常変数へpathを入れたPostgreSQLpath自体をpasswordとして受け取り、実secret値で0/5回、pathで5/5回成功しました。POSTGRES_PASSWORD_FILE版は実secret値で5/5回成功し、意図どおり動きました。

すべてのimage_FILEへ対応するわけではありません。また、password rotationSwarmVaultKubernetes Secretは未検証です。image docsentrypointを確認し、起動後の実認証まで自動testに含めます。

よくある質問

Q. Docker secretのpathPASSWORDへ設定すれば中身が入りますか?

A. 入りません。通常はpath文字列がそのまま値になります。applicationfileを読む必要があります。

Q. 変数名へ_FILEを付ければどのimageでも使えますか?

A. 使えません。imageapplicationがその変数を実装している場合だけ動きます。

Q. PostgreSQL Official Imageでは何を使いますか?

A. 今回の17.10ではPOSTGRES_PASSWORD_FILE=/run/secrets/db_passwordで実secret値が使われました。

Q. inspectにsecret値がなければ設定成功ですか?

A. いいえ。wrong版もraw値はinspectにありませんでしたが、path自体をpasswordにしていました。実認証で確認します。

Q. Compose secretはhost上でも暗号化されますか?

A. Composeはsource filecontainermountします。source fileの保存・暗号化・権限管理は別途必要です。

[PR]
XServer VPSの公式情報を確認する

実験日:2026年9月2日。数値は筆者が契約中のXServer VPS 4GB環境における各5回の実測です。Docker Composeimageentrypoint、認証方式により結果は変わります。

コメント

タイトルとURLをコピーしました