2

I created a Docker image and container via docker-compose that consists of a Rails app backed by PostgreSQL. Rails is meant to start via a docker-entrypoint.sh file which looks like this:

#!/bin/sh

# Exit early if there are any errors.
set -e

# Check that there won't be any server conflicts.
if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

# -b binds the server to all IP addresses, rather than to localhost.
bundle exec rails s -b 0.0.0.0

However, the container stops immediately after startup with this error:

bundler: failed to load command: rails (/usr/local/bundle/bin/rails)
LoadError: cannot load such file -- /usr/local/bundle/specifications/exe/rails
  /usr/local/bundle/bin/rails:23:in `load'
  /usr/local/bundle/bin/rails:23:in `<top (required)>'

Since to my knowledge you can't directly explore the filesystem of a stopped container, I exported the entire filesystem to a .tar file:

docker export a2410e604db9 > container.tar

Looking inside of container.tar, I found that there is a /usr/local/bundle/bin/rails executable file, so I don't know why bundle wouldn't be able to load that command.

The other directory that is mentioned in the error, /usr/local/bundle/specifications/exe/rails, does not exist. There is only /usr/local/bundle/specifications, which contains a bunch of .gemspec files for the Rails project and nothing else.

What is causing this bundler/LoadError problem?

David Gay
  • 1,094
  • 2
  • 16
  • 32
  • How are you running the container? If the image isn't configured to ignore it (the script you provide is run as the image's `CMD`, not its `ENTRYPOINT`) you can `docker run --rm -it your-image bash` to get an interactive shell on the image to poke around. – David Maze Sep 15 '20 at 18:38
  • @DavidMaze I did know about the interactive shell, but my container stops right after it starts, so as far as I can tell, it's impossible to get an interactive shell. The script I provided above _is_ run as an `ENTRYPOINT`, though, in my Dockerfile: `ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]`. – David Gay Sep 15 '20 at 19:22
  • If you change that to `CMD` then you can override it at run time as shown above. You can also split the `ENTRYPOINT` and `CMD`; if you make the last line of the script `exec bundle exec "$@"` then whatever command you pass (default: `CMD rails s -b 0.0.0.0`) will get run in the Bundler context. – David Maze Sep 15 '20 at 20:16
  • @DavidMaze Not sure I understand. I changed the last two lines of my Dockerfile to `ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]` and `CMD rails s -b 0.0.0.0`. I changed the last line of my entrypoint script to `exec bundle exec "$@"`. The container still crashed immediately after start. I then ran `docker run --rm -it 64e8e33e8fc1 bash`, and the Rails server started right there in the console -- no interactive shell, which I thought was the goal -- but the Rails server is inaccessible in the browser, as though it wasn't running. I'm completely lost. – David Gay Sep 16 '20 at 13:32
  • OK, I was able to get a shell by scrapping the attempt in my previous comment, and simply changing `ENTRYPOINT` to `CMD`, and nothing else. I could then run `docker run --rm -it 93350aeeab9c sh` to get a shell into the image that failed to start. So that's something. – David Gay Sep 16 '20 at 17:15

1 Answers1

0

What docker image are you using for your rails app? If it's the public library/ruby one then I presume all the required env variables will be set correctly for your script to work.

I suggest sharing your Dockerfile if it isn't the public ruby one.

First see if your PATH (and script) are using the intended bundle and rails:

docker run -it <YOUR_DOCKER_IMAGE> bash
which bundle
which rails

If not, try running it manually first before scripting to diagnose issues:

docker run -it <YOUR_DOCKER_IMAGE> bash
cd /path/to/app
bundle exec rails s -b 0.0.0.0

Lastly, ensure your docker-compose.yml file exposes the port you're expecting. If it's 4000:

ports:
      - "4000:4000"
chuckwired
  • 147
  • 1
  • 6