<p>Please refer to bash initialization process.
<a href="https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html" rel="nofollow noreferrer">https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html</a></p>

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

<p>Difference</p>

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

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

<p>Regards.</p>

CC BY-SA 4.0
2018-08-10T08:34:03.593Z
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.
ConorSheehan1
CC BY-SA 4.0
2018-08-12T15:29:11.240Z
@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
CC BY-SA 4.0
2019-05-10T15:15:58.197Z
or you can put the bashrc in /etc/bashrc - or softlink or hardlink them
Dagelf
CC BY-SA 4.0
2018-08-10T08:17:55.213Z
2018-08-10T08:17:55.213Z
mvk_il
<p>I had a similar issue and was able to solve it as follows:<br />
(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)</p>
<p>When executing <code>sudo docker -it exec container /bin/bash</code> 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).</p>
<p>But with <code>sudo docker exec -it container /bin/bash -c '&lt;cmd&gt;'</code> the bash is executed in a different mode (I think even using &quot; or ' can make kind of a difference).</p>
<p><strong>My solution:</strong><br />
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.<br />
<code>sudo docker exec -it container /bin/bash -ilc '&lt;cmd&gt;'</code></p>

CC BY-SA 4.0
2022-10-24T12:01:03.340Z
2022-10-24T12:01:03.340Z
dohlenaugur
<p>I have a docker image that looks something like this:</p>

<pre><code>FROM ubuntu:16.04

# Install packages for building ruby
RUN apt-get update &amp;&amp; \
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 &amp;&amp; \
git clone https://github.com/sstephenson/ruby-build.git /root/.rbenv/plugins/ruby-build &amp;&amp; \
/root/.rbenv/plugins/ruby-build/install.sh &amp;&amp; \
echo 'eval "$(rbenv init -)"' &gt;&gt; /etc/profile
echo 'eval "$(rbenv init -)"' &gt;&gt; ~/.profile &amp;&amp; \
echo 'eval "$(rbenv init -)"' &gt;&gt; ~/.bashrc

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

ENTRYPOINT /bin/bash
</code></pre>

<p>My problem is that when I build the image and start a container</p>

<pre><code>docker build -t test .
docker run -it --name test-container test
</code></pre>

<p>If I run the commands directly in the container shell,<br>
ruby is 2.4.1 (as I'd expect after running <code>rbenv global 2.4.1</code>)</p>

<pre><code>ruby -v    # 2.4.1p111
which ruby # /root/.rbenv/shims/ruby
</code></pre>

<p>But if I open a new shell and use docker exec,<br>
ruby is 2.3.1, which is the system default</p>

<pre><code>docker exec test-container ruby -v    # 2.3.1p112
docker exec test-container which ruby # /usr/bin/ruby
</code></pre>

<hr>

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

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

<docker><bash>
Docker exec environment different to container shell
ConorSheehan1
# Docker exec environment different to container shell

(Asked by: username_0 on 2018-08-09)

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?

**Tags:** docker, bash


---

## 2 answers

### Answer by username_1 on 2018-08-10. Score: 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.

Difference

* 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.

Regards.

> **Comments:**
> **username_0**: 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.  
> **username_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`  
> **username_2**: or you can put the bashrc in /etc/bashrc - or softlink or hardlink them  

---

### Answer by username_3 on 2022-10-24. Score: 0

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 ''` 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 ''`


---

