VPS에 Docker로 ERPNext 직접 호스팅하기
Docker Compose를 사용하여 11개 컨테이너로 구성된 ERPNext를 VPS에 구축하는 방법을 안내합니다. 버전 고정, TLS 설정, 아웃바운드 이메일 구성 및 검증된 백업 복구 전략을 포함한 운영 핵심 가이드를 확인하십시오.
운영하게 될 서비스의 성격
VPS에서 ERPNext를 직접 호스팅하는 것은 단순한 명령어 한 줄로 끝나는 설치가 아니라 운영 업무의 영역입니다. 공식 Docker Compose 스택은 11개의 컨테이너로 구성되며, 여기에는 기업의 총계정원장과 고객 기록이 저장됩니다. 따라서 아래의 모든 항목에 대해 높은 기준을 적용해야 합니다. 복구 테스트를 거치지 않은 백업은 백업이 아니며, 태그가 고정되지 않은 이미지는 언제든 스키마 마이그레이션 오류를 일으킬 수 있는 시한폭탄과 같습니다.
몇 가지 용어를 미리 알아두어야 합니다. ERPNext는 비즈니스 애플리케이션이며, Frappe는 그 기반이 되는 Python 프레임워크입니다. Bench는 사이트를 관리하는 명령줄 도구로, 이미 컨테이너 내부에 설치되어 있습니다. 사이트(site)는 하나의 테넌트를 의미하며, 하나의 MariaDB 데이터베이스와 업로드된 파일이 담긴 디렉터리 하나로 구성됩니다. 이 가이드의 거의 모든 명령어는 bench 컨테이너 내부에서 backend 명령을 통해 특정 사이트를 대상으로 실행됩니다.
이 가이드는 프로젝트에서 유지 관리하는 배포 방식인 frappe_docker 저장소를 사용합니다. 아래의 모든 명령어는 2026년 8월 기준으로 해당 저장소에서 검증되었습니다. Docker Compose 자체가 생소하다면 VPS에서 Docker Compose 실행하기를 먼저 참고하여 이 가이드가 전제하는 기초 지식을 습득하시기 바랍니다.
ERPNext는 어느 정도 규모의 VPS가 필요한가?
The data behind this chart
[
{
"label": "Evaluation",
"vcpu": 2,
"ram_gb": 4,
"disk_gb": 40
},
{
"label": "Small production",
"vcpu": 4,
"ram_gb": 8,
"disk_gb": 100
},
{
"label": "Room to grow",
"vcpu": 4,
"ram_gb": 16,
"disk_gb": 160
}
]공식 가이드에 따르면 단일 사용자가 로그인하기 전 최소 2 vCPU와 4 GB의 RAM이 필요합니다. 이는 평가용 사양입니다. 이 수치는 시작점일 뿐 본 가이드에서 측정한 결과가 아니며, 실제 필요한 사양은 사용자의 문서 처리량에 따라 결정됩니다. 마지막 행은 공식 최소 사양이 아닙니다. 메모리 부족을 걱정하지 않아도 되는 대략적인 기준점입니다.
저사양 플랜에 대해서는 현실적으로 판단해야 합니다. 1 GB 또는 2 GB VPS는 스택을 시작할 수는 있지만, 첫 번째 데이터 가져오기나 긴 보고서를 생성할 때 서버가 중단됩니다. 9개의 장기 실행 컨테이너, MariaDB 버퍼 풀, 보고서를 생성하는 Python 워커가 해당 메모리 용량에 모두 들어갈 수 없기 때문입니다. 이 실패는 정상적으로 처리되지 않습니다. 커널의 OOM(Out of Memory) 킬러가 컨테이너를 강제 종료하며, 이때 docker inspect을 확인하면 종료 코드 137과 함께 "OOMKilled": true이 표시됩니다. 작업 도중 워커가 강제 종료되면 제출된 문서의 백그라운드 작업이 절반만 완료된 상태로 남게 됩니다.
ERPNext를 매일 사용하는 기업의 경우, 8 GB RAM, 4 vCPU, 100 GB SSD가 현실적인 최소 사양입니다. RAM이 가장 먼저 부족해집니다. 모든 첨부 파일과 로컬 백업이 데이터베이스와 동일한 볼륨에 저장되므로 디스크 사용량은 예상보다 빠르게 증가합니다.
11개의 컨테이너와 각 컨테이너의 역할
스택이 가동되고 9개의 컨테이너가 실행된 후 docker compose ps를 실행합니다. 나머지 2개인 configurator과 create-site는 작업을 한 번 수행한 뒤 종료되므로, 총 11개의 컨테이너가 구성됩니다.
backend는 gunicorn 환경에서 Frappe 애플리케이션을 실행합니다.bench이 위치하는 곳입니다.frontend은 nginx입니다. 정적 자산을 제공하고 나머지 요청은 백엔드로 전달합니다.queue-short과queue-long는 RQ(Redis Queue) 워커입니다. 발신 이메일, 데이터 가져오기, 보고서 생성과 같은 백그라운드 작업을 처리합니다.scheduler은 예약된 보고서나 자동 반복 문서 등 시간 기반 작업을 실행합니다.websocket은 브라우저의 실시간 업데이트를 담당하는 socket.io 프로세스입니다.db는 MariaDB입니다.redis-cache과redis-queue는 각각 캐시와 작업 큐를 위한 별도의 Redis 인스턴스입니다.
이러한 구조를 파악해 두면 어떤 로그를 확인해야 할지 알 수 있어 유용합니다. 이메일 발송이 지연된다면 큐 워커의 문제이므로 docker compose logs -f queue-short 명령을 확인해야 합니다. 페이지는 로드되지만 알림 배지가 업데이트되지 않는다면 웹소켓 문제입니다. 이 경우 backend 로그를 읽는 것은 시간 낭비일 뿐입니다.
데모용이 아닌 프로덕션용 compose 파일로 설치하기
저장소는 pwd.yml을 제공하며, README는 이에 대해 "이 설정은 단기 평가용입니다. 이 설정에는 사용자 지정 앱을 설치할 수 없습니다"라고 명확히 밝히고 있습니다. ERPNext를 잠시 살펴볼 때만 사용하십시오. 실제 운영 환경에서 실행해서는 안 됩니다.
sudo apt update && sudo apt install -y git
curl -fsSL https://get.docker.com | bash
git clone https://github.com/frappe/frappe_docker
cd frappe_docker
mkdir -p ~/gitops
cp example.env ~/gitops/erpnext.env~/gitops/erpnext.env을 열고 4개의 값을 변경하십시오. ERPNEXT_VERSION는 이미지 태그를 고정합니다. DB_PASSWORD은 예제 파일에서 123로 제공됩니다. SITES_RULE는 Traefik 라우팅 규칙이며, LETSENCRYPT_EMAIL은 인증서 경고를 수신합니다.
ERPNEXT_VERSION=v16.32.1
DB_PASSWORD=<a long random password>
SITES_RULE=Host(`erp.example.com`)
LETSENCRYPT_EMAIL=ops@example.com이제 하나의 compose 파일을 렌더링한 뒤 실행하십시오.
docker compose --project-name erpnext \
--env-file ~/gitops/erpnext.env \
-f compose.yaml \
-f overrides/compose.mariadb.yaml \
-f overrides/compose.redis.yaml \
-f overrides/compose.https.yaml \
config > ~/gitops/erpnext.yaml
docker compose --project-name erpnext -f ~/gitops/erpnext.yaml up -dconfig는 아무것도 시작하지 않습니다. 기본 파일과 오버라이드 파일을 병합하고 모든 변수가 치환된 결과를 출력합니다. 그 후 렌더링된 파일을 실행합니다. 이 추가 단계는 가치가 있습니다. 실행 중인 스택은 읽고 커밋할 수 있는 하나의 파일로 관리되므로, 누군가 env 파일을 수정하거나 저장소를 pull하더라도 설정이 임의로 변경되지 않습니다. 여러 Docker Compose 파일이 병합되는 방식에서 오버라이드 규칙을 자세히 설명합니다.
db가 시작되고 configurator이 종료될 때까지 몇 초간 기다린 후 사이트를 생성하십시오.
docker compose --project-name erpnext exec backend \
bench new-site --mariadb-user-host-login-scope=% \
--db-root-password '<your DB_PASSWORD>' \
--install-app erpnext \
--admin-password '<a strong admin password>' \
erp.example.com확인하십시오:
docker compose --project-name erpnext ps
docker compose --project-name erpnext exec backend bench --site erp.example.com list-appslist-apps은 frappe과 erpnext의 버전을 출력해야 합니다. 정상적인 ps은 9개의 서비스가 running 상태이며 restarting 상태인 서비스가 없음을 보여줍니다.
이 과정에서 자주 발생하는 문제는 두 가지입니다. --mariadb-user-host-login-scope=%은 Docker 환경에서 선택 사항이 아닙니다. 앱 컨테이너는 Docker 네트워크를 통해 MariaDB에 접근하므로 원격 호스트로 인식되며, localhost로 범위가 제한된 데이터베이스 사용자는 해당 위치에서 로그인할 수 없습니다. 이 경우 사이트 생성은 root 사용자에 대한 MariaDB 접근 거부 오류로 실패합니다. % 범위를 사용하면 새 사이트의 사용자가 해당 사설 네트워크의 모든 호스트에서 접근할 수 있습니다.
두 번째는 사이트 이름입니다. 프론트엔드는 기본적으로 HTTP Host 헤더를 기반으로 서비스할 사이트를 선택하므로, erpnext로 생성된 사이트는 erp.example.com로 접속할 수 없습니다(두 사이트가 모두 존재하더라도 마찬가지입니다). 위와 같이 도메인 이름을 따서 사이트 이름을 지정하거나, env 파일에서 FRAPPE_SITE_NAME_HEADER을 사이트 이름으로 설정한 뒤 compose 파일을 다시 렌더링하십시오.
HTTPS와 작동을 위한 전제 조건
compose.https.yaml 오버라이드는 Traefik을 443 포트에서 실행하고, 80 포트를 해당 포트로 리다이렉트하며, Let's Encrypt에서 인증서를 요청합니다. TLS(transport layer security)는 송장이나 세션 쿠키가 평문으로 네트워크를 통해 전송되지 않도록 보호합니다.
인증서가 발급되려면 두 가지 조건이 충족되어야 합니다. 첫째, erp.example.com에 대한 DNS A 레코드가 이미 해당 VPS를 가리키고 있어야 합니다. 둘째, 80 포트와 443 포트가 인터넷에서 접근 가능해야 합니다. Let's Encrypt는 80 포트에서 HTTP-01 챌린지를 수행하여 사용자가 해당 도메인 이름을 제어하고 있음을 확인하기 때문입니다. 서버 내부의 방화벽뿐만 아니라 클라우드 제공업체의 네트워크 방화벽도 확인하십시오. 이 둘은 별개의 제어 항목이며, 많은 사용자가 관리 패널의 방화벽 설정을 잊곤 합니다.
인증서는 cert-data 볼륨의 /letsencrypt/acme.json 경로에 저장됩니다. 브라우저에 사용자의 인증서 대신 기본 인증서가 표시된다면, docker compose --project-name erpnext ps에서 프록시 서비스 이름을 찾아 ACME(automatic certificate management environment) 관련 오류 로그를 확인하십시오. 동일한 서버에서 다른 웹 애플리케이션을 운영 중이신가요? 여러 Docker Compose 애플리케이션 앞단에 하나의 Traefik 인스턴스 배치하기 문서를 참조하여 443 포트 점유 문제 없이 프록시를 공유하는 방법을 확인하십시오.
아웃바운드 이메일, 또는 송장이 서버를 떠나지 않는 경우
이 단계는 대부분의 ERPNext 가이드에서 생략하지만, 시스템의 유용성을 결정짓는 핵심 요소입니다. 아웃바운드 메일이 정상적으로 작동하지 않으면 고객에게 송장이 전달되지 않고, 비밀번호 재설정 메일이 도착하지 않으며, 예약된 보고서도 발송되지 않습니다. ERPNext 스택에는 메일 서버가 포함되어 있지 않습니다.
VPS에서 포트 25를 통해 직접 메일을 발송하려고 시도하지 마십시오. 대부분의 호스팅 제공업체는 신규 계정의 아웃바운드 포트 25를 차단합니다. 설령 발송되더라도 신규 VPS IP 주소는 발송 평판이 없기 때문에 스팸으로 분류되거나 거부됩니다. 포트 587을 사용하는 인증된 릴레이를 사용하십시오.
권장되는 방법은 ERPNext 인터페이스의 Email Account 화면을 사용하는 것입니다. 이 화면은 비밀번호를 암호화하여 저장합니다. 또한 사이트 설정 파일에 직접 키를 입력할 수도 있습니다.
docker compose --project-name erpnext exec backend \
bench --site erp.example.com set-config mail_server smtp.example.com
docker compose --project-name erpnext exec backend \
bench --site erp.example.com set-config mail_port 587 --parse
docker compose --project-name erpnext exec backend \
bench --site erp.example.com set-config use_tls 1 --parse
docker compose --project-name erpnext exec backend \
bench --site erp.example.com set-config mail_login 'erp@example.com'
docker compose --project-name erpnext exec backend \
bench --site erp.example.com set-config auto_email_id 'erp@example.com'--parse은 "587" 문자열 대신 587을 숫자로 저장합니다. 파일을 다시 읽어 해당 두 값에 따옴표가 없는지 확인하십시오.
docker compose --project-name erpnext exec backend \
cat sites/erp.example.com/site_config.jsonmail_password는 명령줄이 아닌 Email Account 화면을 통해 설정하십시오. 그래야 암호화되어 저장되며 셸 기록에 남지 않습니다.
그런 다음 실제 메시지를 발송해 보십시오. Sales Invoice를 생성하여 본인이 제어하는 주소로 이메일을 보내고, 발송하는 동안 큐를 모니터링하십시오.
docker compose --project-name erpnext logs -f queue-short아웃바운드 메일은 백그라운드 작업으로 처리됩니다. 따라서 메시지가 도착하지 않는다면 브라우저의 오류보다는 해당 로그에서 실패한 작업으로 나타나는 경우가 많습니다. 발송 도메인에 대해 SPF(sender policy framework) 및 DKIM(domainkeys identified mail) 레코드를 게시하고 DMARC 정책을 추가하십시오. 이러한 설정이 없으면 기술적으로 올바른 송장이라도 고객의 스팸 메일함으로 들어갑니다. 전체 경로를 직접 관리하고 싶다면 자체 호스팅 Mailcow 메일 서버를 사용하여 ERP와는 별도의 서버에서 제어 가능한 릴레이를 구축할 수 있습니다.
실제로 복구 가능한 백업
데이터베이스 덤프만으로는 ERPNext의 백업이 되지 않습니다. 첨부 파일과 개인 파일은 MariaDB가 아닌 sites 디렉터리에 저장됩니다. 데이터베이스만 복구하면 업로드된 모든 구매 주문서가 깨진 링크로 나타납니다.
docker compose --project-name erpnext exec backend \
bench --site erp.example.com backup --with-files이 명령은 sites 볼륨 내부의 sites/erp.example.com/private/backups 경로에 네 개의 파일을 생성합니다.
-database.sql.gz덤프- 공개 파일의
-files.tar아카이브 - 개인 파일의
-private-files.tar아카이브 - 사이트 설정의
-site_config_backup.json복사본
네 번째 파일은 사람들이 흔히 간과하지만, 가장 중요한 파일입니다. 이 파일에는 Frappe가 저장된 비밀번호(이메일 계정 자격 증명, 결제 게이트웨이 키, 모든 연동 보안 정보)를 암호화하는 데 사용하는 키인 encryption_key이 포함되어 있습니다. 일치하는 키 없이 데이터베이스를 복구하면 사이트는 정상적으로 로드되지만, 메일 발송 시 다음과 같은 오류가 발생합니다.
frappe.exceptions.ValidationError: Encryption key is invalid! Please check site_config.json네 개의 파일을 항상 함께 보관하십시오.
그런 다음 서버 외부로 옮겨야 합니다. 볼륨 내부의 백업은 서버 장애 시 함께 소실되며, bench는 기본적으로 해당 디렉터리에서 24시간이 지난 백업을 삭제합니다.
docker compose --project-name erpnext cp \
backend:/home/frappe/frappe-bench/sites/erp.example.com/private/backups \
~/erpnext-backups이 작업을 cron에서 실행한 다음, 관리하지 않는 다른 곳으로 디렉터리를 전송하십시오. 오프사이트 저장소로 암호화된 restic 백업은 업로드 전에 데이터를 암호화하고 restic check을 통해 저장소가 읽기 가능한 상태인지 검증하므로 적절한 도구입니다. ERP 백업은 전체 원장의 복사본이므로, 현재 서버가 아닌 다른 하드웨어에 암호화된 상태로 보관해야 합니다.
복구 작업은 필요하기 전에 미리 테스트하십시오
테스트하지 않은 백업은 추측에 불과합니다. 백업 데이터는 운영 중인 사이트가 아닌, 동일한 서버 내의 별도 사이트에 복구하여 테스트하십시오.
docker compose --project-name erpnext exec backend \
bench new-site --mariadb-user-host-login-scope=% \
--db-root-password '<your DB_PASSWORD>' \
--admin-password '<a strong admin password>' \
restore-test.example.com
docker compose --project-name erpnext exec backend \
bench --site restore-test.example.com --force restore \
sites/erp.example.com/private/backups/<stamp>-erp.example.com-database.sql.gz \
--with-public-files sites/erp.example.com/private/backups/<stamp>-erp.example.com-files.tar \
--with-private-files sites/erp.example.com/private/backups/<stamp>-erp.example.com-private-files.tar \
--db-root-password '<your DB_PASSWORD>'백업된 설정 파일에서 암호화 키를 복사하여 복구된 사이트에 적용하십시오. 그렇지 않으면 연동 기능이 정상적으로 작동하지 않습니다.
docker compose --project-name erpnext exec backend \
bench --site restore-test.example.com set-config encryption_key '<value from site_config_backup.json>'이제 회계사가 검토하듯 복구 상태를 확인하십시오. 매출 채권 보고서를 열어 마감 잔액이 운영 사이트와 일치하는지 비교하십시오. 최근 매입 송장을 열어 첨부 파일을 다운로드하십시오. 로그인 페이지만 표시된다고 해서 복구가 완료된 것은 아닙니다.
테스트가 끝나면 테스트용 사이트를 삭제하십시오:
docker compose --project-name erpnext exec backend \
bench drop-site restore-test.example.comERPNext에서 버전 고정이 중요한 이유
정적 사이트에서 태그를 고정하지 않으면 예기치 않은 재시작이 발생할 뿐이지만, ERPNext에서는 데이터베이스 스키마 마이그레이션이 실행됩니다. bench migrate은 데이터베이스 테이블을 재작성하며 문서 데이터까지 변경할 수 있는데, 이를 되돌릴 방법은 없습니다. 롤백을 하려면 docker compose down가 아니라 백업본을 복원해야 합니다.
따라서 태그를 반드시 고정하십시오. ERPNEXT_VERSION=v16.32.1은 2026년 8월 기준 저장소의 pwd.yml에 고정된 릴리스였습니다. 해당 번호를 확인 없이 그대로 사용하지 마십시오. 현재 릴리스는 frappe/erpnext 릴리스 페이지에서 확인할 수 있으며, 존재하는 이미지 태그는 Docker Hub에서 볼 수 있습니다. 버전을 변경하기 전에 이동하려는 버전의 릴리스 노트를 읽어보십시오.
업그레이드 작업은 백업과 유지보수 모드 설정으로 시작합니다.
docker compose --project-name erpnext exec backend \
bench --site erp.example.com backup --with-files
docker compose --project-name erpnext exec backend \
bench --site erp.example.com set-maintenance-mode on~/gitops/erpnext.env의 ERPNEXT_VERSION를 수정한 뒤, 설정을 렌더링하고 이미지를 내려받은 후 마이그레이션을 수행하십시오.
docker compose --project-name erpnext \
--env-file ~/gitops/erpnext.env \
-f compose.yaml \
-f overrides/compose.mariadb.yaml \
-f overrides/compose.redis.yaml \
-f overrides/compose.https.yaml \
config > ~/gitops/erpnext.yaml
docker compose --project-name erpnext -f ~/gitops/erpnext.yaml pull
docker compose --project-name erpnext -f ~/gitops/erpnext.yaml up -d
docker compose --project-name erpnext exec backend \
bench --site erp.example.com migrate
docker compose --project-name erpnext exec backend \
bench --site erp.example.com set-maintenance-mode off유지보수 모드가 중요한 이유는 migrate가 실행되는 동안 스키마를 변경하기 때문입니다. 마이그레이션이 진행 중인 테이블에 사용자가 문서를 제출하면, 나중에 수동으로 레코드를 복구해야 하는 상황이 발생합니다.
메이저 버전은 한 번에 하나씩 이동하며, 각 단계 사이에 반드시 백업을 수행하십시오. 릴리스에 포함된 마이그레이션 코드는 이전 버전에서 업그레이드하도록 작성되어 있으므로, 메이저 버전을 건너뛰면 아무도 테스트하지 않은 조합으로 마이그레이션이 실행됩니다.
또한 저장소는 overrides/compose.migrator.yaml를 제공하는데, 이는 컨테이너가 시작될 때마다 bench --site all migrate을 실행합니다. 편리한 기능이지만, 태그가 변경된 상태로 docker compose up을 수행하면 아무도 지켜보지 않는 상황에서 운영 데이터베이스가 마이그레이션될 수 있습니다. 비즈니스 시스템에서는 마이그레이션을 당일 아침에 직접 결정하고 실행하십시오.
고객 기록을 보관하는 서버 강화
최초 로그인 시 관리자 비밀번호를 변경하십시오. 평가용 compose 파일은 기본값으로 admin을 비밀번호로 사용하며, 이 습관이 운영 환경까지 이어지는 경우가 많습니다.
example.env 내의 123에서 DB_PASSWORD를 변경하십시오. 해당 값은 렌더링된 ~/gitops/erpnext.yaml에 일반 텍스트로 노출되므로, 파일을 chmod 600 처리하고 git 저장소에 포함되지 않도록 하십시오. 더 강력한 보안을 위해 overrides/compose.mariadb-secrets.yaml는 환경 변수 대신 Docker secret 파일에서 비밀번호를 읽어옵니다. Docker Compose에서 환경 파일 및 secret 처리하기에서 각 방식의 장단점을 다룹니다.
필요한 포트만 공개하십시오. HTTPS 오버라이드를 사용하면 80번과 443번 포트만 노출됩니다. 데이터베이스 클라이언트 연결을 쉽게 하려고 db 서비스에 ports 매핑을 추가하지 마십시오. 이는 MariaDB를 공용 인터넷에 노출하는 행위입니다. 대신 docker compose --project-name erpnext exec backend bench mariadb을 사용하십시오. 호스트에서는 22, 80, 443번 포트만 허용하고 나머지는 차단하며, 클라우드 제공업체의 별도 네트워크 방화벽 설정도 확인하십시오.
System Manager 역할을 가진 모든 계정에 대해 시스템 설정에서 2단계 인증을 활성화하십시오. 해당 역할은 모든 문서를 읽고 모든 테이블을 내보낼 수 있으므로, 편의를 위한 계정이 아닌 관리자 계정으로 취급해야 합니다. 여러 자체 호스팅 앱을 운영 중이라면 앱마다 비밀번호를 늘리는 것보다 자체 호스팅 SSO 제공자로 Authentik 사용하기가 더 나은 선택입니다.
호스트에 패치를 적용하고 커널 업데이트를 위해 재부팅하십시오. 스택이 다시 정상적으로 시작될지 확인하려면, 각 서비스의 렌더링된 파일에서 restart 정책을 확인하십시오. 해당 정책이 없으면 재부팅 후 스택이 다시 시작되지 않습니다. 재부팅 후 Docker Compose 스택 자동 시작하기에서 systemd 관련 설정을 다룹니다.
ERPNext가 단일 VPS에서 감당하기 어려워질 때
하나의 VPS로도 소규모 기업의 업무를 오랫동안 처리할 수 있습니다. 하지만 더 이상 감당하기 어렵다는 신호는 다음과 같습니다.
- 백그라운드 작업이 쌓여 이메일 발송이나 데이터 가져오기가 몇 분 또는 몇 시간씩 지연됩니다.
docker inspect컨테이너가"OOMKilled": true상태이거나 종료 코드 137을 반환합니다.- 2초 걸리던 보고서 생성에 30초가 소요되며, MariaDB 프로세스가 CPU를 점유하고 있습니다.
- 백업 시간이 너무 길어져 다음 예약된 백업과 겹치게 됩니다.
가장 먼저 MariaDB가 다른 프로세스와 자원을 공유하지 않도록 분리하십시오. 데이터베이스와 Python 워커가 동일한 메모리를 두고 경쟁하며, 특히 buffer pool이 더 많은 메모리를 요구하기 때문입니다. 애플리케이션 서버의 사양을 높이는 것은 기대만큼 효과적이지 않습니다. 데이터베이스를 Docker 또는 호스트에서 실행하기 문서를 통해 관련 결정을 내릴 수 있으며, Docker Compose에서 메모리 제한 설정하기를 통해 특정 컨테이너가 다른 컨테이너의 자원을 고갈시키지 않도록 방지할 수 있습니다.
그다음에는 웹 서버의 용량을 늘리기보다 큐 워커(queue workers)를 추가하십시오. ERPNext에서 느려지는 작업은 주로 보고서 생성이나 대량 데이터 가져오기와 같은 백그라운드 작업입니다. 더 큰 서버를 도입하는 것보다 워커 컨테이너를 늘리는 것이 비용 효율적이며, 사용자가 실제로 겪는 불편을 즉각적으로 해결할 수 있습니다.
FAQ
VPS에서 ERPNext를 운영하려면 RAM이 얼마나 필요한가요?
공식 가이드에서는 4 GB RAM과 2 vCPU를 최소 사양으로 제시하지만, 이는 평가용일 뿐입니다. 실무에서 매일 사용하는 환경이라면 8 GB RAM, 4 vCPU, 그리고 100 GB SSD 구성을 권장합니다. 이보다 사양이 낮으면 부하 발생 시 커널의 OOM(Out of Memory) 킬러가 컨테이너를 강제 종료하며, 이때 docker inspect은 종료 코드 137과 함께 "OOMKilled": true 오류를 보고합니다. 이는 권장 시작점일 뿐이므로, 운영 첫 달 동안 실제 메모리 사용량을 모니터링해야 합니다.
pwd.yml을 운영 환경에서 사용해도 되나요?
아니요. 프로젝트 README에 명시된 대로 이는 단기 평가용이며, 사용자 정의 앱을 설치할 수 없습니다. MariaDB, Redis, HTTPS 오버라이드를 적용한 compose.yaml을 사용하고, docker compose config를 통해 하나의 파일로 렌더링한 뒤 해당 파일을 실행하십시오.
ERPNext 사이트 생성 직후 접속이 되지 않는 이유는 무엇인가요?
프런트엔드는 기본적으로 HTTP Host 헤더를 기준으로 서비스할 사이트를 결정하므로, 브라우저의 도메인과 사이트 이름이 일치해야 합니다. erpnext으로 생성한 사이트는 erp.example.com 주소로 접속할 수 없습니다. 도메인 이름을 사이트 이름으로 사용해 생성하거나, env 파일의 FRAPPE_SITE_NAME_HEADER 값을 사이트 이름으로 설정한 뒤 compose 파일을 다시 렌더링하고 스택을 재시작하십시오.
ERPNext 백업에는 무엇이 포함되어야 하나요?
-database.sql.gz 덤프, -files.tar 및 -private-files.tar 아카이브, -site_config_backup.json 설정 복사본 등 총 4가지 파일이 함께 보관되어야 합니다. bench --site erp.example.com backup --with-files을 실행하면 이 4가지가 모두 생성됩니다. 설정 복사본에는 encryption_key가 포함되어 있으므로, 이를 제외하고 복원하면 저장된 연동 비밀번호를 복호화할 수 없게 되며 Encryption key is invalid! Please check site_config.json 오류가 발생합니다.
데이터를 손상시키지 않고 ERPNext를 업그레이드하려면 어떻게 해야 하나요?
--with-files으로 백업을 수행하고 유지보수 모드를 켠 뒤, env 파일에서 ERPNEXT_VERSION을 변경하십시오. 이후 compose 파일을 다시 렌더링하고 이미지를 pull 받은 다음 스택을 올리고, bench --site erp.example.com migrate을 실행한 뒤 유지보수 모드를 끄십시오. migrate는 스키마와 문서 데이터를 되돌릴 수 없게 변경하므로, 반드시 메이저 버전별로 하나씩 업그레이드하고 릴리스 노트를 먼저 읽어야 합니다. 롤백은 시작 시점에 생성한 백업을 복원하는 방식으로만 가능합니다.