Dockerコンテナから渡された環境変数の可視性 - 誤解

Dockerコンテナから渡された環境変数の可視性 - 誤解

次の例を見てみましょう。

[user@user~]$ sudo docker run -d -e XYZ=123 ubuntu sleep 10000
2543e7235fa9
[user@user~]$ sudo docker exec 2543e7235fa9 echo test
test
[user@user~]$ sudo docker exec 2543e7235fa9 echo $XYZ
<empty row>      
[user@user~]$ sudo docker exec -it 2543e7235fa9 bash
root@2543e7235fa9:/# echo $XYZ
123

<empty row>代わりになぜ受けますか123? bashを実行して入力した後に表示されるのはなぜですかXYZ=123

ベストアンサー1

ここに欠けている2つのことは次のとおりです。

  1. docker exec ... <command><command>デフォルトでは、シェルで実行されず、シェル<command>なしでコンテナでのみ実行されます。

    非対話型シェルの docker でコマンドを実行するには、次のようにします。

    docker exec <container> bash -c '<command>'
    

    複数の単語がある場合は、<command>コマンド全体を一重引用符または二重引用符で囲んで渡す必要がありますbash -c

    例えばsudo docker exec 2543e7235fa9 bash -c 'echo $XYZ'

 

  1. これを行うには、2つのシェルを持つことが重要です。

    • 実行中のシェルsudo docker exec ...(「Shell A」と呼ばれる)
    • コンテナ内で実行されるシェル(「シェルB」と呼ばれる)

     

    もしあなたならいいえシェルAのバックスラッシュエスケープまたは一重引用符$とシェルAは独自の値を挿入します$XYZ(値がなくても空の文字列を返します)。

    したがってXYZ=5、シェルAにいる場合、あなたのシェルsudo docker exec 2543e7235fa9 echo $XYZはと同じですexec 2543e7235fa9 echo 5(dockerにrunを指示しなかったため、シェルBもありませんbash -c ...)。

    もしあなたならするエスケープまたは一重引用符を使用して$それをそのままシェルBに渡し、シェルBはその値を挿入します$XYZ

つまり、次を使用します。

sudo docker exec 2543e7235fa9 bash -c 'echo $XYZ'

または

sudo docker exec 2543e7235fa9 bash -c "echo \$XYZ"

私の考えでは、一重引用符形式が何をしているのか、そしてほとんどの場合使用する必要があることを理解するのは簡単です。一重引用符内では変数の補間は発生しないため、コマンドはシェルBと同じように渡されます。

二重引用符形式は、シェルAからシェルBに変数を渡す必要がある場合に便利です。リテラルも渡す必要がある場合は、$バックスラッシュエスケープを使用する必要があります。たとえば、シェルB echoシェルA$ABCとそれ自体があります$XYZ

sudo docker exec 2543e7235fa9 bash -c "echo $ABC \$XYZ"

シェルA$ABCが123で10シェルB$XYZが123の場合、出力は次のようになります。

10 123

$XYZ注:シェルBの開始ファイルの1つに定義されていない場合、またはdocker run -e XYZ=123例で使用されている(または使用されていない-env-file)場合以外は値はありません。

おすすめ記事