如何在Alpine / Docker中使/etc/profile自动运行

60

如何让/etc/profile在交互式启动Alpine Docker容器时自动运行?我已经将一些别名添加到aliases.sh文件中并将其放置在/etc/profile.d中,但是当我使用docker run -it [my_container] sh启动容器时,我的别名没有生效。每次都必须手动从命令行键入. /etc/profile

有必要进行其他配置来在登录时运行/etc/profile吗?我在使用~/.profile文件方面也遇到了问题。感谢任何洞察力!

编辑:

根据VonC的答案,我拉取并运行了他的示例ruby容器。这是我得到的:

$ docker run --rm --name ruby -it codeclimate/alpine-ruby:b42
/ # more /etc/profile.d/rubygems.sh
export PATH=$PATH:/usr/lib/ruby/gems/2.0.0/bin
/ # env
no_proxy=*.local, 169.254/16
HOSTNAME=6c7e93ebc5a1
SHLVL=1
HOME=/root
TERM=xterm
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
/ # exit
尽管存在 /etc/profile.d/rubygems.sh 文件,但它在我登录时没有运行,并且我的 PATH 环境变量没有被更新。我是否使用了错误的 docker run 命令?是否还有其他缺少的东西?有人是否成功地将 ~/.profile/etc/profile.d/ 文件与 Docker 上的 Alpine 配合使用过?谢谢!

1
你有尝试使用ADD .profile /etc/.profile构建Alpine镜像吗? - Nguyen Sy Thanh Son
2
不,我从来没有听说过尝试使用/etc/.profile的做法。我一直认为.profile应该放在你的HOME目录中,而profile(没有点)则应该放在/etc中。 - Jeff Kilbride
4个回答

80

Alpine Linux 的默认 shell 是 ash

只有在以登录 shell sh -l 启动时,Ash 才会读取 /etc/profile~/.profile 文件。

要强制 Ash 在作为非登录 shell 调用时源 /etc/profile 或任何其他脚本,需要在启动 Ash 之前设置一个名为 ENV 的环境变量。

编辑说明:仅当shell是交互式的情况下,才会源 ENV。

例如,在您的 Dockerfile 中:

FROM alpine:3.5

ENV ENV="/root/.ashrc"

RUN echo "echo 'Hello, world!'" > "$ENV"

当你构建它时,你会得到:

deployer@ubuntu-1604-amd64:~/blah$ docker build --tag test .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM alpine:3.5
3.5: Pulling from library/alpine
627beaf3eaaf: Pull complete
Digest: sha256:58e1a1bb75db1b5a24a462dd5e2915277ea06438c3f105138f97eb53149673c4
Status: Downloaded newer image for alpine:3.5
 ---> 4a415e366388
Step 2/3 : ENV ENV "/root/.ashrc"
 ---> Running in a9b6ff7303c2
 ---> 8d4af0b7839d
Removing intermediate container a9b6ff7303c2
Step 3/3 : RUN echo "echo 'Hello, world!'" > "$ENV"
 ---> Running in 57c2fd3353f3
 ---> 2cee6e034546
Removing intermediate container 57c2fd3353f3
Successfully built 2cee6e034546

最后,当您运行新生成的容器时,您会得到:

deployer@ubuntu-1604-amd64:~/blah$ docker run -ti test /bin/sh
Hello, world!
/ # exit

请注意,Ash shell没有作为登录shell运行。
所以为了回答你的问题,请替换
ENV ENV="/root/.ashrc"

使用:

ENV ENV="/etc/profile"

Alpine Linux的Ash shell每次启动时都会自动源/ etc / profile脚本。

注意:/etc/profile通常只需要被源一次!因此,我建议您不要源它,而是源/root/.somercfile。

来源:https://stackoverflow.com/a/40538356


关于:编辑注释:只有在shell是交互式的情况下,才会使用ENV。这个https://linux.die.net/man/1/ash说:“由于每次调用shell(包括shell脚本和非交互式shell)都会读取ENV文件...”,然后提供了一种限制在ENV文件中的命令只能在交互式调用中使用的方法,这让我认为ash无论shell是否交互式都会处理ENV变量。 - Jinesh Choksi

43

您仍然可以在Dockerfile中尝试:

RUN echo '\
        . /etc/profile ; \
    ' >> /root/.profile

假设当前用户是root。如果不是,请使用完整的主目录路径替换/root

话虽如此,那些位于/etc/profile.d/xx.sh中的文件应该运行。
codeclimate/docker-alpine-ruby为例:

COPY files /

使用'files/etc',其中包括一个files/etc/profile.d/rubygems.sh,一切都运行良好。


OP 项目Dockerfile 中,有一个


COPY aliases.sh /etc/profile.d/

但是默认的shell不是登录shell(sh -l),这意味着 profile文件(或位于/etc/profile.d中的文件)不会被调用。添加sh -l即可解决问题。
docker@default:~$ docker run --rm --name ruby -it codeclimate/alpine-ruby:b42 sh -l
87a58e26b744:/# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/ruby/gems/2.0.0/bin

1
VonC:我也尝试使用/root/.profile文件,并在其中定义了与我在/etc/profile.d/aliases.sh文件中定义的别名相同的内容。实际上,这是我尝试的第一件事。我认为可能是Alpine上的ashsh有所不同,我错过了一些东西--我的.profile没有被读取的原因。我会查看您的示例。谢谢! - Jeff Kilbride
顺便说一下,这是一个基本的 Node 容器,我在其中使用了 aliases.sh 文件。也许有人可以拉取这个容器,看看登录时别名和彩色提示是否正常工作... https://hub.docker.com/r/jkilbride/node-npm-alpine/ - Jeff Kilbride
1
@JeffKilbride 已经明白了。由docker run默认打开的shell不是登录shell(所有细节都在http://askubuntu.com/a/247769/5470中)。我已经编辑了我的答案,展示了正确的`docker run`命令,可以正常工作。 - VonC
1
VonC太棒了!我想这可能与docker有关,但是找不到答案。对我来说,sh -l很有效。感谢您的帮助! - Jeff Kilbride
2
sh -l 是缺失的一部分!感谢您分享这个! - ITW
显示剩余7条评论

8

正如Jinesh之前所提到的,Alpine Linux的默认shell是ash

localhost:~$ echo $SHELL
/bin/ash
localhost:~$ 

因此,简单的解决方案是在.profile中添加您的别名。在这种情况下,我将所有的别名都放在~/.ash_aliases中。
localhost:~$ cat .profile 
# ~/.profile

# Alias
if [ -f ~/.ash_aliases ]; then
    . ~/.ash_aliases
fi

localhost:~$ 

.ash_aliases file

localhost:~$ cat .ash_aliases
alias a=alias
alias c=clear
alias f=file
alias g=grep
alias l='ls -lh'
localhost:~$

它可以工作 :)


是否有类似于 /etc/profile.d 扫描 *.sh 文件的等效方法?我需要以编程方式设置一些环境变量。目前我采用了 Jinesh 的解决方案,但我更喜欢以最合适的方式来完成它。 - Scott Lindner

4

我使用这个:

docker exec -it my_container /bin/ash '-l'

传递给ash的-l标志将使其表现为登录shell,因此会读取~/.profile文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接