복원 문제

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 on  master! ⌚ 23:22:23
$ tree discourse/shared 
discourse/shared
└── standalone
    └── backups
        └── default
            └── icontest-2020-05-12-033823-v20200506044956.tar.gz

3 directories, 1 file

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

~/infra/discourse on  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

파일이 모든 사용자에게 읽을 수 있으며 올바른 위치에 있는 것 같습니다. discourse docker 컨테이너 내부에서 백업을 어디서 확인해야 하나요? 제 unattended restore 스크립트가 올바른가요, 아니면 docker 컨테이너 내부로 복사해야 하나요? 그렇다면 어디로? (docker 외부에서 discourse를 자동화하는 방법에 대한 가이드가 있을까요?)

+ 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
[

경로 끝에 슬래시를 붙이는 것은 필수 사항은 아니지만, 슬래시를 붙이지 않는 것은 기존 디렉토리의 존재 여부에 따라 결과가 달라지기 때문에 좋은 관행이 아닙니다.

대상 디렉토리가 이미 존재하는 경우, 슬래시가 없어도 파일은 해당 디렉토리 내부로 복사됩니다.
대상 디렉토리가 존재하지 않고 끝에 슬래시가 없는 경우, 파일은 'default’라는 이름의 파일로 복사됩니다.
대상 디렉토리가 존재하지 않고 끝에 슬래시가 있는 경우, 디렉토리가 생성되고 파일이 그 안으로 복사됩니다.

이 경우 복사는 잘 진행되는 것처럼 보입니다(운이 좋게도).

그러나,

“did you mean one of the following?” 뒤에 제안된 항목이 없으므로, 파일이 올바른 위치에 있지 않은 것입니다. 드라이브가 Docker 컨테이너에 잘못 매핑된 것으로 보입니다.

Docker 내부에서 백업을 시작(discourse backup)하여 호스트 파일 시스템 어디에 저장되는지 확인해 볼 수 있습니다.

이상하게도 호스트 파일 시스템에서는 보이지 않습니다. 보이나요?

vagrant@ubuntu-xenial:~$ sudo docker exec -w /var/www/discourse -i discourse discourse backup
Starting backup...
[STARTED]
'system' has started the backup!
Marking backup as running...
Making sure '/var/www/discourse/tmp/backups/default/2020-05-14-121930' exists...
Making sure '/var/www/discourse/public/backups/default' exists...
Updating metadata...
Pausing sidekiq...
Waiting for sidekiq to finish running jobs...
Dumping the public schema of the database...

…
pg_dump 관련 내용들이 많이 출력됩니다…

Unpausing sidekiq...
Finalizing backup...
Creating archive: discourse-2020-05-14-121930-v20200512064023.tar.gz
Making sure archive does not already exist...
Creating empty archive...
Archiving data dump...
Archiving uploads...
Removing tmp '/var/www/discourse/tmp/backups/default/2020-05-14-121930' directory...
Gzipping archive, this may take a while...
Executing the after_create_hook for the backup...
Deleting old backups...
Cleaning stuff up...
Removing '.tar' leftovers...
Marking backup as finished...
Refreshing disk stats...
Finished!
[SUCCESS]
Backup done.
Output file is in: /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: command not found
vagrant@ubuntu-xenial:~$ sudo docker exec -w /var/www/discourse -i discourse discourse enable_restore
Restore are now permitted. Disable them with `disable_restore`
vagrant@ubuntu-xenial:~$ 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?

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

여기서 기본값은 텍스트입니다. 새로운 설치의 경우 기본값이 '언어 추측’이라고 생각합니다.

제가 의도한 것은 "엄마, 5번째 줄이 중요해!"라는 것이었고, 기본적으로 특정 줄을 강조하는 것입니다.

보통 /var/discourse/shared/standalone/backups 디렉토리가 컨테이너 내부에서 /var/www/discourse/public/backups로 표시됩니다(따라서 shared라는 이름이 붙었습니다). rsync 명령은 컨테이너 내부에서 접근할 수 있도록 하기 위해 백업 파일을 해당 디렉토리 안에 저장합니다.

반대로, 컨테이너가 public/backups에 데이터를 쓰면 호스트의 shared 디렉토리에서 확인 가능해야 합니다.

위에서 /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 작업은 discourse를 실행하던 (vagrant) 머신 외부에서 수행했습니다.

하지만 현재로서는 조언해 주신 대로 다음을 수행했습니다:

  • vagrant ssh로 머신에 접속하고 내부에서:
    • sudo docker exec -w /var/www/discourse -i discourse discourse backup으로 백업을 수행했습니다
    • 파일 경로를 확인했습니다:
      Output file is in: /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 머신을 새로 생성하고, 표준 /var/discourse 디렉터리에서 내부로 git clone을 수행했습니다. 유일한 “이상한” 점은 컨테이너 내부에 app.yml이 아니라 discourse.yml이 있다는 것입니다.

네, 그렇습니다. 그리고 이것은 원래 질문하신 문제와 동일한 상황입니다:
“Docker 외부에 백업이 있고 그것을 공유 디렉토리에 넣으면, Docker 내부에서 그걸 볼 수 있어야 한다” (하지만 실제로는 보이지 않죠).

문제는 공유 디렉토리에 있으며, 그 이유는 다음과 같습니다:

내가 말한 것은: 일단 완전히 새로운 vagrant 머신을 새로 만들었고, 이전 백업은 아무것도 복사하지 않았습니다. 부트스트래핑을 수행하고 docker 컨테이너를 시작했습니다. 그리고 백업을 수행했습니다.

docker 머신 외부의 vagrant 머신에서는 아무것도 보이지 않습니다.

문제를 찾은 것 같습니다: 이 docker-shared 폴더를 외부 vagrant 머신에 마운트하고 있었습니다.

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

Vagrantfile에서 이 부분을 주석 처리하면 백업이 “마법처럼” 나타납니다.

즉, 문제는 Vagrant 공유 폴더(“”)와 docker 공유 폴더(“”)가 경쟁하여 무효화시키는 것이었습니다.