无法将环境变量传递给容器
Unable to pass the env variable to container
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine
ENV CORECLR_ENABLE_PROFILING=1 \
CORECLR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8} \
CORECLR_PROFILER_PATH=/opt/datadog/Datadog.Trace.ClrProfiler.Native.so \
DD_INTEGRATIONS=/opt/datadog/integrations.json \
DD_DOTNET_TRACER_HOME=/opt/datadog
WORKDIR /app
RUN apk --no-cache update \
&& apk add bash make curl
ARG TRACER_VERSION=1.19.1
RUN mkdir -p /opt/datadog
RUN curl -L https://github.com/DataDog/dd-trace-dotnet/releases/download/v${TRACER_VERSION}/datadog-dotnet-apm-${TRACER_VERSION}.tar.gz \
| tar xzf - -C /opt/datadog
WORKDIR /app
COPY --from=buildcontainer /app/build .
COPY ./Entrypoint.sh /
RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
ENTRYPOINT ["dotnet","testdatadog.dll"]
Entrypoint.sh
#!/bin/bash
set -e
curl http://169.254.169.254/latest/meta-data/local-ipv4 > temp_var
export DD_AGENT_HOST=$(cat temp_var)
exec "$@"
当我通过 ssh 进入我的 ec2 并查看环境变量时,我没有看到 DD_AGENT_HOST 集。当我手动尝试设置 env 时它起作用了。我错过了什么吗?感谢输入。
这个:
RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
实际上 运行 是以下命令:
bash -c "chmod +x /Entrypoint.sh && /Entrypoint.sh"
您的脚本为 运行 所在的 Bash 实例设置环境变量,该实例在脚本完成后立即退出,丢弃其环境。
您需要将 Entrypoint.sh
的执行移动到 ENTRYPOINT 行。
编辑:
所以这是我的测试Dockerfile
(请注意,复制和更改脚本的权限是在单独的阶段完成的,以减小最终图像的大小):
FROM alpine:latest AS build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
FROM alpine:latest
RUN apk add --no-cache bash
COPY --from=build /entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh", "sleep", "10m" ]
和entrypoint.sh
:
#!/bin/bash
set -e
echo "127.0.0.1" > temp_var
export DD_AGENT_HOST=$(cat temp_var)
exec "$@"
我运行以下命令:
docker build -t entrypoint-test .
docker run -itd --rm --name entrypoint entrypoint-test:latest
docker exec -it entrypoint bash
和里面新开的Bashshell:
export
结果:
declare -x HOME="/root"
declare -x HOSTNAME="c951e699bf7b"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/"
declare -x SHLVL="1"
declare -x TERM="xterm"
没有DD_AGENT_HOST
!
所以我搜索了容器的主进程(在我的例子中 sleep
)
ps -a | grep sleep
得到了
1 root 0:00 sleep 10m
32 root 0:00 grep sleep
最后我运行
strings /proc/1/environ
查看该进程的环境。
结果:
HOSTNAME=3f9760ceb473
PWD=/
HOME=/root
TERM=xterm
SHLVL=0
DD_AGENT_HOST=127.0.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DD_AGENT_HOST
找到了!
发生了什么事?
很简单。 entrypoint.sh
仅为它执行的进程设置变量 - 在我的例子中 sleep
。 docker exec
创建一个新的、不相关的进程 运行ning Bash。由于新进程(在 Linux 和 Windows 中)从父进程继承环境,并且由 docker exec
生成的新 Bash 进程不是子进程(而是容器主进程的兄弟),它不知道 DD_AGENT_HOST
变量。
希望对您有所帮助。
编辑 2:
我相信的意思是你可以替换
ENTRYPOINT [ "/entrypoint.sh", "sleep", "10m" ]
和
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "sleep", "10m" ]
然后你可以运行
docker run -it --rm --name entrypoint entrypoint-test:latest bash
以便 entrypoint.sh
执行 bash
而不是 sleep 10m
,允许您直接检查环境而不是通过 /proc/$pid/environ
。
你的 Dockerfile 中的等价物是:
ENTRYPOINT [ "/Entrypoint.sh" ]
CMD [ "dotnet" , "testdatadog.dll" ]
问题的要点是您的指令 RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
在构建时执行,并且对您的运行时环境没有影响。
Konrad 正确地更改您的 ENTRYPOINT 以 Entrypoint.sh 改变您的环境。
Konrad 解决方案的问题是,他用来启动容器的 run
命令对 docker [=49= 的 bash shell 没有影响] 当他发出 exec
命令时。
稍微扩展 Konrad 的回答,您实际上可以 entrypoint.sh 为您设置环境。
我复制了 Konrad 的 Dockerfile,但将 ENTRYPOINT 更改如下:
FROM alpine:latest AS build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
FROM alpine:latest
RUN apk add --no-cache bash
COPY --from=build /entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh", "bash" ]
现在,entrypoint.sh 将设置环境,并执行 bash
。
我使用 Konrad 的命令 运行 容器:
docker run -itd --rm --name entrypoint entrypoint-test:latest
24a7f3d740c37bb345374a835a465482e3bf49a04361e55205b6d63af48d5c3d
这导致容器被启动。 Entrypoint.sh 将为我们 运行 bash,但它处于守护进程模式,因此我们必须附加到它:
$ docker attach 24a7f3d740c37bb345374a835a465482e3bf49a04361e55205b6d63af48d5c3d
bash-5.0# echo $DD_AGENT_HOST
127.0.0.1
或者,您可以只 运行 docker 图像而不使用 -d
选项,避免守护进程模式:
$ docker run -it --rm --name entrypoint entrypoint-test:latest
bash-5.0# echo $DD_AGENT_HOST
127.0.0.1
bash-5.0# echo Hit Ctrl-P Ctrl-Q to leave this container running
综上所述,这对您的 dotnet 调用有效吗?
ENTRYPOINT [ "/entrypoint.sh", "dotnet" , "testdatadog.dll" ]
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine
ENV CORECLR_ENABLE_PROFILING=1 \
CORECLR_PROFILER={846F5F1C-F9AE-4B07-969E-05C26BC060D8} \
CORECLR_PROFILER_PATH=/opt/datadog/Datadog.Trace.ClrProfiler.Native.so \
DD_INTEGRATIONS=/opt/datadog/integrations.json \
DD_DOTNET_TRACER_HOME=/opt/datadog
WORKDIR /app
RUN apk --no-cache update \
&& apk add bash make curl
ARG TRACER_VERSION=1.19.1
RUN mkdir -p /opt/datadog
RUN curl -L https://github.com/DataDog/dd-trace-dotnet/releases/download/v${TRACER_VERSION}/datadog-dotnet-apm-${TRACER_VERSION}.tar.gz \
| tar xzf - -C /opt/datadog
WORKDIR /app
COPY --from=buildcontainer /app/build .
COPY ./Entrypoint.sh /
RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
ENTRYPOINT ["dotnet","testdatadog.dll"]
Entrypoint.sh
#!/bin/bash
set -e
curl http://169.254.169.254/latest/meta-data/local-ipv4 > temp_var
export DD_AGENT_HOST=$(cat temp_var)
exec "$@"
当我通过 ssh 进入我的 ec2 并查看环境变量时,我没有看到 DD_AGENT_HOST 集。当我手动尝试设置 env 时它起作用了。我错过了什么吗?感谢输入。
这个:
RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
实际上 运行 是以下命令:
bash -c "chmod +x /Entrypoint.sh && /Entrypoint.sh"
您的脚本为 运行 所在的 Bash 实例设置环境变量,该实例在脚本完成后立即退出,丢弃其环境。
您需要将 Entrypoint.sh
的执行移动到 ENTRYPOINT 行。
编辑:
所以这是我的测试Dockerfile
(请注意,复制和更改脚本的权限是在单独的阶段完成的,以减小最终图像的大小):
FROM alpine:latest AS build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
FROM alpine:latest
RUN apk add --no-cache bash
COPY --from=build /entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh", "sleep", "10m" ]
和entrypoint.sh
:
#!/bin/bash
set -e
echo "127.0.0.1" > temp_var
export DD_AGENT_HOST=$(cat temp_var)
exec "$@"
我运行以下命令:
docker build -t entrypoint-test .
docker run -itd --rm --name entrypoint entrypoint-test:latest
docker exec -it entrypoint bash
和里面新开的Bashshell:
export
结果:
declare -x HOME="/root"
declare -x HOSTNAME="c951e699bf7b"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/"
declare -x SHLVL="1"
declare -x TERM="xterm"
没有DD_AGENT_HOST
!
所以我搜索了容器的主进程(在我的例子中 sleep
)
ps -a | grep sleep
得到了
1 root 0:00 sleep 10m
32 root 0:00 grep sleep
最后我运行
strings /proc/1/environ
查看该进程的环境。
结果:
HOSTNAME=3f9760ceb473
PWD=/
HOME=/root
TERM=xterm
SHLVL=0
DD_AGENT_HOST=127.0.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
DD_AGENT_HOST
找到了!
发生了什么事?
很简单。 entrypoint.sh
仅为它执行的进程设置变量 - 在我的例子中 sleep
。 docker exec
创建一个新的、不相关的进程 运行ning Bash。由于新进程(在 Linux 和 Windows 中)从父进程继承环境,并且由 docker exec
生成的新 Bash 进程不是子进程(而是容器主进程的兄弟),它不知道 DD_AGENT_HOST
变量。
希望对您有所帮助。
编辑 2:
我相信
ENTRYPOINT [ "/entrypoint.sh", "sleep", "10m" ]
和
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "sleep", "10m" ]
然后你可以运行
docker run -it --rm --name entrypoint entrypoint-test:latest bash
以便 entrypoint.sh
执行 bash
而不是 sleep 10m
,允许您直接检查环境而不是通过 /proc/$pid/environ
。
你的 Dockerfile 中的等价物是:
ENTRYPOINT [ "/Entrypoint.sh" ]
CMD [ "dotnet" , "testdatadog.dll" ]
问题的要点是您的指令 RUN chmod +x /Entrypoint.sh && /Entrypoint.sh
在构建时执行,并且对您的运行时环境没有影响。
Konrad 正确地更改您的 ENTRYPOINT 以 Entrypoint.sh 改变您的环境。
Konrad 解决方案的问题是,他用来启动容器的 run
命令对 docker [=49= 的 bash shell 没有影响] 当他发出 exec
命令时。
稍微扩展 Konrad 的回答,您实际上可以 entrypoint.sh 为您设置环境。
我复制了 Konrad 的 Dockerfile,但将 ENTRYPOINT 更改如下:
FROM alpine:latest AS build
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
FROM alpine:latest
RUN apk add --no-cache bash
COPY --from=build /entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh", "bash" ]
现在,entrypoint.sh 将设置环境,并执行 bash
。
我使用 Konrad 的命令 运行 容器:
docker run -itd --rm --name entrypoint entrypoint-test:latest
24a7f3d740c37bb345374a835a465482e3bf49a04361e55205b6d63af48d5c3d
这导致容器被启动。 Entrypoint.sh 将为我们 运行 bash,但它处于守护进程模式,因此我们必须附加到它:
$ docker attach 24a7f3d740c37bb345374a835a465482e3bf49a04361e55205b6d63af48d5c3d
bash-5.0# echo $DD_AGENT_HOST
127.0.0.1
或者,您可以只 运行 docker 图像而不使用 -d
选项,避免守护进程模式:
$ docker run -it --rm --name entrypoint entrypoint-test:latest
bash-5.0# echo $DD_AGENT_HOST
127.0.0.1
bash-5.0# echo Hit Ctrl-P Ctrl-Q to leave this container running
综上所述,这对您的 dotnet 调用有效吗?
ENTRYPOINT [ "/entrypoint.sh", "dotnet" , "testdatadog.dll" ]