为什么我必须在容器内使用 bash -l -c ?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21895523/
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 09:38:35  来源:igfitidea点击:

Why do I have to use bash -l -c inside my container?

linuxbashshelldocker

提问by Hugo Rodger-Brown

I've created a docker container using the following Dockerfile (truncated):

我使用以下 Dockerfile(已截断)创建了一个 docker 容器:

FROM ubuntu:12.04
# curl enables downloading of other things
RUN apt-get install curl -y
# download and install rvm...
RUN \curl -L https://get.rvm.io | bash -s stable
# ... so that we can install ruby
RUN /bin/bash -l -c "rvm requirements"

And so on.

等等。

This all works, but the problem I have is how / where the packages are installed.

这一切都有效,但我遇到的问题是软件包的安装方式/位置。

If I just run rvm using docker run [...] rvmI get "Unable to locate rvm", but if I run docker run [...] /bin/bash -l -c "rvm"it works. (I found the "-l -c" options online, but have no idea what they do, and can't find a satisfactory explanation of what I'm doing!)

如果我只是使用 rvm 运行,docker run [...] rvm我会得到“无法找到 rvm”,但如果我运行docker run [...] /bin/bash -l -c "rvm"它就可以了。(我在网上找到了“-l -c”选项,但不知道它们是做什么的,也找不到对我在做什么的满意解释!)

This isn't a docker question - it's a bash / *nix question - I presume there's something about how / where things are installed, possibly related to running the install under root?

这不是一个 docker 问题——它是一个 bash / *nix 问题——我认为有些东西是关于如何/在哪里安装的,可能与在 root 下运行安装有关?

Just to be clear - I want to be able to run the things that I install direct from the CLI.

只是要清楚 - 我希望能够直接从 CLI 运行我安装的东西。

EDIT 1

编辑 1

Installing Ruby using rvm is the recommended method, however if you want to run things in a non-interactive, non-login shell (i.e. within a docker container), this just causes too much hassle with paths and environment variables and login scripts not running.

使用 rvm 安装 Ruby 是推荐的方法,但是如果您想在非交互式、非登录的 shell(即在 docker 容器中)运行东西,这只会导致路径和环境变量以及未运行的登录脚本太麻烦.

Given that I am using this to run a docker container, which by definition is isolated, and recoverable (just build another one), I don't really care about switching versions, or isolating packages, and so I've decided to install Ruby from a package repo (http://brightbox.com/docs/ruby/ubuntu/) instead. This 'just works'.

鉴于我正在使用它来运行一个 docker 容器,根据定义,该容器是隔离的且可恢复的(只需构建另一个),我并不真正关心切换版本或隔离包,因此我决定安装 Ruby来自包 repo ( http://brightbox.com/docs/ruby/ubuntu/) 代替。这“有效”。

It may not work for you - I am only installing Ruby in order to get the Foreman gem, as I am running an app through a Procfile, so I'm not that fussed about the details, I just need it to work. If you're building a Ruby app, I wouldn't follow my advice.

它可能对你不起作用 - 我只是为了获得 Foreman gem 安装 Ruby,因为我正在通过 Procfile 运行一个应用程序,所以我对细节并不那么大惊小怪,我只需要它工作。如果你正在构建一个 Ruby 应用程序,我不会听从我的建议。

My Dockerfile is here, FWIW, https://index.docker.io/u/yunojuno/dev/

我的 Dockerfile 在这里,FWIW,https://index.docker.io/u/yunojuno/dev/

回答by Ben Whaley

From bash(1):

来自bash(1)

  • -lMake bash act as if it had been invoked as a login shell
  • -cIf the -c option is present, then commands are read from string.
  • -l使 bash 就像作为登录 shell 被调用一样
  • -c如果存在 -c 选项,则从字符串中读取命令。

You're running the command passed to the -cargument. -lmakes it a login shell so bash first reads /etc/profile, which probably has the path to rvmwhich is what makes it work.

您正在运行传递给-c参数的命令。-l使其成为登录外壳,因此 bash 首先读取/etc/profile,它可能具有rvm使其工作的路径。

FWIW, here's what I do to install rvmin a docker container.

FWIW,这是我rvm在 docker 容器中安装的方法。

# Install some dependencies
RUN apt-get -y -q install curl rubygems

# Install rvm
RUN curl -L https://get.rvm.io | bash -s stable

# Install package dependencies
RUN /usr/local/rvm/bin/rvm requirements

# Install ruby
RUN /usr/local/rvm/bin/rvm install ruby-2.0.0

# create first wrapper scripts
RUN /usr/local/rvm/bin/rvm wrapper ruby-2.0.0 myapp rake rails gem