Could not find rake-11.1.2 in rails docker container - ruby-on-rails

I'm running two docker containers. One with rails and one with Postgres db.
Here is my docker-compose file:
# Docs: https://docs.docker.com/compose/compose-file/
version: '2'
services:
db:
image: postgres
environment:
- POSTGRES_PASSWORD=xxx
rails:
build: .
command: rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app
ports:
- "3000:3000"
links:
- db
depends_on:
- db
Here the Dockerfile for the rails app:
FROM ruby:2.3
RUN apt-get update
RUN apt-get install -y build-essential nodejs
RUN mkdir -p /app
WORKDIR /app
COPY Gemfile Gemfile.lock ./
RUN gem install bundler && bundle install --jobs 20 --retry 5
COPY . ./
EXPOSE 3000
ENTRYPOINT ["bundle", "exec"]
CMD ["rails", "server", "-b", "0.0.0.0"]
When I run docker-compose up everything works fine and I can connect to the server via the ip address from docker-machine.
When I try to connect to the container with the following command:
docker-compose run rails console
I get this error:
Could not find rake-11.1.2 in any of the sources
Run `bundle install` to install missing gems.
bundle install inside the container has no effect and the mentioned gem is definitely installed. In other stack-overflow questions were mentioned that I should run bin/spring stop. So I ran:
docker-compose run bin/spring stop
And it returns:
Spring is not running
I'm still comparibly new to ruby/rails and docker. I hope someone can help me here!
Thanks in advance
PS: Comments on the Dockerfiles are appreciated!

seems to be a late response but I will answer anyway. My educated guess is that your Gemfile.lock is pinning your rake version and that is why it is complaining. If you run the docker build without a volume defined like in your docker-compose.yml you can easily end up like this. So give it a try.
In regard to your Dockerfile: If you use this only for development purposes then this might be ok. Otherwise you should think about running it using a different user (create user with useradd and run RUN tasks and so on accordingly). You might also want to use some bundler features like the --path=<path> option.

We had the exact same problem. Even though Spring said it was not running, my colleague pointed out to me if I looked into bin/rails I'd see that it would, in fact, run with Rails. Removing the spring related gems in Gemfile solved the problem.

I managed to solve this by using this command in my Dockerfile.
RUN bundle install --without development test --with runtime --deployment

Related

Generating files in Docker vs. Docker Compose

I am learning Docker and have a little confusion that I would greatly appreciate some advice on.
When creating a new rails application. Following the guidelines of Docker's tutorial Quickstart: Compose & Rails. They're steps are as follows.
Create Dockerfile & Entrypoint
Create Gemfile with source and rails gem listed.
Create an empty Gemfile.lock
Create a docker-compose.yml and name services.
Generate a new rails app using docker-compose run.
The rails new command.
docker-compose run --no-deps web rails new . --force -d mysql
This is my simple Dockerfile:
FROM ruby:3.1.1-alpine3.15
RUN apk update -q
RUN apk add bash yarn git build-base nodejs mariadb-dev tzdata
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
COPY package.json /app/package.json
COPY yarn.lock /app/yarn.lock
RUN gem install bundler
RUN gem update bundler
RUN bundle install
COPY entrypoint.sh /usr/bin
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
This is my docker-compose.yml:
version: "3.9"
services:
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/app
ports:
- "3000:3000"
As you can see I only have one service listed in my docker-compose.yml, because I do not want any other services or containers.
Everything works fine when I use the command docker-compose run rails new ... it generates a new rails app and persists the files to my local source folder. So I can open and edit the files to develop the application. Perfect.
But when I try and generate a new Rails app without using docker-compose.yml and only the Dockerfile. The generated files are not persisted in my local source folder, only on the container. I can only assume because I am forced to build the image before running it in a container to generate the new rails app.
When using without docker-compose.yml. I have to build the image first.
docker build -t image_name .
Then I can run the container and generate the rails app.
docker run image_name rails new . --force -d mysql
Obviously, this doesn't persit the new files in my local source folder.
How can I generate a new Rails app with just my Dockerfile without docker compose and still have the newly generated files persist in my local source folder?
I must be missing something, but I've done a lot of research and can't find an answer.
In docker-compose.yml you have a 'volumes' key as seen below.
volumes:
- .:/app
But when using it in the CLI you miss passing these volumes.
You can pass these volumes as in the code below.
docker run -d --name=rails --volume /your/workdir:/app image_name
If you want to learn more about volumes, you can find out here.

Unable to run "rails g" commands in docker cli

I am unable to run rails g commands in the docker CLI.
It is throwing the following error, even though everything is already installed and running.
Could not find rake-12.3.2 in any of the sources
Run `bundle install` to install missing gems.
rails db:create and rails db:migrate are fine.
I have tried running the commands from inside the docker CLI and via docker-compose run, and they throw the same error.
My dockerfile, named Dockerfile.dev is as follows
# syntax=docker/dockerfile:1
FROM ruby:2.6.2-stretch
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN gem install bundler && bundle install
RUN rails db:create db:migrate
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]
My docker-compose file as as follows
version: "3.9"
services:
db:
image: postgres
volumes:
- ./tmp/db:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: password
web:
build:
context: .
dockerfile: Dockerfile.dev
image: project-x-image-annotator:v1
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/app
ports:
- "3000:3000"
depends_on:
- db
Another development is that I have 2 copies of rake, but only 1 rails.
xxxx#yyyy project-x % docker-compose run web whereis rails
[+] Running 1/0
⠿ Container project-x-db_1 Running 0.0s
rails: /usr/local/bundle/bin/rails
xxxx#yyyy project-x % docker-compose run web whereis rake
[+] Running 1/0
⠿ Container project-x-db_1 Running 0.0s
rake: /usr/local/bin/rake /usr/local/bundle/bin/rake
I finally solved it.
I think the Gemfile.lock had conflicts on it that affected my container but not my buddy's.
I removed the Gemfile.lock and ran bundle install. This fixed the issue of rails g not working.
Would love to hear from a rails expert on why the bundle install did not make an entirely new lock file when run inside the container.

Rails bundle "Can't find GEM in any of the sources" in Docker Container only

I'm using Rails in a Docker container, and every once in a while I run into this issue that I have no idea how to solve. When adding a new gem to the Gemfile, upon rebuilding the Docker Image + Container, the build will fail with the common bundler error Could not find [GEM_NAME] in any of the sources; Run 'bundle install' to install missing gems. This only occurs to me when I try to build the image in Docker, if I run a regular bundle install on my local machine, the Gemfile gets installed correctly and everything works as expected.
I have a fairly standard Dockerfile & docker-compose file.
Dockerfile:
FROM ruby:2.6.3
ARG PG_MAJOR
ARG BUNDLER_VERSION
ARG UID
ARG MODE
# Add POSTGRESQL to the source list using the right version
RUN curl -sSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& echo 'deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main' $PG_MAJOR > /etc/apt/sources.list.d/pgdg.list
ENV RAILS_ENV $MODE
RUN apt-get update -qq && apt-get install -y postgresql-client-$PG_MAJOR vim
RUN apt-get -y install sudo
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
COPY Gemfile /usr/src/app/Gemfile
COPY Gemfile.lock /usr/src/app/Gemfile.lock
ENV BUNDLER_VERSION $BUNDLER_VERSION
RUN gem install bundler:$BUNDLER_VERSION
RUN bundle install
COPY . /usr/src/app
# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000
# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
docker-compose.yml:
version: '3'
services:
backend:
build:
dockerfile: Dockerfile
args:
UID: ${UID:-1001}
BUNDLER_VERSION: 2.0.2
PG_MAJOR: 10
mode: development
tty: true
stdin_open: true
volumes:
- ./[REDACTED]:/usr/src/app
- gem_data_api:/usr/local/bundle:cached
ports:
- "3000:3000"
user: root
I've tried docker system prune -a, docker builder prune -a, reinstalling Docker, multiple rebuilds in a row, restarting my machine and so on, to no avail. The weird part is that it doesn't happen with every new Gem that I decide to add, only for some specific gems. For example I got this issue once again when trying to add gem 'sendgrid-ruby' to my Gemfile. This is the repo for the gem for reference, and the specific error I get with sendgrid-ruby is Could not find ruby_http_client-3.5.1 in any of the sources. I tried specifying ruby_http_client in my Gemfile, and I also tried sshing into the Docker container and running gem install ruby_http_client, but I get the same errors.
What might be happening here?
You're mounting a named volume over the container's /usr/local/bundle directory. The named volume will get populated from the image, but only the very first time you run the container. After that the old contents of the named volume will take precedence over the content of the image: using a volume this way will cause Docker to completely ignore any changes you make in the Gemfile.
You should be able to delete that volumes: line from the docker-compose.yml file. I'm not clear what benefit you would get from keeping the installed gems in a named volume.

getting bundler load error frequently and no such file Gemfile error

Below is the docker file in project's root directory:-
FROM ruby:2.2
MAINTAINER technologies.com
RUN apt-get update -qq && apt-get install -y build-essential
RUN apt-get install -y libxml2-dev libxslt1-dev
RUN apt-get install -y libqt4-webkit libqt4-dev xvfb
RUN apt-get install -y nodejs
ENV INSTALL_PATH /as_app
RUN mkdir -p $INSTALL_PATH
WORKDIR $INSTALL_PATH
COPY Gemfile Gemfile
RUN bundle install
COPY . .
EXPOSE 3000
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]
Below is the contents in docker-compose.yml file in project's root directory :-
as_web:
build: .
environment:
- RAILS_ENV=development
- QUEUE=*
- REDIS_URL=redis://redis:6379
volumes:
- .:/as_app
ports:
- 3000:3000
links:
- as_mongo
- as_redis
command: rails server -b 0.0.0.0
as_mongo:
image: mongo:latest
ports:
- "27017:27017"
as_redis:
image: redis
ports:
- "6379:6379"
as_worker:
build: .
environment:
- QUEUE=*
- RAILS_ENV=development
- REDIS_URL=redis://redis:6379
volumes:
- .:/as_app
links:
- as_mongo
- as_redis
command: bundle exec rake environment resque:work
docker version 1.11.2, docker-machine version 0.8.0-rc1, docker-compose version 1.8.0-rc1, ruby 2.2.5, rails 4.2.4.
My problem is as:-
1) When I build the image with "docker-compose build" from project root directory the image builds successfully with gems installed.
2) But when I do "docker-compose up" the as_web and as_worker services exits with code 1 and 10 resp. giving error as no gemfile or .bundler found. When I login in image through bash and see the working directory then no project files are seen.
3) Knowledge I want to know is:-
i) when I start terminal, I start VirtualBox instance manually like "docker-machine start default"
ii) Then I execute command "eval $(docker-machine env dev)" to point current shell to virtualbox docker-daemon, So after this when i do "docker build -t as_web ." the terminal gives message like "sending current build context to docker daemon",
a) Is this message saying that build in being done in VirtualBox ?
if I do "docker-compose build" no such message like "sending...." appears,
B) Does docker-compose too point to docker daemon in virtual box or it's being build in localhost(myubuntuOS), I'm little bit confused?
Hoping you guys understood the details if you need any extra info. then let me know, Thanking you all. Happy Coding.
docker-compose build and docker build both do the same thing. They both use the docker engine API to build an image in the virtualbox. The output messages are just a little different.
Your problem is because of this:
volumes:
- .:/as_app
You're overriding the app directory with the project directory from the host. If you haven't run bundle install on the host, the files won't be in the container when it starts.
You can fix this by running docker-compose run as_app bundle install

Docker rails migrations

I'm trying to get running my rails application with docker and fig, it counts with a redis server, mongodb, postgres, and nginx as well,
Here is how my fig.yml looks like:
pg:
image: docker-index.my.com/postgres
ports:
- 5432
redis:
image: docker-index.my.com/redis
ports:
- 6379
mongodb:
image: docker-index.my.com/mongodb
ports:
- 27017
app:
build: .
command: bundle exec rails s
volumes:
- .:/beesor
ports:
- 3000:3000
links:
- pg
- redis
- mongodb
environment:
RAILS_ENV: production
Everything works ok till the moment of starting app, as rails initializers hooks on server starts then I got errors regarding the database connection, the database does not exists! of course because it was not created on the Dockerfile (see below)
Dockerfile contents:
# DOCKER-VERSION 0.10.0
FROM docker-index.my.com/ruby:1.9.3
MAINTAINER my.com
RUN apt-get update -qq && apt-get install -y git-core xvfb curl nodejs libqt4-dev libgtk2.0-0 libgtkmm-3.0-1 libnotify4 sqlite3 libsqlite3-dev graphicsmagick imagemagick subversion libpq-dev libxml2-dev libxslt-dev git build-essential
RUN mkdir /my_app
WORKDIR /my_app
RUN gem install bundler
ADD Gemfile /my_app/Gemfile
ADD Gemfile.lock /my_app/Gemfile.lock
RUN bundle install
RUN bundle pack --all
ADD . /my_app
I don't see a place where I can put the rake db:create db:migrate db:seed commands!, if I put them at the end of the Dockerfile then when fig tries to build app it complains about the database server does not exits, (in the time that fig builds app container the other containers are not started), and I could not fix this changing the order on the fig.yml,
I'm facing egg-chicken problem here, who can I get this working?
I'm sure that all the links work perfectly so the problem is more about orchestration of scripts.
Found the solution!:
I created a rake task to wrap what I need, it runs migrations, seeds, and starts the rails server, so the fix is to change the command on fig by this one:
command: rake my_app:setup

Resources