Source bash profile when starting interactive Docker session - bash

Running this opens bash interactively:
docker exec -it bash
However, it's not sourcing ~/.bash_profile, ie the bash_profile in the container. I've tried bash -i instead of bash at the end, but doesn't work. So how to make profile load when entering the container, as it would in a regular interative shell?

add this to the container user .bashrc:
if [ -f ~/.bash_profile ]; then
. ~/.bash_profile
fi
You need to rebuild the image and copy the .bash_profile file too.

-l works, as mentioned by #chepner in comments:
docker exec -it bash -l

Related

Dockerfile doesn't source .bashrc even in a single subshell

I'm trying to source .bashrc but no luck
USER user
SHELL ["/bin/bash", "-c"]
RUN echo "export TEST_VAR=test" >> /home/user/.bashrc && tail /home/user/.bashrc && source /home/user/.bashrc && echo "1 \"${TEST_VAR} 2\" var" && exit 1
I expect that this RUN command print 1 "test" 2 but what i get is that
Step 13/40 : RUN echo "export TEST_VAR=test" >> /home/user/.bashrc && tail /home/user/.bashrc && source /home/user/.bashrc && echo "1 \"${TEST_VAR}\" 2" && exit 1
---> Running in b870d36e9dd0
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
export TEST_VAR=test
1 "" 2
What's wrong with handling shells in docker? I just wanted to source ~/.bashrc once and use all exposed variables in subsequent command below source call but it doesn't even work in a single subshell joined with &&
Usually ~/.bashrc contains something similar to:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
That is very normal - .bashrc is meant to be used in interactive sessions only. Because RUN is non-interactive, it just exits.
Aaaanyway, I would recommend, if you want to only add environment variables, output them to /etc/profile.d and . /etc/profile.
Most paths in Docker don't read shell dotfiles at all. You need to use other approaches to provide configuration to your application; for example, Dockerfile ENV to set environment variables or an entrypoint wrapper script if you need things to be set up dynamically before starting the container.
Let's look specifically at a reduced form of your example:
SHELL ["/bin/bash", "-c"]
RUN echo "export TEST_VAR=test" >> $HOME/.bashrc
RUN echo "$TEST_VAR"
Bash Startup Files in the GNU Bash manual lists out which dotfiles are read in which case. For the last line Docker combines the SHELL and RUN lines to run the equivalent of
/bin/bash -c 'echo "$TEST_VAR"'
but the bash instance is neither an interactive nor a login shell, so the only dotfile that's automatically read is one named in a $BASH_ENV environment variable. (POSIX sh doesn't specify anything about any shell dotfiles at all.)
This further applies to the image's default CMD, which also will get run with sh -c (or the alternate SHELL) and it won't read dotfiles. If the CMD (or ENTRYPOINT or RUN) uses JSON-array syntax, it won't invoke a shell at all, and again won't read dotfiles.
The only case where shell dotfiles will be read is if the main container command is an interactive shell, and this won't typically be the common case.
docker run --rm -it yourimage /bin/bash # reads .bashrc
docker run --rm -it yourimage /bin/bash --login # also reads .profile, .bash_login
This means you should almost never try to edit the .bashrc, /etc/profile, or any similar files. If you need to set environment variables as in the example, use Dockerfile ENV instead.
ENV TEST_VAR=test
RUN echo "$TEST_VAR"

running multiple command from bash script with out loosing control

I want to run these two command in a loop:
for i in cat input:
do
winpty Kubectl exec -it $i -n image -c podname -- sh
2nd command
done
When I am running the .sh file, the first command works fine and after than nothing is happening.Can anybody help on this?I am running through gitbash from windows machine
I'm a bash rookie, but maybe it's because of the lack of a defined -d directory for unzipped files?

Start docker from command line

Is there a command for starting docker from the command line? While this works, it is quite lame:
$ open /Applications/Docker.app/
$ docker returns help text about docker cli commands.
An alternative could be setting up an alias and place it inside ~/.bashrc
echo -e "\nopen-docker='open /Applications/Docker.app/'" >> ~/.bashrc
Ended up adding these alias to ~/.bash_profile or ~/.zshrc.
alias dock="open -a 'Docker'"
alias dock_start="open -a 'Docker'"
alias docker_start="open -a 'Docker'"

Shell script to enter Docker container and execute command, and eventually exit

I want to write a shell script that enters into a running docker container, edits a specific file and then exits it.
My initial attempt was this -
Create run.sh file.
Paste the following commands into it
docker exec -it container1 bash
sed -i -e 's/false/true/g' /opt/data_dir/gs.xml
exit
Run the script -
bash ./run.sh
However, once the script enters into the container1 it lands to the bash terminal of it. Seems like the whole script breaks as soon as I enter into the container, leaving parent container behind which contains the script.
The issue is solved By using the below piece of code
myHostName="$(hostname)"
docker exec -i -e VAR=${myHostName} root_reverse-proxy_1 bash <<'EOF'
sed -i -e "s/ServerName .*/ServerName $VAR/" /etc/httpd/conf.d/vhosts.conf
echo -e "\n Updated /etc/httpd/conf.d/vhosts.conf $VAR \n"
exit
I think you are close. You can try something like:
docker exec container1 sed -i -e 's/false/true/g' /opt/data_dir/gs.xml
Explanations:
-it is for interactive session, so you don't need it here.
docker can execute any command (like sed). You don't have to run sed via bash

Running system command under interactive bash shell

I am trying to run a command that has been aliased in my ~/.bashrc from Perl using the system command. It works well running the command only once, but when I run it twice the second invocation is run as a background job and then suspended (the same as pressing <CTRL-Z>) and I have to type fg to complete the command. For example
use strict;
use warnings;
system ('bash -ic "my_cmd"');
system ('bash -ic "my_cmd"');
The second call never completes. The output is [1]+ Stopped a.pl.
Note:
The same result is obtained when replacing my_cmd with any other command, for example ls.
It seems not to depend of the contents of my ~/.bashrc file. I tried to remove everything from it, and the problem still persisted.
I am using Ubuntu 14.04 and Perl version 5.18.2.
Update
For debugging I reduced my ~/.bashrc to
echo "Entering ~/.bashrc .."
alias my_cmd="ls"
alias
and my ~/.bash_profile to
if [ -f ~/.bashrc ]; then
echo "Entering ~/.bash_profile .."
. ~/.bashrc
fi
Now running:
system ('bash -lc "my_cmd"');
system ('bash -lc "my_cmd"');
gives
Entering ~/.bash_profile ..
Entering ~/.bashrc ..
alias my_cmd='ls'
bash: my_cmd: command not found
Entering ~/.bash_profile ..
Entering ~/.bashrc ..
alias my_cmd='ls'
bash: my_cmd: command not found
and running
system ('bash -ic "my_cmd"');
system ('bash -ic "my_cmd"');
gives
Entering ~/.bashrc ..
alias my_cmd='ls'
a.pl p.sh
[1]+ Stopped a.pl
Rather than using the -i switch for an interactive shell, I think you should use the -l (or --login) switch, which causes bash to act as if it had been invoked as a login shell.
Using the -l switch doesn't load ~/.bashrc by default. According to man bash, in a login shell, /etc/profile/ is loaded, followed by the first file found from ~/.bash_profile/, ~/.bash_login or ~/.profile/. On my system, I have the following in ~/.bash_profile, so ~/.bashrc is loaded:
# Source .bashrc
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
Now that your ~/.bashrc is being loaded, you need to enable the expansion of aliases, which is off in a non-interactive shell. To do this, you can add the following line before setting your aliases:
shopt -s expand_aliases
A process randomly stopping - aside from ctrl-z is usually when it needs STDIN, but doesn't have it attached.
Try it with - for example passwd &. It'll background and go straight into 'stopped' state. This may well be what's happening with your bash command. -i means interactive shell, explicitly, and you're trying to do something noninteractive with it.
That's almost certainly not the best approach, you probably want to do something different. bash --login might be closer to what you're after.
Tom Fenech's answer worked for me in Ubuntu 16.04.1 LTS with a small addition. At the top of my ~/.bashrc file, I commented out the following section so that if the shell is not interactive (e.g., a login shell), ~/.bashrc is still read. On some other versions of Linux I don't see this section.
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac

Resources