I have a docker image that looks something like this:

FROM ubuntu:16.04

# Install packages for building ruby
RUN apt-get update && \
apt-get -y install build-essential git curl wget net-tools apt-utils sudo man \
libssl-dev libreadline-dev libyaml-dev nano gcc rubygems ruby-dev

# Install rbenv and ruby-build
ENV PATH /root/.rbenv/bin:$PATH
RUN git clone https://github.com/sstephenson/rbenv.git /root/.rbenv && \
git clone https://github.com/sstephenson/ruby-build.git /root/.rbenv/plugins/ruby-build && \
/root/.rbenv/plugins/ruby-build/install.sh && \
echo 'eval "$(rbenv init -)"' >> /etc/profile
echo 'eval "$(rbenv init -)"' >> ~/.profile && \
echo 'eval "$(rbenv init -)"' >> ~/.bashrc

# Install ruby and bundler
# Install Bundler
ENV CONFIGURE_OPTS --disable-install-doc
RUN rbenv install 2.4.1 && \
echo 'gem: --no-rdoc --no-ri' >> ~/.gemrc && \
rbenv global 2.4.1 && \
rbenv local 2.4.1 && \
gem install bundler

ENTRYPOINT /bin/bash

My problem is that when I build the image and start a container

docker build -t test .
docker run -it --name test-container test

If I run the commands directly in the container shell,
ruby is 2.4.1 (as I'd expect after running rbenv global 2.4.1)

ruby -v    # 2.4.1p111
which ruby # /root/.rbenv/shims/ruby

But if I open a new shell and use docker exec,
ruby is 2.3.1, which is the system default

docker exec test-container ruby -v    # 2.3.1p112
docker exec test-container which ruby # /usr/bin/ruby

I think it could have something to do with the bash profile not starting rbenv properly when using docker exec. The env command seems to have less output when using docker exec too, which is why I suspect something to do with .bashrc, .profile, or even /etc/profile not loading somehow.

How can I ensure docker exec produces the same result as running the command directly on the container?

2 Answers 2


Please refer to bash initialization process. https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html

In your Dockerfile, at lines 12-14 you are patching files, but do not activate any of rbenvs. Later at your last RUN call, you finally ARE activating an rbenv. This starts pointing at that specific version of ruby (I thin this patches root files) At that point you have different global shell initialization files vs. user initialization files.


  • entry point: "non-login" initialization process happens, then the file: /root/.bashrc is executed (a.k.a. "sourced"), it points to your cool ruby
  • exec of ruby: ruby executable is located using your default PATH. without running /root/.bash* files.

To validate all this you can append printouts to your shell's initialization files, and see what gets printed upon 2 cases.


  • Thanks for your answer! That makes sense, but is there a way I can force docker exec to source .bashrc without actually prepending source ~/.bashrc && to every command I want to run? The reason this is an issue is that I have to start the container in detached mode, so I can only use exec to run commands. The only solution I've found so far is to force a symlink to /usr/bin/ruby ln -nsf ~/.rbenv/shims/ruby /usr/bin/ruby but that could break applications from ubuntu that rely on the system ruby version. Commented Aug 10, 2018 at 8:34
  • 1
    @con-- I think you can create a wrapper script to do that for you, call it /arbitrary_exec.sh and do all the magic in it, executing everything as is at its bottom line: "${@}", invoke by exec /arbitrary_exec.sh mycmd bla bla bbla
    – mvk_il
    Commented Aug 12, 2018 at 15:29
  • or you can put the bashrc in /etc/bashrc - or softlink or hardlink them
    – Dagelf
    Commented May 10, 2019 at 15:15

I had a similar issue and was able to solve it as follows:
(Side-note: I had not much time to look deep into the topic, so I can not explain in detail why it works, but it worked)

When executing sudo docker -it exec container /bin/bash I believe the shell gets started in interactive mode. This mode will source the .bashrc and so on (See link in answer from mvk_il).

But with sudo docker exec -it container /bin/bash -c '<cmd>' the bash is executed in a different mode (I think even using " or ' can make kind of a difference).

My solution:
Execute the bash specificly in interactive mode and as a login shell. by that, it should behave the same way as if you enter the container and type the command by hand.
sudo docker exec -it container /bin/bash -ilc '<cmd>'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.