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

Выполнение миграции с помощью Rails в контейнере Docker с несколькими экземплярами контейнера

Я видел множество примеров создания контейнеров Docker для приложений Rails. Обычно они запускают сервер рельсов и имеют CMD, который запускает миграцию/настройку, а затем возвращает сервер Rails.

Если я создаю 5 из этих контейнеров одновременно, как Rails обрабатывает несколько процессов, пытающихся инициировать миграцию? Я вижу, что Rails проверяет текущую версию схемы в общем журнале запросов (это база данных MySQL):

 SELECT `schema_migrations`.`version` FROM `schema_migrations`

Но я вижу состояние гонки здесь, если это происходит одновременно с разными экземплярами Rails.

Учитывая, что DDL не является транзакционным в MySQL, и я не вижу каких-либо блокировок, происходящих в общем журнале запросов при выполнении миграций (кроме транзакций для каждой миграции), казалось бы, что их одновременное отключение будет плохая идея. На самом деле, если я удаляю это три раза локально, я вижу, как два экземпляра рельсов разбиваются при попытке создать таблицу, потому что она уже существует, в то время как третий экземпляр rails успешно завершает миграцию. Если это была миграция, которая вставляла что-то в базу данных, это было бы очень опасно.

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

Должен ли я создавать нереляционные контейнеры и один "контейнер миграции", который запускает миграцию, затем выходит?

Есть ли лучший вариант?

4b9b3361

Ответ 1

В частности, с Rails у меня нет опыта, но можно взглянуть с точки зрения докеров и программной инженерии.

Команда Docker защищает, иногда довольно агрессивно, что контейнеры касаются отгрузочных приложений. В это действительно отличное выражение, Джером Петаццони говорит, что речь идет обо всех проблемах. Я чувствую, что это именно то, что вы уже выяснили.

Запуск контейнера рельсов, который начинает миграцию или настройку, может быть полезен для первоначального развертывания и, вероятно, часто требуется во время разработки. Однако, при вводе в производство, вам действительно стоит рассмотреть вопрос о том, чтобы отделить проблемы.

Таким образом, я бы сказал, что есть одно изображение, которое вы используете для запуска контейнера N rails и добавляете инструменты/миграцию/настройку любого контейнера, который вы используете для выполнения административных задач. Посмотрите, что говорят разработчики из официального изображения рельсов:

Он предназначен для использования как в качестве контейнера для выброса (смонтируйте исходный код и запустите контейнер для запуска вашего приложения), так и базу для создания других изображений.

Когда вы смотрите на это изображение, нет команды настройки или миграции. Как пользователь может использовать его. Поэтому, когда вам нужно запустить несколько контейнеров, просто продолжайте.

Из моего опыта работы с mysql это прекрасно работает. Вы можете запустить контейнер только для данных для размещения данных, запустить контейнер с сервером mysql и, наконец, запустить контейнер для административных задач, таких как резервное копирование и восстановление. Для всех трех контейнеров вы можете использовать одно и то же изображение. Теперь вы можете получить доступ к своей базе данных, чтобы сказать несколько контейнеров Wordpress. Это означает четкое разделение проблем. Когда вы используете docker-compose, управлять этими контейнерами не так сложно. Конечно, уже есть много сторонних контейнеров и инструментов, которые также помогут вам создать сложное приложение, состоящее из нескольких контейнеров.

Наконец, вы должны решить, подходит ли докер и архитектура микросервиса для вашей проблемы. Как указано в этой статье, есть некоторые причины. Одной из основных проблем является то, что он добавляет совершенно новый уровень сложности. Тем не менее, так обстоит дело со многими решениями, и я думаю, вы знаете об этом и соглашаетесь, кроме него.

Ответ 2

docker run <container name> rake db:migrate

Запускает стандартный контейнер приложения, но не запускайте CMD (rails server), но rake db:migrate

UPDATE:. Предлагаемый Романом команда теперь будет:

docker exec <container> rake db:migrate