0

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?

3
  • 2
    There are several practical problems with using version managers like rbenv in Docker, but they're also rarely necessary since a typical image contains a single application and its single specific language runtime. Can you build your Dockerfile FROM the correct version of the ruby image, and delete this setup entirely? Commented Oct 18, 2024 at 12:43
  • I'll have to investigate that, but as I understand it we have multiple flavours of the same app for different clients that have different requirements. We want to be able to specify the versions of ruby and python at build time rather than fixing it in the image. Commented Oct 21, 2024 at 10:59
  • You can use a variable in a FROM line, and docker build --build-arg to pass it in. See Understand how ARG and FROM interact in the Dockerfile reference. Commented Oct 21, 2024 at 11:05

2 Answers 2

5

The issue here with the PATH env variable. Each RUN instruction in a Dockerfile executes in a new shell session, and environment changes (like modifications to PATH in .bashrc) do not persist across these sessions.

You need to explicitly set PATH via Docker ENV instruction, like this:

ENV PATH="$HOME/.rbenv/bin:$PATH" 

You can find more info in this stackoverflow answer, and in this Baeldung article.

Sign up to request clarification or add additional context in comments.

Comments

1

~/.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:

RUN bash -l -c '...'

or

RUN . ~/.bashrc; ...

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 (including PATH) using the ENV directive.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.