如何在 Dockerfile 中使用命令替换

Tho*_*lik 9 command-substitution dockerfile

在我的 Dockerfile 中,我需要使用命令替换来添加一些环境变量。我想设置

ENV PYTHONPATH /usr/local/$(python3 -c 'from distutils import sysconfig; print(sysconfig.get_python_lib())')
Run Code Online (Sandbox Code Playgroud)

但它不起作用。结果是

foo@bar:~$ echo $PYTHONPATH
/usr/local/$(python3 -c from distutils import sysconfig; print(sysconfig.get_python_lib()))
Run Code Online (Sandbox Code Playgroud)

怎么了?

cla*_*123 5

什么地方出了错

您尝试的命令$( ... ) 替换适用于 Bash,而 Dockerfile 不是 Bash。所以 docker 不知道该怎么做,这对 docker 来说只是纯文本,docker 只是按原样输出你写的内容。

推荐

PYTHONPATH为了避免将值硬编码到 Dockerfile 中,而是在构建过程中动态更改设置或自定义变量,ARG ...也许--build-argdocker 功能可能是最有帮助的,结合使用ENV ...以确保其持续存在。

在您的 Dockerfile 中:

ARG PYTHON_PATH_ARG

ENV PYTHONPATH ${PYTHON_PATH_ARG}
Run Code Online (Sandbox Code Playgroud)

在构建容器的 Bash 中:

ARG PYTHON_PATH_ARG

ENV PYTHONPATH ${PYTHON_PATH_ARG}
Run Code Online (Sandbox Code Playgroud)

解释

根据文件,ARG

ARG指令定义了一个变量,用户可以使用该标志在构建时通过 docker build 命令将其传递给构建器--build-arg <varname>=<value>

因此,在 Bash 中我们首先:

python_path="/usr/local$(python3 -c 'from distutils import sysconfig; print(sysconfig.get_python_lib())')"
Run Code Online (Sandbox Code Playgroud)
  • $(...)Bash 命令替换用于动态组合 Python 路径值
  • $python_path为了清楚起见,该值临时存储在 Bash 变量中
docker build --build-arg PYTHON_PATH_ARG=$python_path .
Run Code Online (Sandbox Code Playgroud)
  • Bash 变量$python_path值传递给 docker 的--build-arg PYTHON_PATH_ARG

在 Dockerfile 中:

ARG PYTHON_PATH_ARG
Run Code Online (Sandbox Code Playgroud)
  • 所以PYTHON_PATH_ARG存储来自的值--build-arg PYTHON_PATH_ARG...

ARG变量不等于ENV变量,所以我们不能仅仅用它来做事ARG PYTHONPATH和完成它。根据有关使用 arg 变量的文档:

ARG变量不会像变量那样持久保存到构建的映像中ENV

所以最后:

ENV PYTHONPATH ${PYTHON_PATH_ARG}
Run Code Online (Sandbox Code Playgroud)
  • 我们使用 Dockerfile 的${...}约定来获取 的值PYTHON_PATH_ARG,并将其保存到您最初命名的PYTHONPATH环境变量中

与原始代码的差异

您最初写道:

ENV PYTHONPATH /usr/local/$(python3 -c 'from distutils import sysconfig; print(sysconfig.get_python_lib())')
Run Code Online (Sandbox Code Playgroud)

我将Python路径查找部分重写为Bash命令,并在我的机器上进行了测试:

python_path="/usr/local$(python3 -c 'from distutils import sysconfig; print(sysconfig.get_python_lib())')"

docker build --build-arg PYTHON_PATH_ARG=$python_path .
Run Code Online (Sandbox Code Playgroud)

请注意,有一个双正斜杠... local//usr ...,不确定这是否会破坏任何内容,具体取决于您在代码中如何使用它。

相反,我将其更改为:

python_path="/usr/local$(python3 -c 'from distutils import sysconfig; print(sysconfig.get_python_lib())')"
Run Code Online (Sandbox Code Playgroud)

结果:

$ echo $python_path
/usr/local/usr/lib/python3/dist-packages
Run Code Online (Sandbox Code Playgroud)

所以这个新代码将没有双正斜杠。