docker-compose ожидает запуска до тех пор, пока не будет смонтирована файловая система хоста

#docker #docker-compose #mount #nfs

#docker #docker-compose #смонтировать #nfs

Вопрос:

Суть этого вопроса заключается в том, чтобы заставить docker-compose ждать запуска контейнера mysql до тех пор, пока не будет смонтирована файловая система хоста. В моем случае файловая система хоста содержит файлы базы данных mysql.

Для служб, зависящих от контейнера mysql, существуют сценарии, такие как wait-for-it, которые выполняются как часть точки входа контейнера. Эти скрипты проверяют доступность служб на сетевых портах. Но я не вижу, как заставить запуск контейнера ждать, пока файловая система будет смонтирована на хосте.

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

Комментарии:

1. Предполагая, что ваша система использует systemd (что довольно распространено), решение состоит в том, чтобы сделать docker службу зависимой от соответствующего .mount модуля для файловой системы. Это предотвратит запуск docker до монтирования файловой системы. Например, как описано здесь .

2. Отличный ответ @larsks. Я предполагаю , что вы имеете в виду добавить mnt-mountpoint.mount в конец After строки /lib/systemd/system/docker.service . Я протестировал, размонтировав файловую систему, затем остановив и запустив демон docker. К сожалению, все контейнеры запускались с отключенной файловой системой. Затем я протестирую перезагрузку.

3. Более тщательное прочтение связанного вопроса показало, что мне также нужно было добавить mnt-mountpoint.mount к этой Requires строке. Теперь служба docker отказывается запускаться, если файловая система не смонтирована. @larsks, пожалуйста, опубликуйте свой ответ, чтобы я мог его принять.

Ответ №1:

Предполагая, что ваша система использует systemd (что довольно распространено), решение состоит в том, чтобы сделать службу docker зависимой от соответствующего модуля .mount для файловой системы. Это предотвратит запуск docker до монтирования файловой системы. Добавление зависимости от точки монтирования описано, например, в этом ответе над https://unix.stackexchange.com .

Для каждой файловой системы , указанной в /etc/fstab , systemd генерирует единицу с именем <filesystem>.mount . Например, в моей системе, в которой /etc/fstab содержится, среди прочего:

 /dev/tank/scratch /scratch xfs defaults 1 2
 

Я вижу следующий системный блок:

 # systemctl list-units -t mount |grep scratch
scratch.mount        loaded active mounted /scratch
 

Мы можем сделать такую службу, как Docker, зависимой от этой точки монтирования, добавив что-то вроде следующего в [Unit] раздел модуля:

 [Unit]
Requires=scratch.mount
After=scratch.mount
 

Requires Директива означает «когда вы запускаете эту службу (например docker ), также запускайте перечисленные здесь устройства», а After директива означает «запускайте именованные устройства перед этим».

Комментарии:

1. Я считаю, что это правильный ответ, но, к сожалению, он не работает у меня во время загрузки системы. Я думаю, это потому, что в systemd есть ошибка 4-летней давности, связанная именно с этим шаблоном использования. Мне трудно понять, как такая утилита, как systemd, используемая миллионами (?) хостов Linux, может иметь такую ошибку. Будут оценены предложения по обходным путям. Моя система Ubuntu 18 работает под управлением systemd версии 237.

2. Ах, облом, я думал, ты указал, что это работает. Я рассмотрю подробнее, когда у меня будет немного свободного времени завтра.

3. Спасибо. Это работает, когда вы останавливаете и запускаете демон docker после загрузки, но не как часть процесса загрузки.

Ответ №2:

Сервис самого низкого уровня — это mysql. Измените его точку входа, чтобы завершить работу, если каталог, который, как известно, находится в смонтированной файловой системе, отсутствует.

Все зависимые службы могут использовать сценарии dockerize или wait-for-it, которые ожидают открытия сетевого порта mysql.

   mysql:
        image: mysql:5.7.30
        restart: always
        entrypoint: ["bash", "-c", "touch /testdir/dir_on_filesystem/write-test amp;amp; rm /testdir/dir_on_filesystem/write-test amp;amp; echo 'Test for mounted filesystem passed' amp;amp; mysqld --user=root"]
        volumes:
          - /mnt/mountpoint/mysql:/var/lib/mysql
          - /mnt/mountpoint:/testdir
 

Если вы можете гарантировать, что /mnt/mountpoint/mysql он существует в файловой системе до первого запуска контейнера mysql, тогда вы можете использовать этот каталог для теста вместо /testdir/dir_on_filesystem .

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