I have a Dockerfile that defines a Ruby on Rails stack.
Here is the Dockerfile:
FROM ubuntu:14.04
MAINTAINER example <[email protected]>
# Update
RUN apt-get update
# Install Ruby and Rails dependencies
RUN apt-get install -y \
ruby \
ruby-dev \
build-essential \
libxml2-dev \
libxslt1-dev \
zlib1g-dev \
libsqlite3-dev \
nodejs \
curl
RUN gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
RUN curl -sSL https://get.rvm.io | bash -s stable --rails
RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm"
# Install Rails
RUN gem install rails
# Create a new Rails app under /src/my-app
RUN mkdir -p /src/new-app
RUN rails new /src/new-app
WORKDIR /src/my-app
# Default command is to run a rails server on port 3000
CMD ["rails", "server", "--binding", "0.0.0.0", "--port" ,"3000"]
EXPOSE 3000
When I execute the command docker build -t anotherapp/my-rails-app .
I get the following error:
Removing intermediate container 3f8060cdc6f5
Step 8 : RUN gem install rails
---> Running in 8c1793414e63
ERROR: Error installing rails:
activesupport requires Ruby version >= 2.2.2.
The command '/bin/sh -c gem install rails' returned a non-zero code: 1
It looks like the command source /usr/local/rvm/scripts/rvm
isn't working during the build.
I'm not sure exactly why this is happening.
From the docker builder reference, each RUN command is run independently. So doing RUN source /usr/local/rvm/scripts/rvm
does not have any effect on the next RUN command.
Try changing the operations which require the given source file as follows
RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm ; gem install rails"
This doesn't directly answer your question, but it's another way to approach the problem.
Docker provides an official Ruby image. This is the image the Docker Compose and Rails quickstart tutorial uses. As you can see from their example (below), you can copy your Gemfile.lock into your image and run bundle install
without having to worry about RVM.
FROM ruby:2.2.0
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp
You will normally only have one rails application running inside a container using a specific version of Ruby so RVM's ability to manage multiple version of Ruby won't be helpful.
If you are curious how the official images are made, the Dockerfile is on Github.
As to why this is happening. As others pointed out, source
command executes the file in the current shell. Each RUN
instruction
... will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile.
Each RUN
, ADD
, COPY
instruction essentially starts a new shell in a new container and executes a command.
1 RUN /bin/bash -c "source /usr/local/rvm/scripts/rvm"
2 RUN gem install rails
Can be read as
1 Start a brand new shell
Execute: source /usr/local/rvm/scripts/rvm
Save the state of the file system as an image
Exit shell
2 Start a brand new shell
Execute: gem install rails
...
When step 1 finishes, the shell (and everything your sourced into it), goes away.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With