Discourse 인스턴스를 새 서버로 이전하기

질문하기 전에 먼저 검색해 보셨나요? 오른쪽 상단의 :magnifying_glass_tilted_left: 버튼을 눌러 검색해 주세요

안녕하세요,

제시해 주실 모든 지원에 감사드립니다. 말씀드리고 싶은 문제와 자체 호스팅(self-hosted) Discourse 인스턴스에 대한 제 목표를 논의하고 싶습니다.

문제

현재 저는 Hetzner 서버를 사용하여 Discourse 인스턴스를 호스팅하고 있습니다. UploadsBackups에 볼륨을 연결해 두었습니다. 현재 Docker 컨테이너와 이미지, 그리고 app.yml 등의 파일은 서버 자체의 /var/discourse 경로에 호스팅되어 있습니다.

이 서버를 3~4년 이상 사용해 왔으며, 그 동안 서버 자체의 공간(볼륨 제외) 부족 문제로 인해 여러 번 곤란을 겪었습니다. 앱을 재빌드하거나 재시작할 때마다 이미지와 Docker 컨테이너가 볼륨이 아닌 로컬 서버에 설치되어 공간 문제가 발생했습니다. 재빌드를 위해 Docker와 모든 이미지/컨테이너를 삭제하고 처음부터 다시 설치해야 했습니다. 또한 SQL 데이터도 볼륨이 아닌 로컬 서버에 연결되어 있다고 생각합니다.

목표

앞으로 제가 취해야 할 최선의 조치가 무엇인지 잘 모르겠습니다. Postgres DB와 Docker 이미지를 위해 특정 폴더나 파일을 새 볼륨으로 이동하는 것이 좋을까요? 그렇다면 어떻게 해야 하는지 지원을 받고 싶습니다. 아니면 서버를 백업하고, 새 서버에서 모든 볼륨이 올바르게 구성된 위치에 복원하는 방식으로 처음부터 시작하는 것이 좋을까요?


이 모든 상황을 고려할 때, 공간이 많이 차지하는 모든 항목(예: 백업, 업로드, DB, Docker 이미지 등)에 대해 볼륨이 올바르게 구성되도록 app.yml을 설정하는 방법에 대한 지원을 받으면 좋겠습니다. 그러면 필요할 때 백업, 업로드, DB, Docker 이미지 등을 개별적으로 확장할 수 있을 것입니다.

현재 직장에 있어 선제적으로 문제를 해결하고 싶으므로, 오늘 늦게 app.yml 파일을 제공할 수 있습니다.

저는 AWS에서 디스코urs 호스팅을 하고 있으며, /var/discourse를 별도의 마운트 가능한 EBS 볼륨에 두고 필요할 때마다 다른 EC2 인스턴스에 해당 볼륨을 연결하여 마이그레이션을 진행해 왔습니다. 지금까지 큰 성공을 거두고 있습니다. 심지어 x64에서 ARM으로 아키텍처를 완전히 변경하는 과정(EC2 인스턴스를 t3a.large에서 r7g.large로 전환)에서도 /var/discourse 볼륨을 다시 마운트한 후 간단한 launcher rebuild app 명령만 실행하면 아키텍처 변경에도 불구하고 다시 온라인 상태가 되었습니다.

결론적으로, /var/discourse가 마운트 가능한 볼륨에 저장되어 있다면 포럼의 전체 상태가 사실상 언제든 마운트 가능한 상태로 유지된다고 볼 수 있습니다. 호스트를 설정하고 도커를 설치할 수만 있다면, /var/discourse를 해당 호스트에 마운트하고 launcher rebuild app을 실행하면 바로 서비스를 시작할 수 있습니다. (호스트 간에 app.yml에 지정된 호스트명 등 다른 설정들이 동일하게 유지된다는 전제 하에.)

이 구성에 대한 app.yml 예시를 제공해 주실 수 있을까요? 또한 단순히 "/var/discourse"의 콘텐츠를 다른 볼륨으로 이동하는 것만으로 충분한지, 아니면 새 볼륨에 리포지토리를 클론해야 하는지 궁금합니다.


데이터베이스 파일은 어떻게 처리해야 하나요?

현재 사용 중인 app.yml 파일의 비공개 처리된 사본입니다:

## 이것은 올인원, 독립형 Discourse Docker 컨테이너 템플릿입니다.
##
## 이 파일을 변경한 후에는 반드시 다시 빌드해야 합니다.
## /var/discourse/launcher rebuild app
##
## 편집할 때 *매우* 주의하세요!
## YAML 파일은 공백이나 정렬 오류에 대해 매우 민감합니다!
## 필요할 경우 http://www.yamllint.com/ 에서 이 파일을 검증하세요.

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.ssl.template.yml"
  - "templates/web.letsencrypt.ssl.template.yml"
  - "templates/cloudflare.template.yml"

## 이 컨테이너가 노출할 TCP/IP 포트는 무엇입니까?
## Apache나 nginx 같은 다른 웹서버와 Discourse가 포트를 공유하려면
## 자세한 내용은 https://meta.discourse.org/t/17247 을 참조하세요.
expose:
  - "80:80"   # http
  - "443:443" # https

params:
  db_default_text_search_config: "pg_catalog.english"

  ## db_shared_buffers를 총 메모리의 최대 25%로 설정하세요.
  ## 감지된 RAM 기반으로 bootstrap이 자동으로 설정하거나, 직접 덮어쓸 수 있습니다.
  db_shared_buffers: "4096MB"

  ## 정렬 성능을 향상시킬 수 있지만, 연결당 메모리 사용량이 증가합니다.
  db_work_mem: "40MB"

  ## 이 컨테이너가 사용할 Git 리비전은 무엇입니까? (기본값: tests-passed)
  #version: tests-passed

env:
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8
  # DISCOURSE_DEFAULT_LOCALE: en

  ## 동시에 처리할 수 있는 웹 요청의 수는 얼마입니까? 메모리와 CPU 코어 수에 따라 달라집니다.
  ## 감지된 CPU 기반으로 bootstrap이 자동으로 설정하거나, 직접 덮어쓸 수 있습니다.

  ## 2025/8/2 Lee가 변경함
  # UNICORN_WORKERS: 8
  UNICORN_WORKERS: 10

  ## TODO: 이 Discourse 인스턴스가 응답할 도메인 이름
  ## 필수입니다. Discourse는 단순한 IP 주소로는 작동하지 않습니다.
  DISCOURSE_HOSTNAME: discourse.spacecityweather.com

  ## TODO: 초기 가입 시 관리자 및 개발자로 지정될 쉼표로 구분된 이메일 목록
  ## 예: 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: [redacted]

  ## TODO: 새 계정 검증 및 알림 전송에 사용되는 SMTP 메일 서버
  # SMTP ADDRESS는 필수입니다.
  # 경고: SMTP 비밀번호는 문제를 방지하기 위해 따옴표로 감싸야 합니다.
  DISCOURSE_SMTP_ADDRESS: [redacted]
  DISCOURSE_SMTP_PORT: [redacted]
  DISCOURSE_SMTP_USER_NAME: [redacted]
  DISCOURSE_SMTP_PASSWORD: [redacted]
  DISCOURSE_SMTP_DOMAIN: [redacted]
  DISCOURSE_NOTIFICATION_EMAIL: [redacted]

  ## Lets Encrypt 템플릿을 추가했다면, 무료 SSL 인증서를 얻기 위해 아래 주석을 해제하세요.
  LETSENCRYPT_ACCOUNT_EMAIL: [redacted]

  ## IP 주소 조회를 위한 maxmind 지리 위치 IP 계정 ID와 라이선스 키
  ## 자세한 내용은 https://meta.discourse.org/t/-/173941 을 참조하세요.
  DISCOURSE_MAXMIND_ACCOUNT_ID: [redacted]
  DISCOURSE_MAXMIND_LICENSE_KEY: [redacted]

  ## S3 백업 관련 설정
  ## 2025/7/20 Lee가 추가함
  DISCOURSE_USE_S3: true
  DISCOURSE_S3_REGION: [redacted]
  DISCOURSE_S3_USE_IAM_PROFILE: true
  DISCOURSE_S3_BACKUP_BUCKET: [redacted]
  DISCOURSE_BACKUP_LOCATION: s3

  ## sidekiq이 메모리를 과도하게 사용하는 오류를 수정할 수 있을까요?
  UNICORN_SIDEKIQ_MAX_RSS: 1024

  ## 2025/8/2 Lee가 추가함
  SIDEKIQ_CONCURRENCY: 6
  RUBY_GC_HEAP_GROWTH_MAX_SLOTS: 40000
  RUBY_GC_HEAP_GROWTH_FACTOR: 1.1
  RUBY_GLOBAL_METHOD_CACHE_SIZE: 131072
  MALLOC_ARENA_MAX: 2

## Docker 컨테이너는 상태가 없으며(stateless), 모든 데이터는 /shared에 저장됩니다.
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## Docker 인자?
docker_args: "--add-host spacecityweather.com:[redacted] --add-host theeyewall.com:[redacted]"

## 플러그인은 여기에 배치합니다.
## 자세한 내용은 https://meta.discourse.org/t/19157 을 참조하세요.
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git

## 빌드 후 실행할 사용자 정의 명령
run:
  - exec: echo "Beginning of custom commands"
  ## 첫 번째 가입 시 'From' 이메일 주소를 설정하려면 주석을 해제하고 변경하세요:
  ## 첫 번째 가입 이메일을 받은 후, 해당 줄을 다시 주석 처리하세요. 한 번만 실행하면 됩니다.
  #- exec: rails r "SiteSetting.notification_email='info@unconfigured.discourse.org'"
  - exec: echo "End of custom commands"

그리고 DB의 모든 콘텐츠가 /var/discourse에 저장되는 건가요? 그렇다면 /var/discourse의 모든 콘텐츠를 마운트 가능한 볼륨으로 이동하면 기존 데이터를 계속 사용하게 되나요?

저는 표준 단일 컨테이너 셀프 호스팅 설치 방식을 사용하므로, 기본 설정이 어떻게 되어 있는지에 따라 모두 설정되어 있습니다!

질문이 있습니다. /discourse 폴더를 마운트 가능한 볼륨으로 이동했음에도 불구하고 여전히 Docker에서 어려움을 겪고 있습니다. 컨테이너와 이미지가 볼륨이 아닌 로컬 드라이브에서 실행되고 있기 때문입니다. 이 문제를 해결하는 방법에 대한 아이디어가 있을까요?