제시해 주실 모든 지원에 감사드립니다. 말씀드리고 싶은 문제와 자체 호스팅(self-hosted) Discourse 인스턴스에 대한 제 목표를 논의하고 싶습니다.
문제
현재 저는 Hetzner 서버를 사용하여 Discourse 인스턴스를 호스팅하고 있습니다. Uploads와 Backups에 볼륨을 연결해 두었습니다. 현재 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에 지정된 호스트명 등 다른 설정들이 동일하게 유지된다는 전제 하에.)
## 이것은 올인원, 독립형 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"