如何在Dockerfile中使用命令substition

时间:2018-03-22 00:40:08

标签: dockerfile command-substitution

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

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

但它不起作用。结果是

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

怎么了?

2 个答案:

答案 0 :(得分:3)

出了什么问题

您尝试的$( ... ) command substitution用于Bash,而Dockerfile不是Bash。因此,docker不知道如何处理它,它只是docker的纯文本,docker只是喷出你写的那样。

建议

为了避免将值硬编码到Dockerfile中,而是在构建期间动态地将设置或自定义变量更改为PYTHONPATH,可能ARG ...--build-arg泊坞窗功能可能最有帮助的是,与ENV ...结合使用可确保其持续存在。

在您的Dockerfile中:

ARG PYTHON_PATH_ARG

ENV PYTHONPATH ${PYTHON_PATH_ARG}

在构建容器的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 .

说明

根据文件,ARG

  

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

所以,在Bash我们首先:

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

在Dockerfile中:

ARG PYTHON_PATH_ARG
  • 因此PYTHON_PATH_ARG存储--build-arg PYTHON_PATH_ARG...
  • 的值

ARG变量不等同于ENV变量,因此我们不能仅仅执行ARG PYTHONPATH并完成它。根据有关Using arg variables的文档:

  

ARG变量不会持久存储到构建的图像中,因为ENV变量是。

最后:

ENV PYTHONPATH ${PYTHON_PATH_ARG}
  • 我们使用Dockerfile的${...}约定来获取PYTHON_PATH_ARG的值,并将其保存到最初命名的PYTHONPATH环境变量

与原始代码

的差异

你最初写道:

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

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

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

$ echo $python_path
/usr/local//usr/lib/python3/dist-packages

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

相反,我改为:

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

结果:

$ echo $python_path
/usr/local/usr/lib/python3/dist-packages

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

答案 1 :(得分:0)

如果可能,您应该使用ARG。但是有时您确实需要对动态变量使用命令替换。只要将所有命令放在相同的RUN语句中,您仍然可以访问该值。

RUN foo=$(date) && \
    echo $foo