#ruby-on-rails #ruby #docker #bundler
#ruby-on-rails #ruby #docker #bundler
Вопрос:
Я создал образ и контейнер Docker с помощью docker-compose, который состоит из приложения Rails, поддерживаемого PostgreSQL. Rails предназначен для запуска через docker-entrypoint.sh
файл, который выглядит следующим образом:
#!/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
Однако контейнер останавливается сразу после запуска с этой ошибкой:
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)>'
Поскольку, насколько мне известно, вы не можете напрямую исследовать файловую систему остановленного контейнера, я экспортировал всю файловую систему в .tar
файл:
docker export a2410e604db9 > container.tar
Заглянув внутрь container.tar
, я обнаружил, что там есть /usr/local/bundle/bin/rails
исполняемый файл, поэтому я не знаю, почему bundle не сможет загрузить эту команду.
Другой каталог, упомянутый в ошибке, /usr/local/bundle/specifications/exe/rails
не существует. Есть только /usr/local/bundle/specifications
, который содержит кучу .gemspec
файлов для проекта Rails и ничего больше.
Что вызывает эту bundler
/ LoadError
проблему?
Комментарии:
1. Как вы запускаете контейнер? Если изображение не настроено на его игнорирование (предоставленный вами скрипт запускается как изображение
CMD
, а не егоENTRYPOINT
), вы можетеdocker run --rm -it your-image bash
создать интерактивную оболочку для просмотра изображения.2. @DavidMaze Я знал об интерактивной оболочке, но мой контейнер останавливается сразу после его запуска, поэтому, насколько я могу судить, получить интерактивную оболочку невозможно. Приведенный выше скрипт выполняется как
ENTRYPOINT
, однако, в моем Dockerfile:ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]
.3. Если вы измените это на
CMD
, вы можете переопределить его во время выполнения, как показано выше. Вы также можете разделитьENTRYPOINT
иCMD
; если вы создадите последнюю строку скрипта,exec bundle exec "$@"
тогда любая переданная вами команда (по умолчанию:CMD rails s -b 0.0.0.0
) будет запущена в контексте пакета.4. @DavidMaze Не уверен, что понимаю. Я изменил последние две строки моего Dockerfile на
ENTRYPOINT ["./entrypoints/docker-entrypoint.sh"]
иCMD rails s -b 0.0.0.0
. Я изменил последнюю строку моего скрипта точки входа наexec bundle exec "$@"
. Контейнер все еще разбился сразу после запуска. Затем я запустилdocker run --rm -it 64e8e33e8fc1 bash
, и сервер Rails запустился прямо в консоли — без интерактивной оболочки, которая, как я думал, была целью, — но сервер Rails недоступен в браузере, как будто он не был запущен. Я полностью потерян.5. Хорошо, я смог получить оболочку, отказавшись от попытки в моем предыдущем комментарии и просто изменив
ENTRYPOINT
наCMD
, и ничего больше. Затем я мог бы запуститьdocker run --rm -it 93350aeeab9c sh
, чтобы вставить оболочку в изображение, которое не удалось запустить. Так что это уже кое-что.
Ответ №1:
Какой образ docker вы используете для своего приложения Rails? Если это общедоступный library/ruby
, то я предполагаю, что все необходимые env
переменные будут установлены правильно для работы вашего скрипта.
Я предлагаю поделиться вашим Dockerfile
, если это не общедоступный ruby.
Сначала посмотрите, PATH
(и сценарий) использует ли ваш пакет и rails:
docker run -it <YOUR_DOCKER_IMAGE> bash
which bundle
which rails
Если нет, попробуйте сначала запустить его вручную, прежде чем писать сценарий для диагностики проблем:
docker run -it <YOUR_DOCKER_IMAGE> bash
cd /path/to/app
bundle exec rails s -b 0.0.0.0
Наконец, убедитесь, что ваш docker-compose.yml
файл предоставляет порт, который вы ожидаете. Если это 4000
:
ports:
- "4000:4000"