在我的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()))
怎么了?
答案 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路径值$python_path
中docker build --build-arg PYTHON_PATH_ARG=$python_path .
$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}
${...}
约定来获取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