I’m setting up a docker image, I’ve managed to get it working, but only by running one long RUN
command with everything in it.
I want to break it into smaller RUN
commands for ease of maintenance and debugging, etc.
My first RUN
command looks like this:
RUN apt-get update --quiet &&
apt-get install --quiet --yes --no-install-recommends
build-essential
libssl-dev
zlib1g-dev
libreadline-dev
libffi-dev
libyaml-dev &&
git clone --depth 1 https://github.com/rbenv/rbenv.git ~/.rbenv &&
git clone --depth 1 https://github.com/rbenv/ruby-build.git &&
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc &&
echo 'eval "$(rbenv init -)"' >> ~/.bashrc &&
/bin/bash -c "source ~/.bashrc"
When I try call the rbenv install script in the next RUN
command docker can’t find it. Why is this? I’ve tried adding the path in the new RUN
command, but it doesn’t seem to make a difference.
What am I doing wrong?
2
Answers
The issue here with the
PATH
env variable. EachRUN
instruction in a Dockerfile executes in a new shell session, and environment changes (like modifications toPATH
in.bashrc
) do not persist across these sessions.You need to explicitly set
PATH
via DockerENV
instruction, like this:You can find more info in this stackoverflow answer,
and in this Baeldung article.
~/.bashrc
is only executed for login shell and if the login shell is bash. If you want it to be executed in the next RUN commands, you must specify it explicitly, like this:or
Also note that if there is no
~/.bashrc
, bash will execute~/.profile
. But~/.bashrc
normally also includes. ~/.profile
somewhere near the end so it’s usually safer to just append~/.profile
— it will work for both bash and other shells.For the
Dockerfile
though, if you don’t intend to work in the container interactively, you can ignore bash altogether and add environment variables (includingPATH
) using theENV
directive.