4

Error when running rails docker container with volumes bundler: failed to load command: rails (/usr/local/bundle/bin/rails) Bundler::GemNotFound: Could not find rake-12.3.2 in any of the sources

I am able to run my rails docker container without volume. But when i attach volume as such:

docker run --name rails-chat-tutorial-web \
            -e DATABASE_HOST=172.17.0.1 \
            -e DATABASE_PORT=5432 \
            -e DATABASE_USERNAME=postgres \
            -e DATABASE_PASSWORD=postgres \
            -e REDIS_URL=redis://172.17.0.1:6379/1 \
            -p 3000:3000 \
            -v $(pwd):/application rails-chat-tutorial

I will get this error output:

bundler: failed to load command: rails (/usr/local/bundle/bin/rails)
Bundler::GemNotFound: Could not find rake-12.3.2 in any of the sources
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/spec_set.rb:87:in `block in materialize'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/spec_set.rb:81:in `map!'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/spec_set.rb:81:in `materialize'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/definition.rb:170:in `specs'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/definition.rb:237:in `specs_for'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/definition.rb:226:in `requested_specs'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/runtime.rb:108:in `block in definition_method'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/runtime.rb:20:in `setup'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler.rb:107:in `setup'
  /usr/local/bundle/gems/bundler-2.0.1/lib/bundler/setup.rb:20:in `<top (required)>'
  /usr/local/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'
  /usr/local/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:59:in `require'

I have tried including these lines in my Dockerfile but still get the error:

RUN gem install rake -v '12.3.2'
RUN bundle install --binstubs
RUN bundle install --path vendor/bundle
RUN bundle install --local
RUN bun

dle install --local --path=vendor/cache

This is my Dockerfile:

FROM ruby:2.5.0-stretch

COPY ./Gemfile ./application/
COPY ./Gemfile.lock ./application/

WORKDIR /application

ENV BUNDLER_VERSION 2.0.1

RUN gem install bundler -v '2.0.1' 
RUN bundle install --deployment --without development test 
RUN apt-get update -qq && apt-get install -y build-essential 
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash - 
RUN apt-get install -y nodejs 
RUN bundle install --local --path=vendor/cache

RUN npm install yarn -g

COPY . .

ENV RAILS_ENV production 
ENV SECRET_KEY_BASE production_test_key rails c

RUN bundle exec rake assets:precompile

EXPOSE 3000

CMD bundle exec rails server

Content of Gemfile:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.5.0'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.1'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'mini_racer', platforms: :ruby
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of chromedriver to run system tests with Chrome
  gem 'chromedriver-helper'
end

group :production do
  gem 'pg'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

gem 'devise'
gem 'bootstrap', '~> 4.3.1'
gem 'jquery-rails'
gem 'simple_form'
gem 'redis'
gem 'httparty', '~> 0.17.0'
gem 'rake', '12.3.2'

If I run the rails container with shell and gem list, i get 'rake (12.3.2, 12.3.0)'

I have been on this for the past 2 days but no progress.

Thank you in advance for those who are able to provide some guidance.

Stan
  • 131
  • 1
  • 8

1 Answers1

0

When you add a docker run -v $(pwd):/application option, it hides everything in the /application directory in the image and replaces it with the content from your host system. That in particular includes the /application/vendor directory: any bundle commands in your Dockerfile are completely ignored, and your host system's ./vendor directory gets used instead.

There's not really a good answer to this, if you must have live editing and reloading in your deployed container. The Node ecosystem is similar (third-party libraries are in ./node_modules) and most similar questions are about Node rather than Ruby. Add a volume to Docker, but exclude a sub-folder suggests adding an anonymous volume for ./vendor; the first time only that you run your application it will get populated from the image, but if you later change your Gemfile it won't get updated and replicating this setup is unnecessarily complicated in cluster environments like Kubernetes.

If you want to try the anonymous-volume path, that could look like

docker run --name rails-chat-tutorial-web ... \
  -v $PWD:/application -v /application/vendor \
  rails-chat-tutorial

$EDITOR Gemfile
bundle install
docker stop rails-chat-tutorial-web
docker rm -v rails-chat-tutorial-web
docker run ...

(docker rm -v will delete the anonymous volume, and it will get recreated on the next docker run with updated contents. You've told Docker that directory contains important non-code data that must be preserved across runs.)

The sequence that's worked well for me is to develop my application in total ignorance of Docker: develop it locally, run it, write good rspec tests, and generally believe it works. Only then do I docker build and docker run an image, without bind-mounting my source code into it. If it breaks then I reproduce the issue on my local development environment, write a test for it, and fix it, then repeat the docker build; docker run sequence.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Thank you very much for your explanation. I'll definitely try out your suggestions. I'm quite new to docker and trying to make a multi-docker application. That's why I'm trying to set up the multi-docker environment and test on it first. – Stan Jul 06 '19 at 17:00
  • May I ask what does '$EDITOR Gemfile' means? Is it a command? – Stan Jul 06 '19 at 17:03
  • Whatever command you use to edit source files, like your application's `Gemfile`. – David Maze Jul 06 '19 at 22:56