Подтвердить что ты не робот

Сервер Rails по-прежнему работает в новом открытом контейнере для докеров

Я хочу развернуть мой проект рельсов с помощью Docker. Поэтому я использую Docker-Compose. Но я получаю одно странное сообщение об ошибке. При запуске docker-compose up (это содержит db-контейнер с postgresql, redis и веб-контейнер с рельсами), я получаю

web_1 | => Booting Puma web_1 | => Rails 4.2.4 application starting in production on http://0.0.0.0:3000 web_1 | => Run web_1 | => Booting Puma web_1 | => Rails 4.2.4 application starting in production on http://0.0.0.0:3000 web_1 | => Run сервер rails -h for more startup options web_1 | => Ctrl-C to shutdown server web_1 | A server is already running. Check/usr/src/app/tmp/pids/server.pid. web_1 | Exiting for more startup options web_1 | => Ctrl-C to shutdown server web_1 | A server is already running. Check/usr/src/app/tmp/pids/server.pid. web_1 | Exiting for more startup options web_1 | => Ctrl-C to shutdown server web_1 | A server is already running. Check/usr/src/app/tmp/pids/server.pid. web_1 | Exiting Поэтому я не понимаю, почему я получаю это сообщение, потому что каждый раз, когда я запускаю сборку докеров, запускаются новые контейнеры, а не предыдущие. Даже если вы хотите удалить этот server.pid я не могу этого сделать, потому что этот контейнер не запущен.

мой файл docker-compose.yml

web:
  dockerfile: Dockerfile-rails
  build: .
  command: bundle exec rails s -p 3000 -b '0.0.0.0'
  ports:
    - "80:3000"
  links:
    - redis
    - db
  environment:
    - REDISTOGO_URL=redis://[email protected]:6379/

redis:
  image: redis

db:
  dockerfile: Dockerfile-db
  build: .
  env_file: .env_db

Dockerfile рельсы

FROM rails:onbuild

ENV RAILS_ENV=production

Я не думаю, что мне нужно опубликовать все мои Dockerfiles

UPD: я исправил его сам: я просто удалил все свои контейнеры и снова запустил docker-compose up

4b9b3361

Ответ 1

Вы используете изображение onbuild, так что ваш рабочий directcotry установлен в образ контейнера. Это очень полезно для разработки, поскольку ваше приложение обновляется в реальном времени при редактировании кода, а ваша хост-система обновляется, например, при выполнении миграции.

Это также означает, что ваш каталог tmp хост-системы будет записываться вместе с pid файлом каждый раз, когда сервер будет запущен, и останется там, если сервер не будет отключен правильно.

Просто запустите эту команду из вашей хост-системы:

sudo rm tmp/pids/server.pid 

Это может быть настоящей болью, когда вы, например, используете мастера под docker-compose, так как просто нажатие ctrl + c не удаляет файл pid.

Ответ 2

Я был в тупике той же проблемой, пока не понял, что происходит на самом деле. Реальный ответ еще ниже... Сначала вы можете попробовать что-то вроде следующей команды в файле docker-compose.yml:

command: /bin/sh -c "rm -f /rails/tmp/pids/server.pid && rails server puma"

(Я использую Alpine и busybox, чтобы держать вещи крошечными, поэтому no bash!, но -c будет работать с bash). Это приведет к удалению файла, если он существует, чтобы вы не застряли с проблемой, что контейнер продолжает выходить и сидеть там не может выполнять команды.

К сожалению, это НЕ хорошее решение, потому что вы добавляете дополнительный уровень /bin/sh впереди сервера и не позволяете серверу получить команду stop. В результате команды остановки докеры не будут давать изящный выход, и проблема всегда будет выполняться.

Вы можете просто запустить команду rm с помощью компоновки докеров, чтобы удалить файл, а затем изменить команду на сервер и продолжить.

Однако реальный ответ - создать простой файл docker -entry.sh и убедиться, что вы вызываете его с помощью формы exec Документация точки входа так что сигналы (например, остановка) попадают на серверный процесс.

#!/bin/sh
set -e

if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

exec bundle exec "[email protected]"

ПРИМЕЧАНИЕ. Мы используем exec на последней строке, чтобы убедиться, что рельсы будут выполняться как pid 1 (т.е. нет дополнительной оболочки) и, таким образом, заставить сигналы останавливаться. И затем в файле Dockerfile (или compose.yml) добавьте точку входа и команду

# Get stuff running
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["rails", "server", "puma"]

И снова, вы ДОЛЖНЫ использовать формат [], чтобы он был exec'd вместо запуска как sh -c ""

Ответ 3

Что я сделал, это пойти в оболочку bash докера:

docker-compose run web /bin/bash

затем удалите следующий файл

rm tmp/pids/server.pid

Надеюсь, что это поможет!

Ответ 4

для моей работы:

docker-compose run web bash

а затем перейдите в папку по папке с помощью команды cd (я использую панель инструментов win 7), поэтому в конце я использую в bash:

rm tmp/pids/server.pid

Ответ 5

Для тех, у кого проблемы, когда нет tmp/pids/server.pid, действительно существует:

(Docker version 1.11.2, build b9f10c9)

  • Решение, которое работало для меня, - это добавить точную команду в docker-compose.yml, например:

    command:
       rails s -b0
    

    Наличие этой команды, которая на самом деле может просто дублировать Dockerfile CMD - проблема со старым .pid, не отображается.

  • Другой вариант, когда вам нужно использовать Dockerfile CMD, - запустить с опцией --build для восстановления изображения:

    docker-compose up --build
    

    Хотя это требует времени, поэтому первое решение более удобно

Ответ 6

Это адаптированная версия Brendon Whateleys 👏 для

Решение Docker Compose

1. Создайте docker -entrypoint.sh

#!/bin/bash
set -e

if [ -f tmp/pids/server.pid ]; then
  rm tmp/pids/server.pid
fi

exec bundle exec "[email protected]"

2. Адаптируйте свой docker-compose.yml

services:
  web:
    build: .
    entrypoint: /myapp/docker-entrypoint.sh
    command: ["rails", "server", "-b", "0.0.0.0"]
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"

Обратите внимание, что вам нужно будет указать путь к месту установки вашего приложения iE: /myapp

2.5 Если вы столкнулись с ошибкой разрешения

Запустите это в своем терминале, прежде чем запускать docker-compose up или docker-compose up изображение. Спасибо саджадхавами.

chmod +x docker-entrypoint.sh

3. Никогда не удаляйте server.pid вручную

🎉

Ответ 7

Если вы чувствуете себя авантюрно, не стесняйтесь искать server.pid в кодовой базе и проверяете, куда записывается pid. Таким образом, вы можете проверить, не разрешает ли он писать исправления для вас. Поскольку, по-видимому, создание pid помогает предотвратить запуск повторяющихся сервисов в двух разных контейнерах докеров. Но об этом следует заботиться в докере, как есть. Если по какой-то причине это не так, методология столкновения портов должна обязательно позаботиться об этом и предупредить вас. Примечание. Я еще не пробовал этот подход, поскольку он перемещает систему в целом:)

В качестве альтернативы вы можете иметь команды в своем Makefile. Где задача:

Задача:
   docker-compose stop service_name
   docker-compose rm service_name
   rm -f./tmp/pids/server.pid(или относительный путь вашего файла pid)
   docker-compose up service_name

И затем vrooom make task в терминале и нажмите enter. Вышеупомянутые команды задачи предполагают, что служба, которую вы хотите запустить, находится в файле с именем docker-compose.yml

Если имя отличается от команды

docker-compose stop service_name → docker-compose -f your-compose-filename.yml stop service_name

так далее и т.д.

==================== Вернулся, чтобы обновить это. Итак, я попытался прокомментировать мою функцию write_pid. В основном держите определение метода, но не делайте ничего. До сих пор он работает хорошо. Он вообще не пишет pid. Если вы используете свои сервисы в докере, я считаю, что это абсолютно безопасно.

Ответ 8

В файле docker-compose.yml в самом контейнере приложения вы можете использовать:

команда: ["rm/your-app-path/tmp/pids/server.pid && bundle exec bin/rails s -p 3000 -b '0.0.0.0'"]

или же

команда: ["rm/your-app-path/tmp/pids/server.pid; запуск мастера"]

причина для ";" или "&&" заключается в том, что последний отправит выходной сигнал, если rm не сможет найти файл, вынудив ваш контейнер преждевременно остановиться. предыдущий будет продолжать выполняться.

почему это вызвано в первую очередь? рациональным является то, что если сервер (puma/thin/whatever) не выйдет из строя, он оставит pid в главном компьютере, вызывая ошибку выхода.

Ответ 9

Я знаю, что это относительно старый, но вы можете просто установить PID для вашего собственного имени файла:

CMD ["./bin/rails", "s", "--pid", "./tmp/pids/rails.pid"]

Если server.pid существует, это позволит избежать всего этого вместе без проверки файлов, используя