Install Bundler failed in Ruby Docker image - docker

I have a very old project I'm giving support. I'm using docker to make my builds and everything was working until this last one try.
This is my Dockerfile:
FROM ruby:2.1
# Install apt based dependencies required to run Rails as
# well as RubyGems. As the Ruby image itself is based on a
# Debian image, we use apt-get to install those.
RUN apt-get update && apt-get install -y \
git \
ghostscript \
libgs-dev \
build-essential \
libmysqlclient-dev \
locales \
nodejs
# Use en_US.UTF-8 as our locale
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
# Configure the main working directory. This is the base
# directory used in any further RUN, COPY, and ENTRYPOINT
# commands.
RUN mkdir -p /app
WORKDIR /app
# Copy the Gemfile as well as the Gemfile.lock and install
# the RubyGems. This is a separate step so the dependencies
# will be cached unless changes to one of those two files
# are made.
COPY Gemfile Gemfile.lock ./
COPY vendor/oohlalog_gem ./vendor/oohlalog_gem
RUN gem install bundler && bundle install
# Copy the main application.
COPY . ./
# Expose port 3000 to the Docker host, so we can access it
# from the outside.
EXPOSE 3000
# Configure an entry point, so we don't need to specify
# "bundle exec" for each of our commands.
ENTRYPOINT ["bundle", "exec"]
# The main command to run when the container starts. Also
# tell the Rails dev server to bind to all interfaces by
# default.
CMD ["rails", "server", "-b", "0.0.0.0"]
When I try to run:
docker build . -t my_image
I'm getting:
Step 11 : RUN gem install bundler && bundle install
---> Running in 7f8e7442b423 ERROR: Error installing bundler:
bundler requires Ruby version >= 2.3.0.
I don't know how to fix this.

This is a result of a release of a new Bundler version 2.0.0 that happened on January 03, 2019. According to GitHub issue this is a desired behaviour.
As this is an old and not maintained anymore project the best option for you would be using older bundler.
You can modify the line from your Dockerfile:
RUN gem install bundler && bundle install
to the following:
RUN gem install bundler -v '$OLD_BUNDLER_VERSION' && bundle install
where $OLD_BUNDLER_VERSION should be set to last known working version, i.e. 1.16.1

Try a newer version of ruby image as your base. You are using 2.1 ( FROM ruby:2.1 ) but you need ruby version 2.3.0

My way is to use the correct bundler version and run it like this:
ENV BUNDLER_VERSION 2.2.26
RUN gem update --system \
&& gem install bundler -v $BUNDLER_VERSION \
&& bundle install -j 4

Related

RDS related error when deploying a Docker Rails 6 app to AWS ECS

I am trying to deploy a Rails 6 app to AWS ECS.
The deployment fails, and I got the following error:
health_check failed: Plugin http could not be loaded: Error loading
shared library lib/mariadb/plugin/http.so: No such file or directory
Gemfile
gem 'rails', '~> 6.0.0'
gem 'mysql2'
Gemfile.lock
mysql2 (0.5.3)
rails (6.0.3.6)
I am not using MariaDB in my app, but according to the mysql2 gem author, it might be necessary to add MariaDB dependencies.
You may need to install a package such as libmariadb-dev, libmysqlclient-dev, mysql-devel, or default-libmysqlclient-dev; refer to your distribution's package guide to find the particular package. The most common issue we see is a user who has the library file libmysqlclient.so but is missing the header file mysql.h -- double check that you have the -dev packages installed.
Dockerfile
###############################
FROM ruby:2.6.3-alpine
ARG RAILS_ENV
ENV RAILS_ENV ${RAILS_ENV}
RUN apk add --update --no-cache \
build-base \
openssl \
mysql-dev \
mariadb-dev \
git \
tzdata && \
cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
WORKDIR /app
ADD Gemfile* /app/
RUN gem install --no-document bundler
RUN bundle install -j4 --retry 3 \
&& rm -rf /usr/local/bundle/cache/*.gem \
&& find /usr/local/bundle/gems/ -name "*.c" -delete \
&& find /usr/local/bundle/gems/ -name "*.o" -delete
# Add the Rails app
ADD . /app
WORKDIR /app
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
I built my app with:
docker-compose build --no-cache
Any help would be highly appreciated.
The error was related to the DB address format.
To make it work, I removed the http:// prefix and the trailing / to the DB address env variable.
I changed:
DB_HOST=http://abcdef-rds.xyz.ap-northeast-1.rds.amazonaws.com/
to:
DB_HOST=abcdef-rds.xyz.ap-northeast-1.rds.amazonaws.com

linux source command not working when building Dockerfile

I have a Dockerfile that defines a Ruby on Rails stack.
Here is the Dockerfile:
FROM ubuntu:14.04
MAINTAINER example <examplen#example.com>
# 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.

ImageMagick on Google Cloud

I use ImageMagick on the Google Cloud Platform. I use rails and Google's App Engine Flexible Environment. So the problem is I want to upload an Image to process in more sizes. I use paperclip.
The error is:
Could not run the identify command. Please install ImageMagick.
So my question is how I can solve this issue? Uploading a Image without processing works 100%. But the issue is the processing I think. So paperclip needs ImageMagick to process the images.
The problem is I use App Engine Flexible Environment so I am not sure how to install it. I already tried it with apt-get install imageMagick
Okay really simple you need just a Dockerfile.
# This Dockerfile for a Ruby application was generated by gcloud.
# The base Dockerfile installs:
# * A number of packages needed by the Ruby runtime and by gems
# commonly used in Ruby web apps (such as libsqlite3)
# * A recent version of NodeJS
# * A recent version of the standard Ruby runtime to use by default
# * The bundler and foreman gems
FROM gcr.io/google_appengine/ruby
# Install ruby 2.3.0 if not already preinstalled by the base image
RUN cd /rbenv/plugins/ruby-build && \
git pull && \
rbenv install -s 2.3.0 && \
rbenv global 2.3.0 && \
gem install -q --no-rdoc --no-ri bundler --version 1.11.2 && \
gem install -q --no-rdoc --no-ri foreman --version 0.78.0
ENV RBENV_VERSION 2.3.0
# To install additional packages needed by your gems, uncomment
# the "RUN apt-get update" and "RUN apt-get install" lines below
# and specify your packages.
# RUN apt-get update
# RUN apt-get install imagemagick -y
RUN apt-get update && apt-get install imagemagick -y
# Install required gems.
COPY Gemfile Gemfile.lock /app/
RUN bundle install && rbenv rehash
# Start application on port 8080.
COPY . /app/
ENTRYPOINT bundle exec rackup -p 8080 -E production config.ru
After that just run gcloud preview app deploy and it will work for you.
Don't forget to change in your app.yaml runtime: ruby to runtime: custom
That's it happy coding 🎉

Issue with docker and bundler

I'm running some issues with docker/docker-compose and bundler. After building my image I can run the rails server correctly without any issue, but, when I try to run a console with rails console I constantly get:
Could not find i18n-0.7.0 in any of the sources
Run `bundle install` to install missing gems.
If I try to run bundle install in the container there is no problem, all seems to be correctly installed.
docker-compose run web bundle install
...
Using spring 1.3.6
Using therubyracer 0.12.2
Using turbolinks 2.5.3
Using uglifier 2.7.2
Using web-console 2.2.1
Updating files in vendor/cache
Bundle complete! 24 Gemfile dependencies, 119 gems now installed.
Bundled gems are installed into /usr/local/bundle.
My docker-compose.yml looks like this:
db:
image: postgres
web:
build: .
command: rails s -p 3000 -b 0.0.0.0
ports:
- "3000:3000"
volumes:
- .:/app
- ./github_rsa:/root/.ssh/id_rsa
links:
- db
I need to mount a volume with the ssh key because there are some gems that need to be pulled from private repositories.
My Dockerfile looks like this:
FROM ruby:2.2.0
RUN apt-get update -qq && apt-get install -y build-essential \
libpq-dev \
libxml2-dev libxslt1-dev \
nodejs
ENV HOME /root
ENV APP_HOME /app
RUN mkdir $APP_HOME
RUN mkdir $APP_HOME/tmp
RUN mkdir $APP_HOME/log
# Copy the Gemfile and Gemfile.lock into the image.
# Temporarily set the working directory to where they are.
WORKDIR /tmp
ADD Gemfile Gemfile
ADD Gemfile.lock Gemfile.lock
# Copy the github key for pulling gems
COPY github_rsa /root/.ssh/id_rsa
RUN \
chown -R root:root /root/.ssh && \
chmod 700 $HOME/.ssh && \
chmod 600 $HOME/.ssh/id_rsa
RUN echo "Host github.com\n\tStrictHostKeyChecking no\n" >> /root/.ssh/config
# Start ssh agent and add keys
RUN eval "$(ssh-agent)" && \
ssh-add && \
ssh-add -l
# Install bundler
RUN gem install bundler -v '~> 1.10'
# Install ruby dependencies
RUN bundle install
# Remove the ssh key now, we don't want to ship secrets on our images
RUN rm /root/.ssh/id_rsa
# Add app to container
ADD . $APP_HOME
# Add container working directory
WORKDIR $APP_HOME
# Expose puma port
EXPOSE 3000
You need to take this image down immediately. The following does not work:
RUN rm /root/.ssh/id_rsa
You cannot remove files like this; they will still exist in previous layers and be accessible to anyone who has the image. At the moment, you are shipping your secrets.
Regarding the actual question, I suspect it's just to do with the working directory and paths. Try moving RUN bundle install to after the WORKDIR instruction.

bundler installed gems not persisting in fig/docker

I am trying to use fig and docker to set up a local development environment for an existing rails app.
In the build process, I clearly see bundler installing the app's gems, but when I try to start the container with fig up or even reopen it with the /bin/bash command, the gems are not visible.
Here is the Dockerfile:
FROM ubuntu:14.04
# REPOS
RUN apt-get -qq update
RUN apt-get install -y software-properties-common
RUN add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) universe"
RUN add-apt-repository -y ppa:chris-lea/node.js
RUN apt-get -y update
#INSTALL
RUN apt-get install -y -q build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison pkg-config libpq-dev make wget unzip git vim nano nodejs gawk libgdbm-dev libffi-dev
#RUBY
RUN mkdir -p /download
WORKDIR download
RUN wget http://cache.ruby-lang.org/pub/ruby/2.1/ruby-2.1.2.tar.gz
RUN tar xvfz ruby-2.1.2.tar.gz
WORKDIR /download/ruby-2.1.2
RUN ./configure
RUN make
RUN make install
RUN gem update --system
RUN gem install bundler
RUN mkdir /rent
WORKDIR /rent
ADD Gemfile /rent/Gemfile
ADD Gemfile.lock /rent/Gemfile.lock
RUN bundle install --deployment
And here is the fig.yml file:
web:
build: .
command: bundle exec rails s -p 3000
volumes:
- .:/rent
ports:
- "3000:3000"
Running fig build clearly shows the app's gems being installed.
Running fig up fails with the message
bundler: command not found: rails
If I run fig run web /bin/bash and check the contents of
/local/lib/ruby/gems/2.1.0/gems
it only has bundler, rdoc, rake and a few others installed.
If I navigate to the app's directory and run the bundle command, it will install the app's gems and I can see that they are installed in the directory above. I can even start the app with rails server.
Why aren't the bundled gems being persisted in the image(container?).
I ran the rails tutuorial from the fig website and didn't have this problem.
Thanks
It seems that the problem was caused by using the --deployment flag with bundle install.
This flag's main effect is to deploy the gems to the vendor/bundle/ directory instead of the normal gem location. I checked and the gems were there, so I'm not sure why ruby couldn't find them.
Anyways, removing --deployment fixed the problem.
If you're using fig and mounted volumes, I found a solution which allows updates to the mounted files in development (like Gemfile.lock when you do fig run web bundle install) while still keeping container caching behavior.
See this for the full thing: https://gist.github.com/fotinakis/04077671bec4edf77c08
It's slightly convoluted, but basically you always install bundler and the gems as the non-root application user:
# Add 'web' user which will run the application.
RUN adduser web --home /home/web --shell /bin/bash --disabled-password --gecos ""
# Add directory where all application code will live and own it by the web user.
RUN mkdir /app
RUN chown -R web:web /app
# Install gems separately here to take advantage of container caching of `bundle install`.
# Also, ensure that gems are installed as the web user and not system-wide so that we can run
# `fig web bundle install` and the web user will have permissions to update the shared Gemfile.lock.
ADD Gemfile /app/
ADD Gemfile.lock /app/
RUN chown -R web:web /app
USER web
ENV HOME /home/web
ENV PATH $PATH:/home/web/.gem/ruby/2.1.0/bin
ENV GEM_HOME /home/web/.gem/ruby/2.1.0
ENV GEM_PATH $GEM_HOME
RUN gem install --user-install bundler
WORKDIR /app/
RUN bundle install
USER root
# Add the whole application source to the image and own it all by web:web.
# Note: this is overwritten in development because fig mounts a shared volume at /app.
ADD . /app/
RUN chown -R web:web /app
Running this will now work and update your local Gemfile.lock:
$ fig run web bundle install

Resources