源命令无法从入口点/ Dockerfile 中工作

18 浏览
0 Comments

源命令无法从入口点/ 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]

我可以从这里运行脚本,然后愉快地访问workonmkvirtualenv等等。

我做了一些挖掘,最初看起来问题可能在于Ubuntu登录shell作为<bash,Ubuntu系统shell作为dash之间的差异,dash不支持source命令。

然而,解决这个问题的答案似乎是使用source代替\'.\',但这只会导致Docker运行时出现go panic异常。

有什么最好的方法可以从Dockerfile中的RUN指令运行shell脚本以避免这种情况(我正在运行Ubuntu 12.04 LTS的默认基础图像)。

admin 更改状态以发布 2023年5月24日
0
0 Comments

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将被读取,您不需要在命令之前显式引用它。

0
0 Comments

原始答案

FROM ubuntu:14.04
RUN rm /bin/sh && ln -s /bin/bash /bin/sh

对于每个Ubuntu Docker基本镜像,这应该都可以运行。我一般为我编写的每个Dockerfile添加这一行。

由一位关心的旁观者编辑

如果你想要获得“在整个Dockerfile中使用bash而不是sh的效果”,而不会更改可能破坏*容器内的操作系统,你可以告诉Docker你的意图。可以这样做:

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

0