미디어 업로드에 Cloudflare R2를 사용 중인데, 데이터베이스 백업에는 사용되지 않는 것 같습니다. rclone을 사용하여 백업해야 할 파일 디렉토리는 무엇인가요?
아래 주제가 도움이 될 수 있습니다.
ProtonDrive에 백업할 Discourse 파일/디렉터리 (R2/S3 미디어 제외)
1단계 — upload://의 의미
upload://
주석
Discourse는 게시물 내용(원문/렌더링)에 실제 경로가 아닌 upload://<hash>라는 참조만 저장합니다. 렌더링 시점이나 게시물을 구울 때, Discourse는 데이터베이스 테이블(uploads, post_uploads 등)을 참조하여 업로드 저장 위치(로컬, CDN, S3/R2 등)에 따라 이 해시를 실제 URL 또는 경로로 해석합니다.
2단계 — 컨테이너 내부에서의 저장 위치
/shared/uploads/default
주석
표준 Docker 설치(launcher와 app.yml 사용) 환경에서 컨테이너 내부의 /shared는 호스트의 /var/discourse/shared/standalone으로 바인드 마운트됩니다. Discourse가 작성하는 모든 영구 데이터(업로드, 로그, 백업 등)는 /shared 아래에 저장됩니다.
3단계 — 호스트 파일시스템 경로
/var/discourse/shared/standalone/uploads/default
주석
외부 업로드(S3/R2)를 사용하지 않는 경우, 게시물 미디어를 보존하기 위해 ProtonDrive로 동기화해야 하는 주요 경로가 바로 여기입니다. S3/R2를 사용하는 경우 대부분의 업로드는 여기에 없지만, 일부 파일(예: 최적화 변형본, 톰스톤)이 남아 있을 수 있습니다. 이 경로도 백업할지 결정해야 합니다.
4단계 — Docker 볼륨 매핑 (app.yml)
volumes:
- volume:
host: /var/discourse/shared/standalone
guest: /shared
주석
컨테이너 내부의 /shared에 있는 모든 것은 호스트에서는 /var/discourse/shared/standalone이 됩니다. 이 트리(폴더 구조)를 백업하면 업로드, 백업 타르볼, 로그, 그리고 디스크에 저장된 경우 PostgreSQL 데이터까지 확보할 수 있습니다(다만 복구에는 일반적으로 백업 타르볼만으로도 충분합니다).
백업할 구체적 대상 (로컬 스토어 기준)
최소 구성 (Discourse의 타르볼 백업을 신뢰하는 경우):
/var/discourse/shared/standalone/backups/ # Discourse가 생성한 전체 백업 (tarball .tar.gz 파일)
/var/discourse/shared/standalone/uploads/ # 업로드를 로컬에 저장하는 경우에만 필요
주석
- 타르볼 백업은 Discourse 백업 기능에 의해 생성되는 .tar.gz 파일을 의미합니다. 여기에는 전체 데이터베이스 덤프, 사이트 설정, 테마, 그리고 (선택 사항으로 지정 시) 모든 로컬 업로드가 포함됩니다. 외부 S3/R2에 저장된 미디어는 포함되지 않으며, 이를 참조하는 데이터베이스 레코드만 포함됩니다.
- 업로드가 S3/R2에 reside하는 경우, 로컬에서는
/backups/만 백업하고 객체 저장소 버킷은 별도의 프로세스로 백업하면 됩니다.
“언젠가 필요할 수 있는 모든 것” 구성 (파일시스템 레벨 복사):
/var/discourse/shared/standalone/backups/ # Discourse 전체 백업 (타르볼)
/var/discourse/shared/standalone/uploads/ # 로컬 업로드/미디어 (S3/R2가 아닌 경우)
/var/discourse/shared/standalone/log/rails/ # (선택 사항) Rails 로그 — 포렌식 분석에 유용
/var/discourse/shared/standalone/tmp/backups/ # (선택 사항) 임시 백업 스테이징 (보통 비어 있음)
/var/discourse/shared/standalone/postgres_data/ # (선택 사항) 원시 PostgreSQL 데이터 디렉터리 — 보통 불필요
/var/discourse/containers/ # app.yml 및 컨테이너 YML 파일 (설정)
/etc/letsencrypt/ # (선택 사항) 호스트에서 SSL을 종료하는 경우의 TLS 인증서
주석
- 원시 PostgreSQL 데이터는 타르볼 백업에 로직 데이터베이스 덤프가 포함되어 있어 복구가 더 안전하므로 보통 불필요합니다.
- /containers는 크기가 작지만 재해 복구에 매우 중요합니다. 설정과 볼륨 매핑이 여기에 저장됩니다.
- TLS 인증서는 컨테이너 외부에서 SSL을 처리하는 경우에만 중요합니다.
한 줄 요약 맵
upload://
↓
/shared/uploads/default (Docker 내부)
/var/discourse/shared/standalone/uploads/default (호스트)
주석
S3/R2를 사용하는 경우:
- S3/R2 버킷을 별도로 백업하세요 (예: Rclone 사용).
/backups/(타르볼, DB와 설정, 사이트 업로드 포함, 외부 미디어 제외)와/containers/도 백업하는 것을 고려하세요.
ProtonDrive 스레드를 위한 TL;DR
- 로컬 업로드 사용 중? 백업 대상:
- /var/discourse/shared/standalone/uploads/
- /var/discourse/shared/standalone/backups/ # (tarball 백업이 .tar.gz 형식으로 포함됨)
- S3/R2 업로드 사용 중? 백업 대상:
- /var/discourse/shared/standalone/backups/ # (타르볼 백업: db/설정/업로드 테이블)
- S3/R2 버킷은 다른 도구로 백업
- 선택 사항: 전체 DR(재해 복구) 커버리지를 위해 /containers/, /log/rails/, postgres_data 백업
주석
타르볼 백업: Discourse 백업 시스템이 생성하는 .tar.gz 파일로, 로직 데이터베이스 덤프, 테마, 설정, 그리고 (선택 사항) 로컬 업로드를 포함하지만, 외부 S3/R2 미디어는 절대 포함되지 않습니다.
서버를 이전한 3번의 경험에서, 로컬 업로드를 보존하기 위해 tarball 백업에 의존했을 때 기본 app.yml 파일이 매번 달랐다는 점을 강조하고 싶습니다.
따라서, 새 파일의 일부 구문을 이전 파일의 해당 구문으로 수동으로 복사하여 대체하는 것이 더 나은 방법일 것입니다.
그렇다면 컨테이너에서 이를 꺼내는 방법은 무엇일까요?
필요하다면 discourse 컨테이너에서 tarball 백업 파일을 호스트 시스템으로 가져오기 위해 docker cp를 시도해 보고 싶습니다.
- 기본 구문은
docker cp [SOURCE_PATH] [CONTAINER_NAME]:[DEST_PATH]이며, 그 반대도 가능합니다.