How to get /etc/profile to run automatically in Alpine / Docker
Asked Answered
S

4

64

How can I get /etc/profile to run automatically when starting an Alpine Docker container interactively? I have added some aliases to an aliases.sh file and placed it in /etc/profile.d, but when I start the container using docker run -it [my_container] sh, my aliases aren't active. I have to manually type . /etc/profile from the command line each time.

Is there some other configuration necessary to get /etc/profile to run at login? I've also had problems with using a ~/.profile file. Any insight is appreciated!

EDIT:

Based on VonC's answer, I pulled and ran his example ruby container. Here is what I got:

$ 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

Although the /etc/profile.d/rubygems.sh file exists, it is not being run when I login and my PATH environment variable is not being updated. Am I using the wrong docker run command? Is something else missing? Has anyone gotten ~/.profile or /etc/profile.d/ files to work with Alpine on Docker? Thanks!

Scaly answered 25/6, 2016 at 1:39 Comment(2)
Did you try build Alpine Images with ADD .profile /etc/.profile?Ctesiphon
No, I've never actually heard of trying to use /etc/.profile. I've always believed that .profile belongs in your HOME directory, whereas profile (no dot) belongs in /etc.Scaly
S
43

You still can try in your Dockerfile a:

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

(assuming the current user is root. If not, replace /root with the full home path)

That being said, those /etc/profile.d/xx.sh should run.
See codeclimate/docker-alpine-ruby as an example:

COPY files /

With 'files/etc" including an files/etc/profile.d/rubygems.sh running just fine.


In the OP project Dockerfile, there is a

COPY aliases.sh /etc/profile.d/

But the default shell is not a login shell (sh -l), which means profile files (or those in /etc/profile.d) are not sourced.

Adding sh -l would work:

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
Saldana answered 25/6, 2016 at 6:28 Comment(12)
VonC: I've tried using a /root/.profile file, too, with the same alias definitions I'm putting in the /etc/profile.d/aliases.sh file. Actually, that was the first thing I tried. I thought maybe there was something different with ash and sh on Alpine that I was missing -- some reason my .profile wasn't being read. I will take a look at your example. Thanks!Scaly
By the way, here's a basic Node container where I am using the aliases.sh file. Maybe someone could pull this container and see if the aliases and color prompt are working correctly when they login... https://hub.docker.com/r/jkilbride/node-npm-alpine/Scaly
@JeffKilbride I have edited my answer. Maybe a chmod is missing?Saldana
VonC: Thanks for the quick update! Please see the edit I made to my original post above. I pulled and ran the codeclimate/docker-alpine-ruby and had the same problems. My PATH variable was not updated by the rubygems.sh file in /etc/profile.d.Scaly
@JeffKilbride Could you do a ls -alrt /etc/profile.d to see if that sh script is executable or not?Saldana
The rubygems.sh file is not executable, it's rw-rw-r or 0664. I will give it a try on my aliases.sh file, but I am skeptical about that being the problem. These files are being sourced with . filename.sh in /etc/profile. They should not need to be executable. Even the example color_prompt file that comes with Alpine is not executable. And none of my files that customize the shell on other Linux distros are executable (e.g. git-prompt.sh, .bash_profile, .bashrc, etc...) The relevant line in /etc/profile is if [ -r $script ] -- so, it's testing for readability.Scaly
@JeffKilbride make sense, I was just checking just in case.Saldana
Have you logged into that codeclimate/alpine-ruby container? Does it update your PATH correctly? I'm wondering if this is just a problem I'm seeing or if others are having it, too. If it's more than just me, I'll post something at alpinelinux.org.Scaly
@JeffKilbride I am docker pulling your image as we speak.Saldana
@JeffKilbride Got it. The shell opened by default by docker run is not a login shell (all the details are in askubuntu.com/a/247769/5470). I have edited my answer, showing the right docker run which does work.Saldana
VonC Awesome! I figured it was something weird with docker, but couldn't find an answer. The sh -l is working for me. Thanks for the help!Scaly
sh -l is the missing piece! Thank you for sharing this!Gabbey
I
84

The default shell in Alpine Linux is ash.

Ash will only read the /etc/profile and ~/.profile files if it is started as a login shell sh -l.

To force Ash to source the /etc/profile or any other script you want upon its invocation as a non login shell, you need to setup an environment variable called ENV before launching Ash.

Editor's note: ENV is only sourced if the shell is interactive.

e.g. in your Dockerfile

FROM alpine:3.5

ENV ENV="/root/.ashrc"

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

When you build that you get:

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

Finally, when you run the newly generated container, you get:

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

Notice the Ash shell didn't run as a login shell.

So to answer your query, replace

ENV ENV="/root/.ashrc"

with:

ENV ENV="/etc/profile"

and Alpine Linux's Ash shell will automatically source the /etc/profile script each time the shell is launched.

Gotcha: /etc/profile is normally meant to only be sourced once! So, I would advise that you don't source it and instead source a /root/.somercfile instead.

Source: https://stackoverflow.com/a/40538356

Iman answered 2/5, 2017 at 17:4 Comment(1)
Regarding: Editor's note: ENV is only sourced if the shell is interactive. This linux.die.net/man/1/ash says: "Since the ENV file is read for every invocation of the shell, including shell scripts and non-interactive shells..." and then provides a way to restrict commands in the ENV file to interactive invocations which makes me think that ash does process ENV variable regardless of whether the shell is interactive.Iman
S
43

You still can try in your Dockerfile a:

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

(assuming the current user is root. If not, replace /root with the full home path)

That being said, those /etc/profile.d/xx.sh should run.
See codeclimate/docker-alpine-ruby as an example:

COPY files /

With 'files/etc" including an files/etc/profile.d/rubygems.sh running just fine.


In the OP project Dockerfile, there is a

COPY aliases.sh /etc/profile.d/

But the default shell is not a login shell (sh -l), which means profile files (or those in /etc/profile.d) are not sourced.

Adding sh -l would work:

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
Saldana answered 25/6, 2016 at 6:28 Comment(12)
VonC: I've tried using a /root/.profile file, too, with the same alias definitions I'm putting in the /etc/profile.d/aliases.sh file. Actually, that was the first thing I tried. I thought maybe there was something different with ash and sh on Alpine that I was missing -- some reason my .profile wasn't being read. I will take a look at your example. Thanks!Scaly
By the way, here's a basic Node container where I am using the aliases.sh file. Maybe someone could pull this container and see if the aliases and color prompt are working correctly when they login... https://hub.docker.com/r/jkilbride/node-npm-alpine/Scaly
@JeffKilbride I have edited my answer. Maybe a chmod is missing?Saldana
VonC: Thanks for the quick update! Please see the edit I made to my original post above. I pulled and ran the codeclimate/docker-alpine-ruby and had the same problems. My PATH variable was not updated by the rubygems.sh file in /etc/profile.d.Scaly
@JeffKilbride Could you do a ls -alrt /etc/profile.d to see if that sh script is executable or not?Saldana
The rubygems.sh file is not executable, it's rw-rw-r or 0664. I will give it a try on my aliases.sh file, but I am skeptical about that being the problem. These files are being sourced with . filename.sh in /etc/profile. They should not need to be executable. Even the example color_prompt file that comes with Alpine is not executable. And none of my files that customize the shell on other Linux distros are executable (e.g. git-prompt.sh, .bash_profile, .bashrc, etc...) The relevant line in /etc/profile is if [ -r $script ] -- so, it's testing for readability.Scaly
@JeffKilbride make sense, I was just checking just in case.Saldana
Have you logged into that codeclimate/alpine-ruby container? Does it update your PATH correctly? I'm wondering if this is just a problem I'm seeing or if others are having it, too. If it's more than just me, I'll post something at alpinelinux.org.Scaly
@JeffKilbride I am docker pulling your image as we speak.Saldana
@JeffKilbride Got it. The shell opened by default by docker run is not a login shell (all the details are in askubuntu.com/a/247769/5470). I have edited my answer, showing the right docker run which does work.Saldana
VonC Awesome! I figured it was something weird with docker, but couldn't find an answer. The sh -l is working for me. Thanks for the help!Scaly
sh -l is the missing piece! Thank you for sharing this!Gabbey
A
8

As mentioned by Jinesh before, the default shell in Alpine Linux is ash

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

Therefore simple solution is too add your aliases in .profile. In this case, I put all my aliases in ~/.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:~$

And it works :)

Accretion answered 16/6, 2017 at 5:2 Comment(1)
Is there an equivalent to the /etc/profile.d scan for *.sh files? I have to set some environment variables programmatically. For now I have taken Jinesh's solution, but I prefer to do it the most appropriate way possible.Miki
A
5

I use this:

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

The -l flag passed to ash will make it behave as a login shell, thus reading ~/.profile

Affairs answered 14/1, 2022 at 17:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.