将Shell脚本从Docker获取(“引用”)。

16 浏览
0 Comments

将Shell脚本从Docker获取(“引用”)。

我有一个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

如果我进入该目录(为了测试之前的步骤是否已完成),我可以看到文件已按预期存在:

$ 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是DashDash不支持source命令。

然而,解决方法似乎是使用“。”而不是source,但这会导致Docker运行时爆发go panicking异常。

从Dockerfile的RUN指令运行Shell脚本的最佳方法是什么(我正在运行Ubuntu 12.04 LTS的默认基本映像)?

admin 更改状态以发布 2023年5月23日
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例如将被读取,您不需要在执行命令之前显式的调用source命令。

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个结果)都期望一个完全的POSIX shell在/bin/sh上。Bash shell不仅仅是POSIX加上额外的内置内容。有内置内容(以及更多内容)的行为与POSIX完全不同。我完全支持避免POSIX(和你认为你避免了basmisms的任何脚本的谬论)并只使用bashism。但是,您要通过脚本中的适当shebang来实现这一点。而不是从整个操作系统中提取POSIX shell。(除非您有时间验证所有随Linux附带的2700多个脚本以及任何安装的包中的所有脚本。)

在下面的这个回答中有更多的细节。https://stackoverflow.com/a/45087082/117471

0