Whenever gem 'failed to load command: rake' - ruby

looking for some help.
I am running a rails app (v3.2.5) with the whenever gem (v0.9.7) and rake (v11.2.2). I am also doing this in a docker container image ruby:2.3 (cron was installed and bundle install was ran)
Here is my schedule.rb
set :environment, ENV['RAILS_ENV']
every '*/2 9,10,11,12,13,14,15,16 * * 1-5' do
rake "import_csv", output: {:error => 'log/import_csv_errors.log', :standard => 'log/import_csv.log'}'
end
note RAILS_ENV is set at container launch to development
Here is my cron job that is on the container after build (crontab -l):
# Begin Whenever generated tasks for: /usr/src/app/config/schedule.rb
*/2 9,10,11,12,13,14,15,16 * * 1-5 /bin/bash -l -c 'cd /usr/src/app && RAILS_ENV=development bundle exec rake import_csv --silent >> log/import_csv.log 2>> log/import_csv_errors.log'
# End Whenever generated tasks for: /usr/src/app/config/schedule.rb
When this cron job runs, the logs return:
import_csv_errors.log
Bundler::GemNotFound: Could not find rake-11.2.2 in any of the sources
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/spec_set.rb:95:in `block in materialize'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/spec_set.rb:88:in `map!'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/spec_set.rb:88:in `materialize'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/definition.rb:140:in `specs'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/definition.rb:185:in `specs_for'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/definition.rb:174:in `requested_specs'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/environment.rb:19:in `requested_specs'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:14:in `setup'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler.rb:95:in `setup'
/usr/local/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/setup.rb:19:in `<top (required)>'
/usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
/usr/local/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
import_csv.log
bundler: failed to load command: rake (/usr/local/bin/rake)
Now here is the odd thing. If I copy the cron job command:
/bin/bash -l -c 'cd /usr/src/app && RAILS_ENV=development bundle exec rake import_csv --silent >> log/import_csv.log 2>> log/import_csv_errors.log'
and run this in the container, it works fine, but if the cron job runs it, I get thos errors in the logs!!! I am at a lost here...
I've tried adding
env :PATH, ENV['PATH']
env :GEM_PATH, '/usr/local/bundle'
to the top of schedule.rb and I tried doing
command 'cd /usr/src/app && RAILS_ENV=development bundle exec rake import_csv --silent >> log/import_csv.log 2>> log/import_csv_errors.log'
Instead of using rake in the task and I get the same errors..
Any help is appriciated

I've fixed the same error by modifying the Dockerfile with:
RUN gem update --system 2.6.12
RUN gem install bundler --version 1.14.6
And schedule.rb:
ENV.each { |k, v| env(k, v) }

I have updated my rake version and it worked for me. Below are the steps I followed:
sudo bundle update rake
sudo bundle install
Open a Rakefile and replace the line rake/rdoctask with require 'rdoc/task'.

I resolved my issue by using a different image and building as I needed it instead of using docker hub image ruby:2.x.
Dockerfile (edited to fit thread):
FROM ubuntu:14.04
# Installs needed to run rails on ubuntu 14.04 (must use mysql 5.6 or 5.5):
RUN apt-get update && apt-get install -y apache2 curl git build-essential libmysqlclient-dev mysql-server-5.6 nodejs make
RUN apt-get update && apt-get install -y ruby-dev zlib1g-dev
RUN gem install rails --version 3.2.5 --no-ri --no-rdoc
# Update ruby to v2.2 (optional)
RUN apt-get install -y software-properties-common && apt-add-repository ppa:brightbox/ruby-ng
RUN apt-get update && apt-get install -y ruby2.2
# Install cron
RUN apt-get install -y cron
# Finish the build
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# If you code is in the same directory you ran docker build then:
COPY . /usr/src/app
RUN bundle install
RUN whenever --update-crontab
CMD ["passenger start"]

Related

Unable to install ruby from source in ubuntu 18.04 docker image

I am installing ruby 2.7.2 on a docker container that uses ubuntu:18.04.c I first tried to install rbenv but it did not offer the version I need so I resorted to installing from source. However when installing from source the make install does not pass. This is the method I used to install from source https://coderwall.com/p/3u__pq/install-ruby-from-source-on-ubuntu and this is what I looked at to resolve my issues to no avail Unable to locate package openssl-dev. Also I cannot install rvm as it is not picked up by bash.
docker file
#
# Ubuntu Dockerfile
#
# https://github.com/dockerfile/ubuntu
#
# Pull base image.
FROM ubuntu:18.04
ARG APP_NAME=<appname>
# Install.
RUN \
apt-get update && \
apt-get -y upgrade && \
apt-get install -y build-essential openssl libssl-dev zlib1g-dev&& \
apt-get install -y software-properties-common && \
apt-get install -y byobu curl git htop man unzip vim wget openssl libffi-dev &&\
rm -rf /var/lib/apt/lists/*
RUN \
wget https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.bz2 &&\
tar -xf ruby-2.7.2.tar.bz2
RUN cd ruby-2.7.2
RUN pwd
RUN ./ruby-2.7.2/configure --prefix=/my/ruby/dir
RUN make
RUN make install
# Set environment variables.
EXPOSE 5000
ENV HOME /root
ENV PATH="${PATH}:/my/ruby/dir"
# Define working directory.
WORKDIR /root
COPY ${APP_NAME}/ ./${APP_NAME}/
# Define default command.
CMD ["bash"]
When I did make install it is complaining that openssl is not installed however I did do apt install openssl
*** Following extensions are not compiled:
openssl:
Could not be configured. It will not be installed.
/ruby-2.7.2/ext/openssl/extconf.rb:97: OpenSSL library could not be found. You might want to use --with-openssl-dir=<dir> option to specify the prefix where OpenSSL is installed.
Check ext/openssl/mkmf.log for more details.
dbm:
Could not be configured. It will not be installed.
Check ext/dbm/mkmf.log for more details.
readline:
Could not be configured. It will not be installed.
/ruby-2.7.2/ext/readline/extconf.rb:62: Neither readline nor libedit was found
Check ext/readline/mkmf.log for more details.
gdbm:
Could not be configured. It will not be installed.
Check ext/gdbm/mkmf.log for more details.
zlib:
Could not be configured. It will not be installed.
Check ext/zlib/mkmf.log for more details.
*** Fix the problems, then remove these directories and try again if you want.
Later on this is the error message
Traceback (most recent call last):
11: from ./tool/rbinstall.rb:947:in `<main>'
10: from ./tool/rbinstall.rb:947:in `each'
9: from ./tool/rbinstall.rb:950:in `block in <main>'
8: from ./tool/rbinstall.rb:799:in `block in <main>'
7: from ./tool/rbinstall.rb:835:in `install_default_gem'
6: from ./tool/rbinstall.rb:835:in `each'
5: from ./tool/rbinstall.rb:845:in `block in install_default_gem'
4: from ./tool/rbinstall.rb:279:in `open_for_install'
3: from ./tool/rbinstall.rb:846:in `block (2 levels) in install_default_gem'
2: from /ruby-2.7.2/lib/rubygems/specification.rb:2430:in `to_ruby'
1: from /ruby-2.7.2/lib/rubygems/core_ext/kernel_require.rb:92:in `require'
/ruby-2.7.2/lib/rubygems/core_ext/kernel_require.rb:92:in `require': cannot load such file -- openssl (LoadError)
I think your problem is here
RUN cd ruby-2.7.2
RUN pwd
RUN ./ruby-2.7.2/configure --prefix=/my/ruby/dir
You cd into ruby-2.7.2 then attempt ./ruby-2.7.2/configure ... but you are already in the directory ruby-2.7.2 so this line
RUN ./ruby-2.7.2/configure --prefix=/my/ruby/dir
should fail.
Try replacing
RUN ./ruby-2.7.2/configure --prefix=/my/ruby/dir
with
RUN ./configure --prefix=/my/ruby/dir
You could clean up your Docerfile a bit as well by removing lines like
RUN pwd

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

Configure Dockerfile to Run Cron Tasks using Whenver and Rake

I want to create a container using Docker which is will be responsible for starting recurrent rake tasks based on the Whenever gem's configuration. I have a plain ruby project (without rails/sinatra) with the following structure:
Gemfile:
source 'https://rubygems.org'
gem 'rake', '~> 12.3', '>= 12.3.1'
gem 'whenever', '~> 0.9.7', require: false
group :development, :test do
gem 'byebug', '~> 10.0', '>= 10.0.2'
end
group :test do
gem 'rspec', '~> 3.5'
end
config/schedule.rb: (whenever's configuration)
ENV.each { |k, v| env(k, v) }
every 1.minutes do
rake 'hello:start'
end
lib/tasks/hello.rb: (rake configuration)
namespace :hello do
desc 'This is a sample'
task :start do
puts 'start something!'
end
end
Dockerfile:
FROM ruby:2.5.3-alpine3.8
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories && \
apk update && apk upgrade && \
apk add build-base bash dcron && \
apk upgrade --available && \
rm -rf /var/cache/apk/* && \
mkdir /usr/app
WORKDIR /usr/app
COPY Gemfile* /usr/app/
RUN bundle install
COPY . /usr/app
RUN bundle exec whenever --update-crontab
CMD ['sh', '-c', 'crond && gulp']
I've used the following resources to get at the this point
How to run a cron job inside a docker container
https://github.com/renskiy/cron-docker-image/blob/master/alpine/Dockerfile
https://stackoverflow.com/a/43622984/5171758 <- very close to I want but no success
If I call my rake task using command line, I get the result I want.
$ rake 'hello:start'
start something!
However, I can't figure out how to make it work using Docker. The container is build but no log is written, no output is shown, nothing happens. Can someone help me showing what I'm doing wrong?
building commands
docker build -t gsc:0.0.1 .
docker container run -a stdin -a stdout -i --net host -t gsc:0.0.1 /bin/bash
Thanks all. Cheers
This is the solution to the problem I listed above. I had some issues at the Dockerfile and schedule.rb. This is what I had to change to make it work correctly.
Dockerfile
wrong echo call
wrong bundle command
change ENTRYPOINT instead of CMD
FROM ruby:2.5.3-alpine3.8
RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/main && \
apk update && apk upgrade && \
apk add build-base bash dcron && \
apk upgrade --available && \
rm -rf /var/cache/apk/* && \
mkdir /usr/app
WORKDIR /usr/app
COPY Gemfile* /usr/app/
RUN bundle install
COPY . /usr/app
RUN bundle exec whenever -c && bundle exec whenever --update-crontab && touch ./log/cron.log
ENTRYPOINT crond && tail -f ./log/cron.log
config/schedule.rb
no need to ENV.each
every 1.minutes do
rake 'hello:start'
end
UPDATE
I've created a GitHub repository and a Docker Hub repository to share with the community this progress.

Base docker healthcheck on STDOUT logs

I've got a script that outputs logs to STDOUT. I want to monitor this, and if x seconds passes without log output, the healthcheck should fail and the container should restart.
I've got something that I feel should work (using strace), but it's not. I'll post the files below. Does anyone have any idea how to solve this?
Dockerfile:
FROM ruby:2.5.1
RUN apt-get update
RUN dpkg --configure -a
ENV TZ=Europe/London
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y keyboard-configuration
RUN apt-get install -y --fix-missing curl gnupg build-essential mosh iceweasel git libappindicator1 postgresql libpq-dev xvfb xorg dbus-x11
RUN apt-get install -y --fix-missing libxss1 nodejs xfonts-100dpi xfonts-75dpi sqlite libindicator7 unzip wget curl bzip2 libssl-dev libreadline-dev zlib1g-dev strace
RUN ln -sf /usr/bin/nodejs /usr/local/bin/node
RUN gem install bundler activerecord activesupport watir watir-scroll nokogiri pg pry forgery rspec headless rake vcr webmock rails logger
WORKDIR /home/
COPY . .
HEALTHCHECK --interval=25s --timeout=5s --retries=5 CMD strace -p $(pgrep -n ruby) 2>&1 | grep -m 1 write\(
CMD ["ruby", "./test.rb"]
test.rb:
require 'logger'
$logger = Logger.new(STDOUT)
$logger.level = Logger::DEBUG
loop do
sleep 5
$logger.warn 'hi'
end
Logs are outputting as expected when running docker container log, but the health status is always starting, and shortly after starting it will consider it failed and restart. I intend to use Docker Swarm once this is working.

Docker - Ruby Dependencies installed at build time not available at container up

I am running the following command in my Dockerfile:
RUN apt-get update && apt-get -y install gnupg2
RUN gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
RUN curl -sSL https://get.rvm.io | bash -s
RUN /bin/bash -l -c ". /etc/profile.d/rvm.sh && rvm install 2.3.1 && rvm use --default 2.3.1 && gem install bundler"
# some more code
ENTRYPOINT ["/entrypoint.sh"]
In my entrypoint.sh, I am running bundle install. But it's throwing error:
bundle not found
Upon further investigation, I found that none of the dependencies installed during Docker build time seem to be available at container run time. I am probably missing something very basic. Help very appreciated.
The entrypoint.sh does not load rvm, so it doesn't see the rvm-installed Ruby or its bundler.
Load rvm in the entrypoint.sh by adding . /etc/profile.d/rvm.sh and rvm use .. before Ruby is used.

Resources