bash 为什么运行docker容器时不执行`~/.bashrc`?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/55206227/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 17:06:35  来源:igfitidea点击:

Why `~/.bashrc` is not executed when run docker container?

bashshelldocker

提问by Joey Yi Zhao

I have a docker file as below. launch.shis the entry point in this docker image.

我有一个 docker 文件,如下所示。launch.sh是这个 docker 镜像的入口点。

FROM ubuntu:16.04
USER root

RUN apt-get update && apt-get install -y \
        curl \
        vim \
        net-tools \
        git \
        iputils-ping \
        wget

RUN apt-get install -y python
RUN apt-get update && apt-get install -y gcc g++ make libgflags-dev libsnappy-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev

RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash

ENV NVM_DIR /root/.nvm
RUN . $NVM_DIR/nvm.sh && \
  nvm install 7.9.0 && npm install -g [email protected]

ADD ./Docker/launch.sh /workspace/

CMD ["/bin/sh", "/workspace/launch.sh"]

The content of launch.shis:

内容launch.sh为:

#!/bin/bash

cd /workspace/demo
npm install
node index.js

when I run the docker container: docker run IMAGE_NAME, I got this error:

当我运行 docker container: 时docker run IMAGE_NAME,出现此错误:

npm: not found
node: not found

The nodein this image is managed by nvmwhich has been installed and its script has been set on /root/.bashrcfile. But I don't know why it can't find the nodejs commands. But if I run the container by docker run -it IMAGE_NAME bash, then manually run workspace/launch.shcommand, everything works fine. It seems the ~/.bashrcis not executed when run the image. How can I let the container source .bashrc?

node此图像中设法通过nvm已安装和脚本的设置/root/.bashrc文件。但是我不知道为什么它找不到nodejs命令。但是如果我通过 运行容器docker run -it IMAGE_NAME bash,然后手动运行workspace/launch.sh命令,一切正常。~/.bashrc运行图像时似乎没有执行。我怎样才能让容器来源 .bashrc?

The content of /root/.bashrcis:

内容/root/.bashrc为:

# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

# don't put duplicate lines in the history. See bash(1) for more options
# ... or force ignoredups and ignorespace
HISTCONTROL=ignoredups:ignorespace

# append to the history file, don't overwrite it
shopt -s histappend

# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000

# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize

# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"

# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
    debian_chroot=$(cat /etc/debian_chroot)
fi

# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
    xterm-color) color_prompt=yes;;
esac

# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes

if [ -n "$force_color_prompt" ]; then
    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
    # We have color support; assume it's compliant with Ecma-48
    # (ISO/IEC-6429). (Lack of such support is extremely rare, and such
    # a case would tend to support setf rather than setaf.)
    color_prompt=yes
    else
    color_prompt=
    fi
fi

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[3[01;32m\]\u@\h\[3[00m\]:\[3[01;34m\]\w\[3[00m\]$ '
else
    PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w$ '
fi
unset color_prompt force_color_prompt

# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
    PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
    ;;
*)
    ;;
esac

# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
    alias ls='ls --color=auto'
    #alias dir='dir --color=auto'
    #alias vdir='vdir --color=auto'

    alias grep='grep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias egrep='egrep --color=auto'
fi

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.

if [ -f ~/.bash_aliases ]; then
    . ~/.bash_aliases
fi

# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
#if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
#    . /etc/bash_completion
#fi

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

采纳答案by Szymon Maszke

Each command runs a separate sub-shell, so the environment variables are not preserved and .bashrcis not sourced (see this answer).

每个命令都运行一个单独的子 shell,因此环境变量不会被保留并且.bashrc没有来源(请参阅此答案)。

You have to source your script manually in the same processwhere you run your command so it would be:

您必须在运行命令的同一过程中手动获取脚本因此它将是:

CMD source /root/.bashrc && /workspace/launch.sh

provided your launch.shis an executable.

前提launch.sh是你是一个可执行文件。

As per documentationexecform you are using does not invoke a command shell, so it won't work with your .bashrc.

根据您使用的文档exec形式不会调用命令外壳,因此它不适用于您的.bashrc.

Edit:

编辑:

BASH wasn't your default shell so

BASH 不是你的默认 shell,所以

CMD /bin/bash -c "source /root/.bashrc && /workspace/launch.sh"

was needed in order to run your script. If you want yo set your shell as BASH by default, you can use SHELLinstruction as described in documentation, e.g.:

需要运行您的脚本。如果您希望默认情况下将 shell 设置为 BASH,您可以使用文档中SHELL描述的指令,例如:

SHELL ["/bin/bash", "-c"]

回答by Mostafa Hussein

You can add source /path/to/bashrcin launch.shand change the CMDto the following instead of changing to bash through CMDitself:

您可以添加source /path/to/bashrclaunch.sh并更改CMD为以下,而不是通过改变来砸CMD自己:

CMD ["/workspace/launch.sh"]

Alternatively, You can do the following in your Dockerfile instead of depending on bashrc

或者,您可以在 Dockerfile 中执行以下操作,而不是依赖于 bashrc

ENV NVM_DIR /root/.nvm
ENV NODE_VERSION 7.9.0
ENV NODE_PATH $NVM_DIR/v$NODE_VERSION/lib/node_modules #Ensure that this is the actual path
ENV PATH $NVM_DIR/versions/node/v$NODE_VERSION/bin:$PATH
RUN . $NVM_DIR/nvm.sh && \
  nvm install $NODE_VERSION && npm install -g [email protected]