我有一个如下的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 npm@5.6.0
ADD ./Docker/launch.sh /workspace/
CMD ["/bin/sh", "/workspace/launch.sh"]
Run Code Online (Sandbox Code Playgroud)
的内容launch.sh是:
#!/bin/bash
cd /workspace/demo
npm install
node index.js
Run Code Online (Sandbox Code Playgroud)
当我运行docker container:时docker run IMAGE_NAME,出现以下错误:
npm: not found
node: not found
Run Code Online (Sandbox Code Playgroud)
在node此图像中设法通过nvm已安装和脚本的设置/root/.bashrc文件。但是我不知道为什么找不到nodejs命令。但是,如果我通过运行容器docker run -it IMAGE_NAME bash,然后手动运行workspace/launch.sh命令,则一切正常。似乎~/.bashrc在运行映像时未执行。如何让容器源.bashrc?
的内容/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)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[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
Run Code Online (Sandbox Code Playgroud)
Chu*_*son 30
现有的答案都没有准确回答标题问题:为什么~/.bashrc运行docker容器时不执行?
有两点需要注意:
根据bash手册页:
当bash作为交互式登录 shell 或带有--login 选项的非交互式 shell 被调用时,它首先从文件/etc/profile中读取并执行命令(如果该文件存在)。读取该文件后,它会按顺序查找~/.bash_profile、~/.bash_login和~/.profile,并从第一个存在且可读的文件中读取并执行命令。启动 shell 时可以使用--noprofile选项来禁止此行为。
因此,为了在调用 时自动读取.profile/ ,需要使用or选项进行调用。.bashrcbashbash--login-l
您可以通过以下几种方式来做到这一点:
1. 设置 shell 包含-l选项。例如,
SHELL ["/bin/bash", "-l", "-c"]
Run Code Online (Sandbox Code Playgroud)
2.-l使用RUN 的 exec 形式调用特定命令:
CMD ["/bin/bash", "-l", "-c", "/workspace/launch.sh"]
Run Code Online (Sandbox Code Playgroud)
.bashrc从上面的手册页中,我们知道搜索和加载配置文件的顺序。如果你看一下,/root/.profile你可能会看到这样的东西:
# ~/.profile: executed by Bourne-compatible login shells.
if [ "$BASH" ]; then
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
fi
mesg n 2> /dev/null || true
Run Code Online (Sandbox Code Playgroud)
这就是~/.bashrc获取bashshell 源的方法。因此,我们可以期望在使用shell~/.bashrc时进行采购。bash
但是,请仔细查看文件顶部附近.bashrc:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Run Code Online (Sandbox Code Playgroud)
这意味着除了交互式shell 之外,其余内容实际上都.bashrc被忽略。
一个答案建议使用调用交互式 shell-i的选项。bash这确实有效,因为环境变量PS1是为交互式 shell 设置的,因此.bashrc会继续。
但是,也许您不需要交互式 shell。在这种情况下,有以下几种选择:
1. 注释掉返回行。您可以在您的Dockerfile:
RUN sed -e '/[ -z "$PS1" ] && return/s/^/#/g' -i /root/.bashrc
Run Code Online (Sandbox Code Playgroud)
此修改将.bashrc防止其从非交互式调用中提前退出。
2. Move the nvm setup to .profile. Move the last three lines of your .bashrc file to .profile so they're executed unconditionally.
3. Manually source .bashrc. As other answers have already noted, you can certainly manually source .bashrc as needed, as in,
RUN source /root/.bashrc && /workspace/launch.sh
Run Code Online (Sandbox Code Playgroud)
Observe that much of the content of .bashrc makes the most sense for interactive shells and is usually unnecessary otherwise, which may make option 2 above the most appealing.
Szy*_*zke 12
每个命令都运行一个单独的子 shell,因此环境变量不会被保留并且.bashrc没有来源(请参阅此答案)。
您必须在运行命令的同一过程中手动获取脚本,因此它将是:
CMD source /root/.bashrc && /workspace/launch.sh
Run Code Online (Sandbox Code Playgroud)
前提launch.sh是你是一个可执行文件。
根据您使用的文档 exec形式不会调用命令外壳,因此它不会与您的.bashrc.
BASH 不是你的默认 shell,所以
CMD /bin/bash -c "source /root/.bashrc && /workspace/launch.sh"
Run Code Online (Sandbox Code Playgroud)
需要运行您的脚本。如果您希望默认情况下将 shell 设置为 BASH,您可以使用文档中SHELL描述的指令,例如:
SHELL ["/bin/bash", "-c"]
Run Code Online (Sandbox Code Playgroud)
dan*_*eis 10
带有 CMD 和 shell 形式
CMD /bin/bash -i "/workspace/launch.sh"
Run Code Online (Sandbox Code Playgroud)
编辑 还应该与 ENTRYPOINT 一起使用,并使用 exec 形式使用
ENTRYPOINT ["bash","-i","/workspace/entrypoint.sh"]
Run Code Online (Sandbox Code Playgroud)
我相信 -i 标志按预期方式工作,.bashrc 文件按预期使用,其他解决方案对我不起作用,.bashrc 文件从未使用过
解决方案可能并不适合每个人,使用 -i 标志,程序可能会提示用户交互
ps:我使用了 docker create 和 docker start -i "container name"
| 归档时间: |
|
| 查看次数: |
1875 次 |
| 最近记录: |