Bash 在带有';来源';不起作用
我有一个Dockerfile,我正在组装它来安装一个普通的python环境(我将在其中安装一个应用程序,但稍后会安装) 构建运行正常,直到最后一行,在那里我得到以下异常:Bash 在带有';来源';不起作用,bash,shell,docker,Bash,Shell,Docker,我有一个Dockerfile,我正在组装它来安装一个普通的python环境(我将在其中安装一个应用程序,但稍后会安装) 构建运行正常,直到最后一行,在那里我得到以下异常: [previous steps 1-9 removed for clarity] ... Successfully installed virtualenvwrapper virtualenv-clone stevedore Cleaning up... ---> 1fc253a8f860 Step 10 : ENV
[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
命令,我会得到与上面相同的“notfound”错误。但是,如果我运行交互式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不支持源代码命令
然而,答案似乎是使用'。而不是源代码,但这只会导致Docker运行时爆发go panic异常
从Dockerfile运行指令运行shell脚本的最佳方法是什么(我运行的是Ubuntu12.04 LTS的默认基本映像)。这可能是因为source
是bash的内置程序,而不是文件系统中的二进制程序。您是否打算让您正在寻找的脚本在以后更改容器?这可能是因为source
是bash的内置组件,而不是文件系统中的二进制文件。您是否打算让您正在寻找的脚本在以后更改容器?编辑:我的答案过时了。我认为另一个答案更好
运行/bin/bash-c“source/usr/local/bin/virtualenvwrapper.sh”编辑:我的答案过时了。我认为另一个答案更好
运行/bin/bash-c“source/usr/local/bin/virtualenvwrapper.sh”原始答案
这应该适用于每个Ubuntu docker基本映像。我通常为我编写的每个Dockerfile添加这一行
由关心的旁观者编辑
如果您想在整个Dockerfile中获得“使用bash
而不是sh
”的效果,而不改变和可能损坏容器内的操作系统,您可以。就是这样做的:
SHELL ["/bin/bash", "-c"]
*可能的损害是,Linux中的许多脚本(在新安装的Ubuntu上grep-rHInE'/bin/sh'/
返回超过2700个结果)希望在/bin/sh
上使用完全的POSIX shell。bashshell不仅仅是POSIX加上额外的内置组件。有一些内置(以及更多)的行为与POSIX中的完全不同。我完全支持避免POSIX(以及一种谬论,即您没有在另一个shell上测试的任何脚本都会工作,因为您认为您避免了Basmism),而只是使用bashism。但你要在剧本中加入一个恰当的“shebang”。而不是从整个操作系统下拉出POSIX外壳。(除非您有时间验证Linux附带的所有2700多个脚本以及您安装的任何软件包中的所有脚本。)
更多细节请参见下面的回答 原始答案
这应该适用于每个Ubuntu docker基本映像。我通常为我编写的每个Dockerfile添加这一行
由关心的旁观者编辑
如果您想在整个Dockerfile中获得“使用bash
而不是sh
”的效果,而不改变和可能损坏容器内的操作系统,您可以。就是这样做的:
SHELL ["/bin/bash", "-c"]
*可能的损害是,Linux中的许多脚本(在新安装的Ubuntu上grep-rHInE'/bin/sh'/
返回超过2700个结果)希望在/bin/sh
上使用完全的POSIX shell。bashshell不仅仅是POSIX加上额外的内置组件。有一些内置(以及更多)的行为与POSIX中的完全不同。我完全支持避免POSIX(以及一种谬论,即您没有在另一个shell上测试的任何脚本都会工作,因为您认为您避免了Basmism),而只是使用bashism。但你要在剧本中加入一个恰当的“shebang”。而不是从整个操作系统下拉出POSIX外壳。(除非您有时间验证Linux附带的所有2700多个脚本以及您安装的任何软件包中的所有脚本。)
更多细节请参见下面的回答 我也遇到了同样的问题,为了在virtualenv内部执行pip安装,我必须使用以下命令:
RUN pip install virtualenv virtualenvwrapper
RUN mkdir -p /opt/virtualenvs
ENV WORKON_HOME /opt/virtualenvs
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh \
&& mkvirtualenv myapp \
&& workon myapp \
&& pip install -r /mycode/myapp/requirements.txt"
我希望它能有所帮助。我也遇到了同样的问题,为了在virtualenv内部执行pip安装,我必须使用以下命令:
RUN pip install virtualenv virtualenvwrapper
RUN mkdir -p /opt/virtualenvs
ENV WORKON_HOME /opt/virtualenvs
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh \
&& mkvirtualenv myapp \
&& workon myapp \
&& pip install -r /mycode/myapp/requirements.txt"
我希望它能有所帮助。您可能需要运行bash-v
来查看源代码
我将执行以下操作,而不是使用符号链接:
运行echo“source/usr/local/bin/virtualenvwrapper.sh”>/etc/bash.bashrc
您可能需要运行bash-v
来查看源代码
我将执行以下操作,而不是使用符号链接:
运行echo“source/usr/local/bin/virtualenvwrapper.sh”>>/etc/bash.bashrc
基于本页的答案,我想补充一点,您必须知道,每个RUN语句都使用/bin/sh-c
独立于其他语句运行,因此不会获得通常在登录shell中来源的任何环境变量
到目前为止,我找到的最好的方法是将脚本添加到/etc/bash.bashrc
,然后作为bash登录调用每个命令
RUN echo "source /usr/local/bin/virtualenvwrapper.sh" >> /etc/bash.bashrc
RUN /bin/bash --login -c "your command"
例如,您可以安装和设置VirtualEnvRapper,创建虚拟环境,在使用bash登录时激活它,然后将python模块安装到此环境中:
RUN pip install virtualenv virtualenvwrapper
RUN mkdir -p /opt/virtualenvs
ENV WORKON_HOME /opt/virtualenvs
RUN echo "source /usr/local/bin/virtualenvwrapper.sh" >> /etc/bash.bashrc
RUN /bin/bash --login -c "mkvirtualenv myapp"
RUN echo "workon mpyapp" >> /etc/bash.bashrc
RUN /bin/bash --login -c "pip install ..."
阅读上的手册有助于了解什么是源代码。在answ上构建
RUN source /usr/local/bin/virtualenvwrapper.sh
RUN . /usr/local/bin/virtualenvwrapper.sh
RUN cd ansible && source ./hacking/env-setup
RUN echo "source /ansible/hacking/env-setup" >> /tmp/setup
RUN /bin/bash -C "/tmp/setup"
RUN rm -f /tmp/setup
RUN ["/bin/bash", "-c", "echo hello"]
RUN "source file" # translates to: RUN /bin/sh -c "source file"
SHELL ["/bin/bash", "-c"]
RUN "source file" # now translates to: RUN /bin/bash -c "source file"
SHELL ["/bin/bash", "-c"]
SHELL ["/bin/bash", "-c", "source /usr/local/bin/virtualenvwrapper.sh"]
SHELL ["executable", "parameters"]
FROM microsoft/windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello
...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...
# escape=`
FROM microsoft/nanoserver
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'
PS E:\docker\build\shell> docker build -t shell .
Sending build context to Docker daemon 4.096 kB
Step 1/5 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/5 : SHELL powershell -command
---> Running in 6fcdb6855ae2
---> 6331462d4300
Removing intermediate container 6fcdb6855ae2
Step 3/5 : RUN New-Item -ItemType Directory C:\Example
---> Running in d0eef8386e97
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/28/2016 11:26 AM Example
---> 3f2fbf1395d9
Removing intermediate container d0eef8386e97
Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\
---> a955b2621c31
Removing intermediate container b825593d39fc
Step 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world'
---> Running in be6d8e63fe75
hello world
---> 8e559e9bf424
Removing intermediate container be6d8e63fe75
Successfully built 8e559e9bf424
PS E:\docker\build\shell>
RUN ["/bin/bash", "-c", "source /usr/local/bin/virtualenvwrapper.sh"]
# don't do this...
RUN /bin/bash -c "source /usr/local/bin/virtualenvwrapper.sh"
# because it is the same as this...
RUN ["/bin/sh", "-c", "/bin/bash" "-c" "source /usr/local/bin/virtualenvwrapper.sh"]
SHELL ["/bin/bash", "-c"]
SHELL ["/bin/bash", "-c", "-l"]
# Install ruby version specified in .ruby-version
RUN rvm install $(<.ruby-version)
# Install deps
RUN rvm use $(<.ruby-version) && gem install bundler && bundle install
CMD rvm use $(<.ruby-version) && ./myscript.rb
ENTRYPOINT ["bash", "--rcfile", "/usr/local/bin/virtualenvwrapper.sh", "-ci"]
## Conda with custom entrypoint from base ubuntu image
## Build with e.g. `docker build -t monoconda .`
## Run with `docker run --rm -it monoconda bash` to drop right into
## the environment `foo` !
FROM ubuntu:18.04
## Install things we need to install more things
RUN apt-get update -qq &&\
apt-get install -qq curl wget git &&\
apt-get install -qq --no-install-recommends \
libssl-dev \
software-properties-common \
&& rm -rf /var/lib/apt/lists/*
## Install miniconda
RUN wget -nv https://repo.anaconda.com/miniconda/Miniconda3-4.7.12-Linux-x86_64.sh -O ~/miniconda.sh && \
/bin/bash ~/miniconda.sh -b -p /opt/conda && \
rm ~/miniconda.sh && \
/opt/conda/bin/conda clean -tipsy && \
ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh
## add conda to the path so we can execute it by name
ENV PATH=/opt/conda/bin:$PATH
## Create /entry.sh which will be our new shell entry point. This performs actions to configure the environment
## before starting a new shell (which inherits the env).
## The exec is important! This allows signals to pass
RUN (echo '#!/bin/bash' \
&& echo '__conda_setup="$(/opt/conda/bin/conda shell.bash hook 2> /dev/null)"' \
&& echo 'eval "$__conda_setup"' \
&& echo 'conda activate "${CONDA_TARGET_ENV:-base}"' \
&& echo '>&2 echo "ENTRYPOINT: CONDA_DEFAULT_ENV=${CONDA_DEFAULT_ENV}"' \
&& echo 'exec "$@"'\
) >> /entry.sh && chmod +x /entry.sh
## Tell the docker build process to use this for RUN.
## The default shell on Linux is ["/bin/sh", "-c"], and on Windows is ["cmd", "/S", "/C"]
SHELL ["/entry.sh", "/bin/bash", "-c"]
## Now, every following invocation of RUN will start with the entry script
RUN conda update conda -y
## Create a dummy env
RUN conda create --name foo
## I added this variable such that I have the entry script activate a specific env
ENV CONDA_TARGET_ENV=foo
## This will get installed in the env foo since it gets activated at the start of the RUN stanza
RUN conda install pip
## Configure .bashrc to drop into a conda env and immediately activate our TARGET env
RUN conda init && echo 'conda activate "${CONDA_TARGET_ENV:-base}"' >> ~/.bashrc
ENTRYPOINT ["/entry.sh"]
[mlazo@srvjenkins project_textile]$ cat docker/Dockerfile.debug
FROM malazo/project_textile_ubuntu:latest
ENV PROJECT_DIR=/proyectos/project_textile PROJECT_NAME=project_textile WRAPPER_PATH=/usr/share/virtualenvwrapper/virtualenvwrapper.sh
COPY . ${PROJECT_DIR}/
WORKDIR ${PROJECT_DIR}
RUN echo "source ${WRAPPER_PATH}" > ~/.bashrc
SHELL ["/bin/bash","-c","-l"]
RUN mkvirtualenv -p $(which python3) ${PROJECT_NAME} && \
workon ${PROJECT_NAME} && \
pip3 install -r requirements.txt
EXPOSE 8000
ENTRYPOINT ["tests/container_entrypoint.sh"]
CMD ["public/manage.py","runserver","0:8000"]
[mlazo@srvjenkins project_textile]$ cat tests/container_entrypoint.sh
#!/bin/bash
# *-* encoding : UTF-8 *-*
sh tests/deliver_env.sh
source ~/.virtualenvs/project_textile/bin/activate
exec python "$@"
[mlazo@srvjenkins project_textile]$ cat ./tests/container_deployment.sh
#!/bin/bash
CONT_NAME="cont_app_server"
IMG_NAME="malazo/project_textile_app"
[ $(docker ps -a |grep -i ${CONT_NAME} |wc -l) -gt 0 ] && docker rm -f ${CONT_NAME}
docker run --name ${CONT_NAME} -p 8000:8000 -e DEBUG=${DEBUG} -e MYSQL_USER=${MYSQL_USER} -e MYSQL_PASSWORD=${MYSQL_PASSWORD} -e MYSQL_HOST=${MYSQL_HOST} -e MYSQL_DATABASE=${MYSQL_DATABASE} -e MYSQL_PORT=${MYSQL_PORT} -d ${IMG_NAME}