源命令无法从入口点/ Dockerfile 中工作
源命令无法从入口点/ Dockerfile 中工作
我有一个Dockerfile文件,用来安装一个普通的Python环境(稍后再安装一个应用程序进去)。
FROM ubuntu:12.04 # required to build certain python libraries RUN apt-get install python-dev -y # install pip - canonical installation instructions from pip-installer.org # http://www.pip-installer.org/en/latest/installing.html ADD https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py /tmp/ez_setup.py ADD https://raw.github.com/pypa/pip/master/contrib/get-pip.py /tmp/get-pip.py RUN python /tmp/ez_setup.py RUN python /tmp/get-pip.py RUN pip install --upgrade pip # install and configure virtualenv RUN pip install virtualenv RUN pip install virtualenvwrapper ENV WORKON_HOME ~/.virtualenvs RUN mkdir -p $WORKON_HOME RUN source /usr/local/bin/virtualenvwrapper.sh
在一直运行到最后一行时,我遇到了以下异常:
[previous steps 1-9 removed for clarity] ... Successfully installed virtualenvwrapper virtualenv-clone stevedore Cleaning up... ---> 1fc253a8f860 Step 10 : ENV WORKON_HOME ~/.virtualenvs ---> Running in 8b0145d2c80d ---> 0f91a5d96013 Step 11 : RUN mkdir -p $WORKON_HOME ---> Running in 9d2552712ddf ---> 3a87364c7b45 Step 12 : RUN source /usr/local/bin/virtualenvwrapper.sh ---> Running in c13a187261ec /bin/sh: 1: source: not found
如果我没有任何更改地ls
进入该目录(只是为了测试先前的步骤是否被提交),我可以看到文件按预期存在:
$ docker run 3a87 ls /usr/local/bin easy_install easy_install-2.7 pip pip-2.7 virtualenv virtualenv-2.7 virtualenv-clone virtualenvwrapper.sh virtualenvwrapper_lazy.sh
如果我只是运行source
命令,我会得到与上面相同的“未找到”的错误。但是如果我运行交互式的shell会话,则source
命令可以工作:
$ docker run 3a87 bash source bash: line 1: source: filename argument required source: usage: source filename [arguments]
我可以从这里运行脚本,然后愉快地访问workon
,mkvirtualenv
等等。
我做了一些挖掘,最初看起来问题可能在于Ubuntu登录shell作为<bash,Ubuntu系统shell作为dash之间的差异,dash不支持source
命令。
然而,解决这个问题的答案似乎是使用source
代替\'.\',但这只会导致Docker运行时出现go panic异常。
有什么最好的方法可以从Dockerfile中的RUN指令运行shell脚本以避免这种情况(我正在运行Ubuntu 12.04 LTS的默认基础图像)。
RUN
指令的默认Shell为["/bin/sh", "-c"]
。
RUN "source file" # translates to: RUN /bin/sh -c "source file"
使用SHELL指令,您可以更改Dockerfile中后续RUN
指令的默认Shell:
SHELL ["/bin/bash", "-c"]
现在,默认Shell已更改,您无需在每个RUN指令中显式定义它。
RUN "source file" # now translates to: RUN /bin/bash -c "source file"
附加说明:您还可以添加--login
选项,这将启动一个登录Shell。这意味着例如~/.bashrc
将被读取,您不需要在命令之前显式引用它。
原始答案
FROM ubuntu:14.04 RUN rm /bin/sh && ln -s /bin/bash /bin/sh
对于每个Ubuntu Docker基本镜像,这应该都可以运行。我一般为我编写的每个Dockerfile添加这一行。
由一位关心的旁观者编辑
如果你想要获得“在整个Dockerfile中使用bash
而不是sh
的效果”,而不会
SHELL ["/bin/bash", "-c"]
*可能的危害是在Linux(在一个新的Ubuntu安装中,
grep -rHInE '/bin/sh' /
返回超过2700个结果)中,许多脚本期望在/bin/sh
中拥有一个完全的POSIX shell。bash shell不仅仅是POSIX加上额外的内置。有一些内置(以及更多),它们的行为完全不同于POSIX。我完全支持避免POSIX(以及任何你没有在另一个shell上测试的脚本,因为你认为你避免了basmisms的谬论),只使用bashism。但是你需要在你的脚本中有一个正确的shebang命令来做到这一点,而不是在整个操作系统底下拔掉POSIX shell。(除非你有时间验证Linux中随附的所有2700多个脚本以及你安装的任何程序包中的所有脚本。)
在以下答案中有更多详细信息。https://stackoverflow.com/a/45087082/117471