Проблемы с восстановлением

На основе репозитория discourse_docker я написал небольшой скрипт для автоматизации его использования внутри машины Vagrant (запускайте с опцией set -x, чтобы видеть, что именно происходит)

Неправильно ли я скопировал резервную копию в указанное место?

И что означает строка лога:
Making sure /var/www/discourse/tmp/restores/default/2020-05-13-190832 exists...

~/infra/discourse on  master! ⌚ 21:14:07
$ pwd
/home/pihentagy/infra/discourse
~/infra/discourse on  master! ⌚ 21:01:14
$ ./wl.sh start
+ set -e
+ VAGRANT_MACHINE_NAME=guest
+ cd discourse
+ case "$1" in
+ init
+ printf 'Checking out and updating repo…\n'
Checking out and updating repo…
+ cd ..
+ git clone https://github.com/discourse/discourse_docker.git discourse
fatal: destination path 'discourse' already exists and is not an empty directory.
+ printf 'Repo already there\n'
Repo already there
+ cd discourse
+ printf 'Updating repo…\n'
Updating repo…
+ git pull -r
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 2), reused 5 (delta 2), pack-reused 0
Unpacking objects: 100% (6/6), done.
From https://github.com/discourse/discourse_docker
   3e465a2..49ed141  master     -> origin/master
Created autostash: 36aae80
HEAD is now at 3e465a2 Remove all pg12 traces so pg_wrapper doesn't get confused
First, rewinding head to replay your work on top of it...
Fast-forwarded master to 49ed14152971f7f4a7437657987952be44c33c0a.
Applying autostash resulted in conflicts.
Your changes are safe in the stash.
You can run "git stash pop" or "git stash drop" at any time.
+ printf 'Copying config file…\n'
Copying config file…
+ cp ../resources/discourse.yml containers/
+ echo 'Starting Vagrant machine...'
Starting Vagrant machine...
+ vagrant up
Bringing machine 'dockerhost' up with 'virtualbox' provider...
==> dockerhost: Checking if box 'ubuntu/xenial64' is up to date...
==> dockerhost: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> dockerhost: flag to force provisioning. Provisioners marked to run always will still run.
+ vagrant ssh -c 'cd /vagrant;sudo ./launcher start discourse'
2627afdfbaac
Nothing to do, your container has already started!
Connection to 127.0.0.1 closed.
+ exit 0

~/infra/discourse on  master! ⌚ 21:07:56
$ ./wl.sh restore /home/pihentagy/infra/icontest-2020-05-12-033823-v20200506044956.tar.gz
+ set -e
+ VAGRANT_MACHINE_NAME=guest
+ cd discourse
+ case "$1" in
+ shift
+ backup=/home/pihentagy/infra/icontest-2020-05-12-033823-v20200506044956.tar.gz
+ discourse_backup_dir=shared/standalone/backups/default
+ mkdir --parents shared/standalone/backups/default
+ rsync -P --verbose /home/pihentagy/infra/icontest-2020-05-12-033823-v20200506044956.tar.gz shared/standalone/backups/default
icontest-2020-05-12-033823-v20200506044956.tar.gz
    390,774,609 100%  317.41MB/s    0:00:01 (xfr#1, to-chk=0/1)

sent 390,870,133 bytes  received 35 bytes  156,348,067.20 bytes/sec
total size is 390,774,609  speedup is 1.00
+ vagrant ssh -c 'sudo docker exec -w /var/www/discourse -i discourse discourse enable_restore'
Restore are now permitted. Disable them with `disable_restore`
Connection to 127.0.0.1 closed.
+ vagrant ssh -c 'sudo docker exec -w /var/www/discourse -i discourse discourse restore'
You must provide a filename to restore. Did you mean one of the following?

Connection to 127.0.0.1 closed.
+ vagrant ssh -c 'sudo docker exec -w /var/www/discourse -i discourse discourse restore icontest-2020-05-12-033823-v20200506044956.tar.gz'
Starting restore: icontest-2020-05-12-033823-v20200506044956.tar.gz
[STARTED]
'system' has started the restore!
Marking restore as running...
Making sure /var/www/discourse/tmp/restores/default/2020-05-13-190832 exists...
Copying archive to tmp directory...
EXCEPTION: lib/discourse.rb:90:in `exec': Failed to copy archive to tmp directory.
cp: cannot stat '/var/www/discourse/public/backups/default/icontest-2020-05-12-033823-v20200506044956.tar.gz': No such file or directory
lib/discourse.rb:100:in `execute_command'
lib/discourse.rb:90:in `exec'
lib/discourse.rb:40:in `execute_command'
/var/www/discourse/lib/backup_restore/local_backup_store.rb:42:in `download_file'
/var/www/discourse/lib/backup_restore/backup_file_handler.rb:61:in `copy_archive_to_tmp_directory'
/var/www/discourse/lib/backup_restore/backup_file_handler.rb:21:in `decompress'
/var/www/discourse/lib/backup_restore/restorer.rb:42:in `run'
script/discourse:143:in `restore'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/thor-1.0.1/lib/thor/command.rb:27:in `run'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/thor-1.0.1/lib/thor/base.rb:485:in `start'
script/discourse:284:in `<top (required)>'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `load'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:63:in `kernel_load'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli/exec.rb:28:in `run'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:476:in `exec'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/invocation.rb:127:in `invoke_command'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor.rb:399:in `dispatch'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:30:in `dispatch'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/vendor/thor/lib/thor/base.rb:476:in `start'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/cli.rb:24:in `start'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/exe/bundle:46:in `block in <top (required)>'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/lib/bundler/friendly_errors.rb:123:in `with_friendly_errors'
/usr/local/lib/ruby/gems/2.6.0/gems/bundler-2.1.4/exe/bundle:34:in `<top (required)>'
/usr/local/bin/bundle:23:in `load'
/usr/local/bin/bundle:23:in `<main>'
Trying to rollback...
There was no need to rollback
Cleaning stuff up...
Removing tmp '/var/www/discourse/tmp/restores/default/2020-05-13-190832' directory...
Unpausing sidekiq...
Marking restore as finished...
Notifying 'system' of the end of the restore...
Finished!
[FAILED]
Restore done.
Connection to 127.0.0.1 closed.

Vagrant не поддерживается, но вот несколько советов на всякий случай. :wink:

Не совсем уверен, как работает rsync. Нужно ли, чтобы путь заканчивался на косую черту? Если файл попал в правильную директорию, убедитесь, что сервер имеет права на чтение скопированного файла.

Значит ли это, что vagrant (virtualbox) может вызвать некоторые проблемы?

~/infra/discourse на  master! ⌚ 23:22:23
$ tree discourse/shared 
discourse/shared
└── standalone
    └── backups
        └── default
            └── icontest-2020-05-12-033823-v20200506044956.tar.gz

3 директории, 1 файл

~/infra/discourse на  master! ⌚ 23:22:27
$ ls discourse/shared/standalone/backups/default 
icontest-2020-05-12-033823-v20200506044956.tar.gz

~/infra/discourse на  master! ⌚ 23:22:36
$ ls -l discourse/shared/standalone/backups/default
total 381620
-rw-r--r-- 1 pihentagy pihentagy 390774609 May 13 21:08 icontest-2020-05-12-033823-v20200506044956.tar.gz

Похоже, что файл доступен для чтения всем и находится в правильном месте. Изнутри docker-контейнера discourse где я должен видеть резервную копию? Правильна ли мой скрипт автоматического восстановления, или мне нужно скопировать файл внутрь docker-контейнера? Если да, то куда? (Может быть, есть какие-либо руководства по автоматизации Discourse извне [docker?])

+ vagrant ssh -c 'sudo docker exec -w /var/www/discourse -i discourse discourse restore'
Вы должны указать имя файла для восстановления. Возможно, вы имели в виду один из следующих?

Соединение с 127.0.0.1 закрыто.
+ vagrant ssh -c 'sudo docker exec -w /var/www/discourse -i discourse discourse restore icontest-2020-05-12-033823-v20200506044956.tar.gz'
Запуск восстановления: icontest-2020-05-12-033823-v20200506044956.tar.gz
[

Это не обязательно, но отсутствие слэша в конце пути — плохая практика, так как результат зависит от того, существует ли уже целевая директория или нет.

Если целевая директория уже существует, слэш не нужен, и файл копируется внутрь этой директории.
Если целевая директория не существует и в конце нет слэша, файл копируется под именем ‘default’.
Если целевая директория не существует и в конце есть слэш, директория создаётся, и файл копируется внутрь неё.

В данном случае копирование, похоже, прошло успешно (по случайности).

Однако,

Поскольку после фразы «Вы имели в виду один из следующих?» никаких вариантов не предлагается, файл находится не в правильном месте. Похоже, диски неправильно смонтированы внутри контейнера Docker.

Вы можете запустить резервное копирование изнутри Docker (discourse backup) и посмотреть, куда файл попадает на вашей хостовой файловой системе.

Странно, что его не видно в файловой системе хоста. Должно ли оно быть там?

vagrant@ubuntu-xenial:~$ sudo docker exec -w /var/www/discourse -i discourse discourse backup
Запуск резервного копирования...
[НАЧАЛО]
Система начала создание резервной копии!
Пометка резервной копии как запущенной...
Проверка существования '/var/www/discourse/tmp/backups/default/2020-05-14-121930'...
Проверка существования '/var/www/discourse/public/backups/default'...
Обновление метаданных...
Приостановка sidekiq...
Ожидание завершения выполнения задач sidekiq...
Выгрузка публичной схемы базы данных...


Много всего из pg_dump"

Возобновление sidekiq...
Завершение резервного копирования...
Создание архива: discourse-2020-05-14-121930-v20200512064023.tar.gz
Проверка, что архив ещё не существует...
Создание пустого архива...
Добавление дампа данных в архив...
Добавление загрузок в архив...
Удаление временной директории '/var/www/discourse/tmp/backups/default/2020-05-14-121930'...
Сжатие архива в gzip, это может занять время...
Выполнение after_create_hook для резервной копии...
Удаление старых резервных копий...
Очистка...
Удаление остатков '.tar'...
Пометка резервной копии как завершённой...
Обновление статистики диска...
Готово!
[УСПЕХ]
Резервное копирование завершено.
Файл вывода находится в: /var/www/discourse/public/backups/default/discourse-2020-05-14-121930-v20200512064023.tar.gz

vagrant@ubuntu-xenial:~$ find / -name discourse-2020-05-14-121930-v20200512064023.tar.gz 2>/dev/null
vagrant@ubuntu-xenial:~$ sudo docer exec -w /var/www/discourse -i discourse discourse enable_restore
sudo: docer: команда не найдена
vagrant@ubuntu-xenial:~$ sudo docker exec -w /var/www/discourse -i discourse discourse enable_restore
Восстановление теперь разрешено. Отключите его с помощью `disable_restore`
vagrant@ubuntu-xenial:~$ sudo docker exec -w /var/www/discourse -i discourse discourse restore
Вы должны указать имя файла для восстановления. Возможно, вы имели в виду один из следующих?

discourse restore discourse-2020-05-14-121930-v20200512064023.tar.gz
discourse restore discourse-2020-05-14-121710-v20200512064023.tar.gz
discourse restore discourse-2020-05-14-120436-v20200512064023.tar.gz

Кстати: есть ли способ подсвечивать строки в блоках кода?

```bash

Здесь по умолчанию указан текст. Я полагаю, что по умолчанию для новых установок стоит «определить язык»,

Я имел в виду «смотри, мама, пятая строка важна!», то есть выделить конкретную строку (строки).

Обычно директория /var/discourse/shared/standalone/backups видна в вашем контейнере как /var/www/discourse/public/backups (отсюда и слово shared). Ваша команда rsync помещает резервную копию внутрь этой директории, чтобы сделать её доступной из контейнера.

И наоборот, если контейнер записывает данные в public/backups, они должны быть видны на хосте в общей директории.

Я указал выше путь /var/discourse/shared.... Но, похоже, вы работаете в ~/infra/discourse, поэтому вы копируете файлы в ~/infra/discourse/shared/standalone/backups/default.

Обычно контейнер мапится на /var/discourse/shared/....

В этом может быть проблема. Можете проверить, существует ли у вас директория /var/discourse/shared?

Нет. В блоке кода это сделать нельзя, так как всё отображается в точности как есть.

Ну, я только что сделал резервную копию и проверил, можно ли найти её за пределами виртуальной машины Docker, но не получилось.

vagrant@ubuntu-xenial:~$ sudo docker inspect -f "{{.Mounts}}" discourse
[{bind  /var/discourse/shared/standalone /shared   true rprivate} {bind  /var/discourse/shared/standalone/log/var-log /var/log   true rprivate}]

Да, но я пока проигнорировал это. Кстати, rsync выполнялся вне (vagrant) машины, на которой запускался мой Discourse.

Но пока, как вы и посоветовали, я сделал следующее:

  • подключился к машине через vagrant ssh и изнутри:
    • сделал резервную копию с помощью sudo docker exec -w /var/www/discourse -i discourse discourse backup
    • заметил путь к файлу:
      Выходной файл находится в: /var/www/discourse/public/backups/default/discourse-2020-05-14-125606-v20200512064023.tar.gz
      
    • искал этот конкретный файл по всей машине vagrant, но ничего не нашёл
      find / -name discourse-2020-05-14-125606-v20200512064023.tar.gz 2>/dev/null
      
    • однако, если зайти внутрь контейнера Docker, файл там есть
      root@ubuntu-xenial-discourse:/var/www/discourse/public/backups/default# ls
      discourse-2020-05-14-120436-v20200512064023.tar.gz  discourse-2020-05-14-121930-v20200512064023.tar.gz
      discourse-2020-05-14-121710-v20200512064023.tar.gz  discourse-2020-05-14-125606-v20200512064023.tar.gz
      

Так что мой вопрос: если я создаю резервную копию, должен ли я видеть её извне Docker?

Тем временем я просто создал виртуальную машину vagrant и выполнил git clone изнутри в стандартную директорию /var/discourse. Единственная “странность” в том, что у меня внутри контейнера есть файл discourse.yml, а не app.yml.

Да, и это то же самое, что и ваша первоначальная проблема:
«если у вас есть резервная копия вне Docker и вы поместите её в общую папку, вы должны видеть её внутри Docker» (а вы не видите).

Проблема связана с вашими общими директориями, и причина этого в следующем:

Я имел в виду: пока я создал новую машину Vagrant, без копирования каких-либо предыдущих резервных копий. Выполнил запуск и запуск контейнера Docker. Сделал резервную копию.

Внутри машины Vagrant ничего не видно за пределами машины Docker.

Кажется, я нашел проблему: я подключил эту общую папку Docker в машине Vagrant.

config.vm.synced_folder "discourse/", "/var/discourse"

Если закомментировать это в моем файле Vagrantfile, резервные копии «волшебным образом» появляются.

Так что проблема заключалась в том, что общая папка Vagrant (для «вверх») и общая папка Docker (для «вниз») конфликтуют и делают её недействительной.