skip to Main Content

I’m creating a Dockerfile to run truffleruby. I’m getting an error when trying to install bundler and foreman. The error is /bin/sh: 1: gem: not found

Dockerfile

FROM debian:buster-slim

# Install packages for building ruby
RUN apt update -y && apt install -y git curl libssl-dev libpq-dev libreadline-dev zlib1g-dev 
  autoconf bison build-essential libyaml-dev 
  libreadline-dev libncurses5-dev libffi-dev libgdbm-dev
RUN apt clean

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

RUN rbenv install truffleruby-20.3.0
RUN rbenv global truffleruby-20.3.0
RUN rbenv rehash

ENV BUNDLER_VERSION=2.2.4 NODE_ENV=production RAILS_ENV=production RAILS_SERVE_STATIC_FILES=true RAILS_LOG_TO_STDOUT=true PORT=3000
ENV CONFIGURE_OPTS --disable-install-doc

RUN apt-get install -y curl -sL https://deb.nodesource.com/setup_14.x | bash - && 
  apt-get update && apt-get install -y nodejs && 
  apt-get clean

RUN rbenv versions
RUN gem install bundler:2.2.4 foreman

RUN mkdir /app
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN bundle config set --local deployment 'true'
RUN bundle config set --local without 'development test'
RUN bundle install
COPY . .


EXPOSE 3000
CMD ["foreman", "start"]

tail of build

Removing intermediate container 1a445fde7fc0
 ---> 43c3d72b7eb6
Step 17/27 : RUN rbenv versions
 ---> Running in feb5bb9361cc
* truffleruby-20.3.0 (set by /root/.rbenv/version)
Removing intermediate container feb5bb9361cc
 ---> c7d1a5826af5
Step 18/27 : RUN gem install bundler:2.2.4 foreman
 ---> Running in 998461afc89c
/bin/sh: 1: gem: not found
The command '/bin/sh -c gem install bundler:2.2.4 foreman' returned a non-zero code: 127

2

Answers


  1. You don’t generally use version managers like rbenv in Docker. There are a couple of reasons for this. One is that an image usually only contains a single application and its single runtime, so you’d never have more than one Ruby in an image and therefore there’s no need to switch. A second is that most common paths of running containers (including docker run and the Dockerfile RUN directive) don’t look at shell dotfiles like .bashrc or /etc/profile, so the version manager setup will never get run.

    TruffleRuby is distributed (among other ways) as a standalone tar file so you can just install that in your Dockerfile. I’d make the Dockerfile look roughly like:

    FROM debian:buster-slim
    # Install the specific dependency packages TruffleRuby recommends
    # (build-essential is much larger but might actually be necessary)
    RUN apt-get update 
     && DEBIAN_FRONTEND=noninteractive 
        apt-get install --no-install-recommends --assume-yes 
          curl 
          gcc 
          libssl-dev 
          libz-dev 
          make
    
    # Download and unpack TruffleRuby
    ARG TRUFFLERUBY_VERSION=20.3.0
    ENV PATH /opt/truffleruby-$TRUFFLERUBY_VERSION-linux-amd64/bin:$PATH
    RUN cd /opt 
     && curl -L https://github.com/oracle/truffleruby/releases/download/vm-$TRUFFLERUBY_VERSION/truffleruby-$TRUFFLERUBY_VERSION-linux-amd64.tar.gz | tar xz 
     && /opt/truffleruby-$TRUFFLERUBY_VERSION-linux-amd64/lib/truffle/post_install_hook.sh
    
    # Now build and install your application
    RUN gem install bundler:2.2.4
    WORKDIR /app
    COPY Gemfile Gemfile.lock ./
    RUN bundle config set --local deployment 'true'
    RUN bundle config set --local without 'development test'
    RUN bundle install
    COPY . .
    ENTRYPOINT ["bundle", "exec"]
    EXPOSE 3000
    CMD ["rails", "start"]
    

    You can reasonably split this into two separate Dockerfiles. End the first one before the "build and install your application" comment, and build it with docker build -t myname/truffleruby:20.3.0 -f Dockerfile.truffleruby .. Then the second one can begin with FROM myname/truffleruby:20.3.0 in the same way as the standard Docker Hub ruby image.

    Login or Signup to reply.
  2. Does the same work with CRuby?

    I’d suspect RUN doesn’t read shell files, so PATH needs to be modified.

    RUN git clone https://github.com/sstephenson/rbenv.git /root/.rbenv
    ...
    RUN /root/.rbenv/plugins/ruby-build/install.sh
    ENV PATH /root/.rbenv/bin:$PATH
    

    seems a bit weird, is rbenv cloned and installed in the same place?

    I would skip rbenv in Docker, and instead just:

    RUN ruby-build truffleruby ~/.rubies/truffleruby
    ENV PATH $HOME/.rubies/truffleruby/bin:$PATH
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search