Не забудьте выполнить docker remove app при переустановке Discourse

Я использую Discourse уже несколько лет. Каждые полгода я настраиваю новый экземпляр. Моя конфигурация включает Docker и прокси на базе nginx, поэтому она, возможно, немного нестандартна. По этой причине я не использую discourse-setup.

Каждые полгода, когда я повторяю этот процесс, после того как я заново клонирую свежую копию Discourse из репозитория git и запускаю ./launcher bootstrap app, контейнер не запускается. В логе отображается:

anacron: Can't chdir to /var/spool/anacron: No such file or directory
run-parts: /etc/runit/1.d/anacron exited with return code 1
run-parts: executing /etc/runit/1.d/00-ensure-links
run-parts: executing /etc/runit/1.d/00-fix-var-logs
run-parts: executing /etc/runit/1.d/01-cleanup-web-pids
run-parts: executing /etc/runit/1.d/anacron
anacron: Can't chdir to /var/spool/anacron: No such file or directory

и так до бесконечности.

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

Однако в этот раз, кажется, я наконец нашёл причину, и она вот в чём: apparently, ./launcher start app перезапускает старые экземпляры контейнеров с именем app, даже если Discourse был заново клонирован и перепересобран.

Отсутствующий шаг — docker remove app. Итоговый порядок действий:

./launcher stop app
docker remove app
... теперь заново клонируем, пересобираем и запускаем `./launcher start app`, и всё работает

Моя ошибка заключалась в том, что я ожидал, будто после выполнения ./launcher bootstrap app следующий ./launcher start app запустит новый образ контейнера, но, похоже, это не так. Естественно, всё идёт наперекосяк со старым контейнером, так как путь /var/discourse/shared был переинициализирован.

Я оставляю это здесь на случай, если кто-то ищет те же сообщения об ошибках в логах.

В качестве возможного улучшения было бы здорово, если бы контейнер обнаруживал изменения в своей директории /var/discourse/shared.

Если вы хотите запустить bootstrap «по-дискурсовски», используйте:

./launcher bootstrap app
./launcher destroy app
./launcher start app

Однако, если у вас всего один контейнер, нет причин не делать просто:

./launcher rebuild app

как почти во всех примерах. Эта команда останавливает работающий контейнер, создаёт новый с помощью bootstrap и запускает его. Если bootstrap по какой-то причине не удался, вы можете (обычно) перезапустить старый контейнер с помощью ./launcher start app (как вы и описали).

Думаю, я вижу проблему, и она связана с обычной путаницей между «экземпляром контейнера» и «образом контейнера».

Если посмотреть, например, на 10. Обслуживание после установки, там сказано:

Usage: launcher COMMAND CONFIG [--skip-prereqs] [--docker-args STRING]
Commands:
    start:      Start/initialize a container
    stop:       Stop a running container
    restart:    Restart a container
    destroy:    Stop and remove a container
    enter:      Use nsenter to get a shell into a container
    logs:       View the Docker logs for a container
    bootstrap:  Bootstrap a container for the config based on a template
    rebuild:    Rebuild a container (destroy old, bootstrap, start new)
    cleanup:    Remove all containers that have stopped for > 24 hours

В большинстве случаев использования слова «контейнер» в этом выводе справки речь идёт об экземпляре контейнера. Исключение — bootstrap, где имеется в виду образ. (./launcher bootstrap использует docker commit для создания нового образа, из которого затем запускаются последующие экземпляры контейнеров.) Мне кажется, это было неочевидно (и я наивно предположил, что это затронет также текущий экземпляр app).

В команде rebuild слово «контейнер» относится и к образам, и к экземплярам, поскольку она включает набор операций, затрагивающих как экземпляры контейнеров, так и их образы.

Неясно также, что именно имеется в виду в cleanup: будут ли удалены только экземпляры или также и созданный при загрузке образ?