How to install ruby and bundler with dockerfile? - ruby

New to ruby and bundler here.
I am installing them in a docker image with this docker file:
FROM alpine:3.5
# Install Ruby, Ruby Bundler and other ruby dependencies
RUN apk add --update \
ruby ruby-bigdecimal ruby-bundler \
ca-certificates libressl \
libressl-dev build-base ruby-dev \
ruby-rdoc ruby-io-console ruby-irb; \
\
&& bundle config build.nokogiri --use-system-libraries; \
&& bundle config git.allow_insecure true; \
\
&& gem install json foreman --no-rdoc --no-ri; \
&& gem cleanup; \
&& rm -rf /usr/lib/ruby/gems/*/cache/*; \
&& apk del libressl-dev build-base ruby-dev; \
&& rm -rf /var/cache/apk/* /tmp;
CMD ["bundle"]
When I run do a docker run I get:
Don't run Bundler as root. Bundler can ask for sudo if it is needed,
and installing your bundle as root will break this application for all
non-root users on this machine.
Could not locate Gemfile or .bundle/ directory
How do I resolve this? I just want to install ruby and ruby-bundle and be done with this ...

There are pre built ruby images (e.g Alpine 3.11 Ruby 2.7) that include bundler. It's easier to start with them as they generally use the current "best practices" to build.
Notice that they set the BUNDLE_SILENCE_ROOT_WARNING environment variable with ENV directive in the image build to remove that root warning.
You normally wouldn't run bundler as the CMD for a container either, you might run bundler during a RUN image build step though.
Running containers as non-root users is not a bad idea in any case. Use the USER directive to change that.
FROM ruby:2.7
WORKDIR /app
ADD . /app/
RUN set -uex; \
bundle install; \
adduser -D rubyapp; \
mkdir -p /app/data; \
chown rubyapp /app/data
USER rubyapp
CMD [ "ruby", "whatever.rb" ]

Related

gem command not found when install rbenv in debian

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

Docker: Ruby version upgrade from 2.2.0 to 2.4.0

I am using Ruby version 2.2.0 in my Rails Application and Rails version is 4.2.0.
Currently, Project is built through docker, so I am thinking of to upgrade the ruby version with 2.4.0 version.
I believe I need to change the docker image to upgrade the ruby version.
I already check a few of the articles but didn't get enough information.
Docker file
FROM ruby:2.2.0
RUN apt update && \
apt install -y --no-install-recommends \
git \
curl \
gnupg2 \
libpq-dev \
libmysqlclient-dev \
nodejs \
graphviz \
&& rm -rf /var/lib/apt/lists/*
Once ruby version upgraded then I will upgrade the rails version.
Any help will be appreciated.
You can always build your own Docker image as such:
FROM ubuntu
RUN apt-get update
RUN apt-get install -y build-essential wget
RUN wget --no-check-certificate -O ruby-install.tar.gz https://github.com/postmodern/ruby-install/archive/master.tar.gz
RUN tar -xzvf ruby-install.tar.gz
RUN cd ruby-install-master && make install
RUN cd /
RUN rm -rf ruby-install-master && rm -rf ruby-install.tar.gz
RUN ruby-install --latest
RUN ruby-install -i /usr/local/ ruby 2.4.0 -- --disable-install-doc
RUN gem update --system --no-document
RUN gem install bundler --force
depends on how one manages ruby application and ruby version. here are few things i would offer to check:
update Gemfile if bundler is used
$ cat Gemfile | head -n 1
ruby '2.4.0'
update .ruby-version if rbenv or [rvm][3] is used
$ cat .ruby-version
2.4.0
update Dockerfile if docker is used
$ cat Dockerfile | grep FROM
FROM ruby:2.4.0

Running a cucumber test on firefox in a docker container

I'm trying to run my cucumber tests in a docker container using firefox. I'm getting this error when my code just tries to visit 'google.com'
Net::ReadTimeout (Net::ReadTimeout)
Here is my Dockerfile
FROM ruby:2.2.2
RUN mkdir /app
WORKDIR /app
RUN gem update
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
RUN bundle install
RUN apt-get update && apt-get install -y --fix-missing iceweasel xvfb unzip
ENV GECKODRIVER_VERSION v0.13.0
RUN echo $GECKODRIVER_VERSION
RUN mkdir -p /opt/geckodriver_folder
RUN wget -O /tmp/geckodriver_linux64.tar.gz https://github.com/mozilla/geckodriver/releases/download/$GECKODRIVER_VERSION/geckodriver-$GECKODRIVER_VERSION-linux64.tar.gz
RUN tar xf /tmp/geckodriver_linux64.tar.gz -C /opt/geckodriver_folder
RUN rm /tmp/geckodriver_linux64.tar.gz
RUN chmod +x /opt/geckodriver_folder/geckodriver
RUN ln -fs /opt/geckodriver_folder/geckodriver /usr/local/bin/geckodriver
ADD features /app/features
I've tried increasing my read_timeout to 120 with no effect.
When i bash into the container and run firefox it says "no display specified"
Any suggestions ?
I was having the same issue. This worked for me: https://github.com/juandelgado/docker-headless-firefox-cucumber/blob/master/Dockerfile
FROM ruby:2.4-slim
MAINTAINER Juan Delgado <juan#ustwo.com>
RUN mkdir /home/ustwo
WORKDIR /home/ustwo
RUN apt-get update && \
apt-get install -y xvfb build-essential libffi-dev wget firefox-esr && \
wget https://github.com/mozilla/geckodriver/releases/download/v0.17.0/geckodriver-v0.17.0-linux64.tar.gz && \
tar -zxvf geckodriver-v0.17.0-linux64.tar.gz && \
chmod +x geckodriver && \
mv geckodriver /usr/local/bin && \
rm geckodriver-v0.17.0-linux64.tar.gz
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle
RUN ["cucumber", "--version"]

How to require dependencies for ruby IronWorker

I put together a simple script to run in iron.io. I follow the steps in this tutorial but fail during testing.
$ docker run --rm -it -e "SLACK_API_TOKEN="xox-LALLALA"" -v "$PWD":/worker -w /worker iron/ruby ruby bubbebot.rb
bubbebot.rb:1:in `require_relative': cannot load such file -- /worker/slack-ruby-client (LoadError)
from bubbebot.rb:1:in `<main>'
It's failing whether I try require or relative_require. Any idea what I need to do to vendor this dependency?
That error message means you are trying to use something that is not in the iron/ruby image.
To understand how to fix this, let's take a look at the Dockerfile for that image:
FROM iron/base
RUN apk update && apk upgrade \
&& apk add libxml2 libxslt libevent libffi glib ncurses readline \
openssl yaml zlib curl mariadb-libs libpq ruby ruby-io-console \
ruby-bigdecimal \
&& rm -rf /var/cache/apk/*
If you want to use something that is not present on that build, you'll need to add it yourself. I would suggest making your own custom Docker image. Something along the lines of this should work:
FROM iron/ruby:2.3.1-dev
RUN apk add && apk update
RUN gem install slack --no-ri --no-rdoc
RUN rm -rf /var/cache/apk/*
Build that image and push it to Dockerhub and try running your code on that.

Bundler GemspecError when building inside Docker container

People were reporting this error and solved it by deleting a folder holding cached gems. Since I'm working inside a Docker container, this didn't seem like helpful advice for me. Indeed, the cache folder was not empty but did contain two items (I guess they are there from gem install bundle).
This is my (faulty) dockerfile
FROM nginx
RUN apt-get update -qqy && \
apt-get install -qqy \
build-essential \
ruby-full \
ruby-dev
RUN gem install bundle
RUN useradd -ms /bin/bash udo
USER udo
WORKDIR /home/udo
COPY . .
RUN bundle install
RUN bundle exec -- jekyll build
USER root
RUN cp -r _site/* /usr/share/nginx/html
I could fix the error by replacing RUN bundle install with
RUN bundle install --path=tmp
at the expense of having this local tmp directory that I then had to add to the exclude list in the _config.yml for Jekyll.
I'd prefer to know what was actually going on. I suspect there's a problem with the way I use the non-root user.
Note: bundle install --no-cache did not help.

Resources