子プロセスとしてエクスポートされたインライン宣言/定義環境変数と、すでに存在するか継承されている環境変数を区別したいと思います。
$ export NODEJS=8
$ FU=BAR sh -c 'echo $FU $NODEJS'
具体的なユースケースはcmdラッパー/デコレータです。カプセル化コンテナ使用量(これは単なる例です)。
/tmp $ cat ./go.sh
#!/bin/sh
set -eu
docker run \
--rm \
--volume $PWD:/opt/main \
--workdir /opt/main \
golang:1.15 go "${@--h}"
/tmp $ go version
go version go1.15.5 darwin/amd64
/tmp $ mkdir -p /tmp/bin
/tmp $ ln -sf /tmp/go.sh /tmp/bin/go
/tmp $ chmod +x /tmp/go.sh
/tmp $ PATH=/tmp/bin:$PATH
/tmp $ go version
Unable to find image 'golang:1.15' locally
1.15: Pulling from library/golang
756975cb9c7e: Pull complete
d77915b4e630: Pull complete
5f37a0a41b6b: Pull complete
96b2c1e36db5: Pull complete
145393847161: Pull complete
3f8843661db9: Pull complete
218d240e42d4: Pull complete
Digest: sha256:0edb8df3d92a2ccf84d3245c8b0cc31edd6d23f9c3da3e07c8e2bd96eea34547
Status: Downloaded newer image for golang:1.15
go version go1.15.6 linux/amd64
上記のラッパースクリプトのエンドユーザーがDarwinホストで呼び出すかコンテナから呼び出すか、インターフェイスや期待に違いがあってはならないので、カプセル化を強調します。これは、次の空の環境がないことを意味します。
/tmp $ env -i FU=BAR sh -c 'echo $FU $NODEJS'
BAR
環境変数をDockerランタイムに渡すには、次のようにします。
$ cat <<eof | head -n3
> docker run \
> --rm \
> --volume $PWD:/opt/main \
> --workdir /opt/main \
> $( env -0 | xargs -0 -L1 printf '--env "%s"\n' ) \
> golang:1.15 go "${@--h}"
> eof
docker run --rm --volume /tmp:/opt/main --workdir /opt/main --env "TERM_PROGRAM=Apple_Terminal"
--env "SHELL=/bin/bash"
--env "TERM=xterm-256color"
...
これは、シェルオペレーティング環境(例えば、umなど)を無視すると大きな混乱を招く可能性があります。 ENVSなどの追加マニフェストを使用して使用したい環境をホワイトリストに追加できますが、これはさまざまな理由で問題になりますSHELL
。PATH
$ cat /tmp/go.sh
#!/bin/sh
set -eu
cat <<eof
docker run \
--rm \
--volume $PWD:/opt/main \
--workdir /opt/main \
$( echo $ENVS | xargs -n1 -- sh -c 'printf -- "--env %s=%s\n" $1 ${!1}' _) \
golang:1.15 go "${@--h}"
eof
$ ENVS="FU NODEJS" FU=BAR /tmp/go.sh
docker run --rm --volume /tmp:/opt/main --workdir /opt/main --env FU=BAR
--env NODEJS=8 golang:1.15 go "-h"
第一に、本当に混乱しており、第二に、ラッパーの予想動作が基本ターゲットの予想動作と一致しなければならないという原則に違反します。以下のようにgoコマンドにenvを渡しましたが、うまくいきませんENVS
。
# fails to build appropriately targeted binary, but doesn't fail to build
$ GOOS=linux GOARCH=ppc64 go build
# this makes me mad
$ ENVS="GOOS GOARCH" GOOS=linux GOARCH=ppc64 go build
明らかなハードコーディングに加えて、この問題を解決する他の方法があるかどうかはわかりませんが、過度に賢くて簡潔なものがあれば見たいです。