概要
Dockerの環境内で複数の環境変数をセットしたい場合や、特に秘密鍵のような情報を持つ場合は、
通常の方法での取り扱いが難しくなります。この記事では、その問題の原因とその解決策について考えてみました。
まず最初に考えた方法
シェルスクリプトを用いて環境変数を読み込み、それをDocker環境内で利用するためのexportコマンドに変換することを考えました。
cat .env | grep -v ^# | sed 's/^\(.*\)=\(.*\)$/export \1="\2"/g' > export_env.sh
source export_env.sh
rm export_env.sh
しかしこれは秘密鍵のようなマルチラインの環境変数に対応できない問題が発生します。
解決策
解決策
awkを利用して、マルチラインの環境変数も適切に取り扱うスクリプトを考えました
awk 'BEGIN {ORS=""; print "" > "export_env.sh"}
!/^#/ && /=/ {
if ($0 ~ /-----BEGIN/) {
key=$1;
sub(/=.*/, "", key);
printf("export %s=\"", key) > "export_env.sh";
do {
getline;
printf("%s\\n", $0) > "export_env.sh";
} while ($0 !~ /-----END/);
print "\"" > "export_env.sh";
} else {
split($0, a, "=");
printf("export %s=\"%s\"\n", a[1], a[2]) > "export_env.sh";
}
}' .env
解説
BEGINセクション
-
ORS=""デフォルトの行の終わりのセパレータを空文字に設定します。これにより、続く行の出力が新しい行にならないようにする -
print "" > "export_env.sh": 出力ファイルexport_env.shを初期化
パターンに合わせてアクションする
-
!/^#/ && /=/:行が#で始まらない、=を含む行にマッチさせてコメント行や無効な行をフィルタリング
マルチラインの環境変数の処理
-
$0: 現在の行全体を示すAWKの変数 -
~:正規表現マッチングを行うオペレーター、左側の文字列が右側の正規表現にマッチする場合に真を返す -
getline:この関数は、次の行を読み取り、現在の行変数を更新 -
split:文字列を指定したセパレータで分割し、配列にその結果を格納 -
-----BEGINで始まる場合の処理を行い、key=$1とsub(/=.*/, "", key):変数の名前を取得する。do-whileループ:-----ENDが見つかるまでの各行を読み込み、それらを\nでエスケープして連結する。
print "\"" > "export_env.sh":ダブルクォートで値の部分を閉じる。
このスクリプトにより、.envの内容が読み取られ、マルチラインの環境変数を考慮した形でexport_env.shに変換されるようになりました。
そもそも論
- セキュリティ
- 一時ファイルに機密情報を書き出すことはセキュリティ上のリスクがあります。お勧めできる方法ではありません。
- 特定のフォーマットに依存
- このスクリプトは、環境変数が特定のフォーマット(-----BEGINから始まるマルチライン)であることを前提としています。他の形式のマルチライン文字列では正常に動作しない可能性しかない。