When i start to run a Rails console in my docker container i got the error Could not find ..... in locally installed gems
with the list of all gems
rails s
or rails routes
work fine and i don't got errors when i build
bundle install change nothing
The one way i found to fix it is with docker-compose run web bundle install --binstubs
I doesnt find same problems here with all gems bundle install issue and i would like know what is wrong in my Docker files
Dockerfile:
# Use the official Ruby 2.5.0 image as the parent image
FROM ruby:2.5.0-slim
# Install dependencies
RUN apt-get update -qq \
&& apt-get install -y \
# Needed for certain gems
build-essential \
shared-mime-info \
# Needed for postgres gem
libpq-dev \
# Needed for mysql
default-libmysqlclient-dev \
# Needed for redis
libssl-dev \
# Needed for elastic search
libcurl4-openssl-dev \
# Needed for foreman
procps
# Set the working directory to /app
WORKDIR /app
# Copy the Gemfile and Gemfile.lock into the image and install gems
ENV BUNDLER_VERSION=2.3.26
COPY Gemfile Gemfile.lock ./
RUN gem install bundler -v $BUNDLER_VERSION && bundle install --jobs 20 --retry 5
# Copy the rest of the application code into the image
COPY . .
# Expose port 3000 for the Rails app to listen on
EXPOSE 3000
# Start the Rails app with Puma
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
Docker-compose:
version: '3.3'
services:
db:
image: mysql/mysql-server:5.7
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: app_api_dev
MYSQL_USER: app_api
MYSQL_PASSWORD: app_api
volumes:
- ./tmp/db:/var/lib/mysql
ports:
- "3306:3306"
redis:
image: redis
web:
build: .
command: bundle exec rails s -p 3000 -b '0.0.0.0'
volumes:
- .:/app
ports:
- "3000:3000"
depends_on:
- db
- redis
environment:
DATABASE_HOST: db
DATABASE_USERNAME: app_api
DATABASE_PASSWORD: app_api
DATABASE_NAME: app_api_dev
The other answer doesn't make much sense:
--binstubs
does not install gems; it generates stubs in bin/
from the gems that are already installed as part of the bundle, allowing them to be invoked without prefixing the commands with bundle exec
.RUN
statements that run each command exactly the same as before has no impact on the outcome of the commands being run, it just results in two separate Docker layers which will increase the overall size of the Docker image for no reason.There are a few actual issues that I think you're seeing. First is that you're:
WORKDIR
to /app
in your containerCOPY . .
to copy the contents of your app into /app
.
into your Docker container at /app
The result is that step 2 may as well not be happening at all; the files that you copied into /app
are ignored and Docker Compose instead reads directly from your local computer's filesystem. This is probably not the intended behavior if you're expecting to build a Docker image that contains your app.
This can be especially problematic if you're using a .dockerignore
file and expect that certain files and folders are not being copied into the image; volumes don't respect .dockerignore
and the entire directory is available at /app
.
And again this can be problematic if you're using bundle config
options like BUNDLE_PATH
and BUNDLE_CACHE_PATH
that you don't expect to be loaded into your app. You might be expecting gems to be installed to and read from locations within your Docker image's system paths but if bundle config
options you don't expect to have in place are pointing to a local path like vendor/bundle
and vendor/cache
then mounting the volume to the local path is going to use these pre-existing paths on your local system, not what's in the image.
The second issue is that you're not running commands with bundle exec
. You don't make it clear how you're attempting to run rails console
or rails server
or rails routes
but these commands need to be prefixed with bundle exec
, e.g., bundle exec rails console
. For example, if you've already run docker compose up
and the server is running:
docker exec -it web bash
And then when you're in your container:
cd /app
bundle exec rails console
If you want to use binstubs instead then before you create your Docker image you need to run bundle binstubs --all
on your local computer to create the stubs in bin/
, then to invoke those commands using the binstubs you need to run them with their relative path included, e.g.:
bin/rails console
bin/rails server
bin/rails routes
You would need to do this anywhere that you would otherwise run bundle exec rails ...
.
Finally, attempting to run them with just rails console
or rails server
is likely not going to work because it requires the Docker image itself to have those gems installed globally, and those global versions may not match your bundled versions. If you just run rails <something>
then what happens is the system will look in $PATH
to attempt to find a binary named rails
-- it does not automagically find the version of Rails that you have defined in Gemfile.lock
and does not automagically find the binary installed by bundle install
. It just finds the first responsive binary which may or may not know about your bundled application and its dependencies. Always specify the command with either bundle exec rails ...
or bin/rails ...
.