스팸 필터 통합 메일 서버 구축 및 운영 안내서
Docker 기반 OpenProject 심층 운영 가이드
1. OpenProject Docker 환경 준비: 견고한 기반 마련
OpenProject를 성공적으로 배포하고 운영하기 위한 첫 단계는 안정적이고 표준화된 Docker 환경을 구축하는 것이다. 이 장에서는 프로덕션 환경에 가장 적합한 배포 아키텍처를 선정하고, OpenProject 실행을 위한 필수 환경을 준비하는 방법을 상세히 다룬다.
1.1 Docker Engine 설치: 필수 구성 요소
OpenProject 컨테이너를 실행하기 위해서는 Docker Engine이 반드시 필요하다. 각 운영체제에 맞는 공식적인 절차를 따라 설치를 진행해야 한다.
1.1.1 Linux (Ubuntu/Debian, RHEL/CentOS) 환경
Linux 환경에서는 각 배포판의 패키지 관리자를 통해 Docker 공식 저장소를 설정하고 최신 버전을 설치하는 것이 권장된다.
- 저장소 설정 및 Docker Engine 설치:
- Ubuntu/Debian:
apt패키지 관리자를 사용하여 Docker의 공식 GPG 키를 등록하고 저장소를 추가한다. 그 후, Docker Engine, CLI 및 containerd를 설치한다.
Bash
# 필수 패키지 설치
sudo apt-get update
sudo apt-get install -y ca-certificates curl
# Docker GPG 키 추가
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Docker 저장소 추가
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
# Docker Engine 설치
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
- RHEL/CentOS:
dnf(또는yum) 패키지 관리자를 사용하여 Docker 공식 저장소를 추가하고 관련 패키지를 설치한다.
Bash
# dnf-plugins-core 설치 및 저장소 설정
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# Docker Engine 설치
sudo dnf install -y docker-ce docker-ce-cli containerd.io
- sudo 없이 Docker 명령어 사용 설정:
설치 후 매번 sudo를 입력하지 않고 Docker 명령어를 실행하려면 현재 사용자를 docker 그룹에 추가해야 한다. 이는 보안상 주의가 필요하지만 개발 및 관리 편의성을 크게 향상시킨다.1
Bash
sudo usermod -aG docker $USER
이 변경 사항을 적용하려면 시스템에서 로그아웃한 후 다시 로그인하거나 새 터미널 세션을 시작해야 한다.
1.1.2 설치 확인
모든 설치가 완료된 후, 터미널에서 다음 명령어를 실행하여 Docker가 정상적으로 설치되었는지 확인한다.
Bash
# Docker 버전 확인
docker --version
# Docker 데몬 동작 테스트
docker run hello-world
hello-world 컨테이너가 성공적으로 실행되고 환영 메시지가 출력되면, Docker 환경 구축이 성공적으로 완료된 것이다.3
1.2 설치 방식 선정: 아키텍처 결정
OpenProject를 Docker로 배포하는 방식은 크게 두 가지로 나뉜다. 어떤 방식을 선택하느냐에 따라 시스템의 확장성, 안정성, 유지보수성이 결정되므로 신중한 접근이 필요하다.
- Docker Compose (다중 컨테이너): 이 방식은 OpenProject를 구성하는 각 기능(웹 서버, 백그라운드 워커, 데이터베이스, 캐시 서버 등)을 독립된 컨테이너로 분리하여 실행한다.4 각 서비스는
docker-compose.yml 파일에 정의되며, Docker Compose가 이들 간의 네트워크와 데이터 볼륨을 관리한다. 이는 서비스별로 자원을 할당하고, 개별적으로 업데이트하거나 확장할 수 있게 하여 장애 격리에도 유리하다. 이러한 장점 때문에 모든 프로덕션 환경에서는 Docker Compose 방식이 표준으로 강력히 권장된다.
- 단일 컨테이너 (All-in-one):
docker run명령어를 사용하여 모든 프로세스가 하나의 컨테이너 안에서 실행되는 방식이다.5 설치가 간편하여 빠른 기능 테스트나 개인적인 용도로는 유용할 수 있다.6 하지만 이 방식은 심각한 한계를 내포하고 있다.
단일 컨테이너 방식은 프로덕션 환경의 함정과 같다. 많은 공식 문서나 튜토리얼에서 docker run 명령어를 ‘빠른 시작’ 방법으로 제시하지만 6, 이는 장기적인 운영을 고려하지 않은 접근법이다. 공식 문서에서도 단일 컨테이너는 확장성이 부족하다고 명시적으로 경고하며 5, 다른 설치 방식에서 Docker 기반으로 마이그레이션할 때는 Docker Compose 사용을 권장한다.8 이는 Compose 방식이 전문가 수준의 운영 표준임을 명확히 보여준다.
단일 컨테이너 아키텍처는 웹, 백그라운드, 데이터베이스 프로세스를 하나의 실행 단위로 강하게 결합시킨다. 이로 인해 특정 프로세스의 부하가 다른 프로세스에 직접적인 영향을 미치는 성능 병목 현상이 발생하기 쉽고, 전체 시스템이 단일 장애점(Single Point of Failure)이 된다. ’쉽다’는 이유로 이 방식으로 프로덕션 환경을 구축한 사용자는 필연적으로 시스템 확장, 업그레이드, 유지보수 과정에서 심각한 기술적 부채에 직면하게 된다. 결국, 시스템을 확장하거나 안정적으로 운영하기 위해서는 복잡하고 위험 부담이 큰 마이그레이션 작업을 수행해야만 한다.8 따라서, 이 가이드에서는 초기 테스트 단계부터 프로덕션 배포까지
Docker Compose를 유일한 전략으로 채택할 것을 강력히 권고한다.
2. Docker Compose 기반 OpenProject 배포: 단계별 실행 가이드
이 장에서는 프로덕션 표준 방식인 Docker Compose를 사용하여 OpenProject를 배포하는 전체 과정을 단계별로 상세히 안내한다. 프로젝트 초기화부터 환경 변수 설정, 데이터 영속성 확보, 그리고 최종 실행까지 안정적인 시스템 운영을 위한 핵심 절차를 다룬다.
2.1 프로젝트 초기화 및 구조 이해
배포의 첫 단계는 공식 openproject-docker-compose 저장소를 로컬 시스템으로 복제하는 것이다. 이 저장소에는 OpenProject 스택을 실행하는 데 필요한 모든 구성 파일이 포함되어 있다.
- Git 저장소 복제:
터미널을 열고 다음 명령어를 실행하여 최신 안정화 버전(예: stable/16)의 저장소를 복제한다. 특정 버전을 명시하는 것은 예기치 않은 변경으로부터 배포 환경을 보호하는 좋은 습관이다.4
Bash
git clone https://github.com/opf/openproject-docker-compose.git --depth=1 --branch=stable/16 openproject
cd openproject
- 핵심 파일 구조:
복제된 openproject 디렉토리에는 여러 파일이 있지만, 그중 핵심은 다음 세 가지다.
-
docker-compose.yml: OpenProject를 구성하는 모든 서비스(예:proxy,web,worker,db)의 기본 정의, 네트워크 설정, 볼륨 등을 포함하는 핵심 파일이다. 이 파일은 직접 수정하지 않는 것이 원칙이다.10 -
.env.example: OpenProject 스택의 동작을 제어하는 환경 변수들의 예시와 설명을 담고 있는 템플릿 파일이다.4 -
docker-compose.override.yml.example: 기본docker-compose.yml설정을 덮어쓰거나 확장하기 위한 사용자 정의 파일의 템플릿이다. 이를 통해 원본 파일을 건드리지 않고도 커스터마이징이 가능하다.4
2.2 핵심 환경 구성: .env 파일 설정
OpenProject의 동작은 .env 파일에 정의된 환경 변수를 통해 제어된다. 예시 파일을 복사하여 실제 운영 환경에 맞게 수정해야 한다.
- .env 파일 생성:
.env.example 파일을 복사하여 실제 설정 파일인 .env를 생성한다.4
Bash
cp.env.example.env
- 필수 환경 변수 설정:
텍스트 편집기로 .env 파일을 열고 다음의 필수 변수들을 설정한다. 이 변수들은 시스템의 보안과 정상적인 작동에 직접적인 영향을 미친다.
OPENPROJECT_SECRET_KEY_BASE: Rails 애플리케이션의 세션 데이터와 쿠키를 암호화하는 데 사용되는 비밀 키다. 이 값은 반드시 예측 불가능한 무작위 문자열로 설정해야 한다.secret과 같은 기본값을 사용하는 것은 심각한 보안 취약점이다. Linux 환경에서는 다음 명령어로 강력한 키를 생성할 수 있다.7
Bash
# 생성된 문자열을 복사하여.env 파일에 붙여넣는다.
head /dev/urandom | tr -dc A-Za-z0-9 | head -c 32 ; echo ''
-
OPENPROJECT_HOST__NAME: 사용자가 웹 브라우저를 통해 OpenProject에 접속할 때 사용하는 전체 도메인 이름 또는 IP 주소와 포트를 정확하게 입력해야 한다 (예:openproject.example.com). 이 값은 시스템이 생성하는 이메일 알림 내 링크나 리디렉션 URL에 사용되며, 잘못 설정될 경우 기능 오작동을 유발한다. 또한, 올바른 호스트 이름을 명시하는 것은 Host 헤더 공격과 같은 웹 보안 위협을 방지하는 데 중요한 역할을 한다.7 -
OPENPROJECT_HTTPS: 외부 리버스 프록시에서 TLS/SSL을 처리하는 경우, 이 값을true로 설정해야 한다. 이는 OpenProject 애플리케이션에 원본 요청이 HTTPS였음을 알려, 보안 쿠키를 사용하고 올바른https://링크를 생성하도록 한다. 이 값을false로 두면 프로덕션 환경에서 보안 문제가 발생할 수 있다.13
다음 표는 OpenProject 설치 시 반드시 검토하고 설정해야 할 주요 환경 변수들을 요약한 것이다.
[표 1] 주요 환경 변수 설정 가이드
| 환경 변수명 | 설명 | 기본값/예시 | 중요도 |
|---|---|---|---|
OPENPROJECT_SECRET_KEY_BASE | 애플리케이션의 암호화 키. 반드시 고유하고 무작위적인 값으로 설정해야 한다. | secret (예시) | 필수 (보안) |
OPENPROJECT_HOST__NAME | 외부에서 접속하는 전체 호스트 이름. 이메일 링크 생성 등에 사용된다. | localhost:8080 | 필수 |
PORT | OpenProject가 외부에 노출할 포트 번호. | 8080 | 선택 |
OPENPROJECT_HTTPS | 외부 리버스 프록시에서 TLS/SSL을 처리하는 경우 true로 설정한다. | false | 필수 (보안) |
OPDATA | 데이터 볼륨(pgdata, assets)이 저장될 호스트의 경로. | ./opdata | 필수 (데이터) |
POSTGRES_PASSWORD | PostgreSQL 데이터베이스의 postgres 사용자 비밀번호. | (무작위 생성) | 필수 (보안) |
DATABASE_URL | OpenProject가 데이터베이스에 연결하기 위한 URL. 일반적으로 자동 생성된다. | postgres://... | 정보 |
EMAIL_DELIVERY_METHOD | 이메일 발송 방식. SMTP 사용 시 smtp로 설정. | smtp | 선택 (알림) |
SMTP_ADDRESS | SMTP 서버 주소. | smtp.example.com | 선택 (알림) |
OPENPROJECT_RAILS__RELATIVE__URL__ROOT | 하위 디렉토리에서 OpenProject를 실행할 경우 경로를 지정한다. | /openproject | 고급 |
2.3 데이터 영속성 확보: Docker 볼륨 전략
Docker 컨테이너는 기본적으로 상태 비저장(stateless)이다. 즉, 컨테이너가 삭제되거나 재생성되면 내부의 모든 데이터는 사라진다. 따라서 OpenProject의 핵심 데이터인 PostgreSQL 데이터베이스 파일과 사용자가 업로드한 첨부 파일 등은 컨테이너 외부의 영속적인 저장소에 보관해야 한다. 이는 선택 사항이 아닌, 모든 운영 환경의 필수 요구사항이다.
가장 간단한 docker run 예제들은 데이터 영속성을 고려하지 않아 6, 이를 그대로 사용할 경우 업그레이드나 재시작 시 모든 데이터를 잃는 치명적인 결과를 초래할 수 있다. 백업 및 복원 절차 역시 데이터가 외부 볼륨에 마운트되어 있음을 전제로 한다.15 따라서
docker compose up 명령을 실행하기 전에 데이터 영속성 설정은 반드시 완료되어야 한다.
- 데이터 저장 경로 설정:
.env 파일에서 OPDATA 변수를 설정하여 호스트 시스템에 데이터가 저장될 절대 경로를 지정한다. 예를 들어, /var/openproject 디렉토리에 모든 데이터를 보관하도록 설정할 수 있다.
#.env 파일 내
OPDATA=/var/openproject
- 호스트 디렉토리 생성 및 권한 설정:
OPDATA에 지정한 경로를 호스트 시스템에 생성하고, Docker 컨테이너 내부의 openproject 사용자(기본적으로 UID 1000, GID 1000)가 해당 디렉토리에 파일을 읽고 쓸 수 있도록 소유권과 권한을 올바르게 설정해야 한다. 권한이 잘못되면 컨테이너가 시작되지 않거나 파일 업로드 시 오류가 발생한다.4
Bash
# 데이터 저장 디렉토리 생성
sudo mkdir -p /var/openproject/pgdata
sudo mkdir -p /var/openproject/assets
# 소유권 변경 (UID 1000, GID 1000)
sudo chown 1000:1000 -R /var/openproject
2.4 컨테이너 실행 및 초기 접속
모든 환경 구성이 완료되면, Docker Compose를 사용하여 OpenProject 스택을 실행할 수 있다.
- 컨테이너 실행:
프로젝트 디렉토리 내에서 다음 명령어를 실행하여 백그라운드 모드(-d)로 모든 서비스를 시작한다.12
Bash
docker compose up -d
이 명령은 docker-compose.yml에 정의된 이미지를 다운로드하고, 네트워크와 볼륨을 생성한 후 컨테이너들을 실행한다. 초기 실행 시 이미지를 다운로드하는 데 시간이 다소 소요될 수 있다.
- 로그 확인 및 모니터링:
컨테이너들이 정상적으로 시작되고 있는지 확인하기 위해 로그를 실시간으로 모니터링한다.
Bash
docker compose logs -f
로그에서 오류 메시지가 없는지 확인하고, 데이터베이스 연결 및 웹 서버 시작 메시지가 나타나는지 주시한다.
- 웹 인터페이스 접속 및 초기 설정:
컨테이너가 모두 정상적으로 실행되면, 웹 브라우저를 열고 설정한 주소로 접속한다. .env 파일의 PORT 변수를 변경하지 않았다면 기본 포트는 8080이다.
- URL:
http://<서버 IP 또는 도메인>:8080
초기 접속 시 로그인 화면이 나타난다. 기본 관리자 계정 정보는 다음과 같다.4
-
사용자명:
admin -
비밀번호:
admin
로그인 후 즉시 관리자 계정의 비밀번호를 예측하기 어려운 강력한 암호로 변경해야 한다. 이는 시스템 보안을 위한 가장 기본적인 첫 단계이다.
3. 프로덕션 환경을 위한 고급 구성
실제 다수의 사용자가 접속하는 프로덕션 환경을 구축하기 위해서는 보안, 알림, 확장성을 고려한 고급 구성이 필수적이다. 이 장에서는 외부 리버스 프록시 연동, 이메일 알림 설정, 그리고 사용자 정의 확장 방법을 심도 있게 다룬다.
3.1 외부 리버스 프록시 연동 및 HTTPS 설정
프로덕션 환경에서 모든 웹 트래픽을 암호화하는 것은 필수다. OpenProject Docker 이미지는 기본적으로 SSL을 처리하지 않으므로, 컨테이너 앞단에 Nginx Proxy Manager와 같은 리버스 프록시 서버를 배치하여 SSL 종료(SSL Termination)를 처리하는 것이 표준 아키텍처다.19
이러한 구성에서 가장 중요한 것은 리버스 프록시와 OpenProject 컨테이너 간의 올바른 통신 설정이다.
- 리버스 프록시의 역할:
외부 사용자의 HTTPS 요청을 리버스 프록시가 수신하여 TLS 암호화를 해제하고, 내부망을 통해 OpenProject 컨테이너의 HTTP 포트(기본 8080)로 요청을 전달한다. 이 과정에서 리버스 프록시는 원본 요청이 HTTPS였음을 백엔드에 알려주는 특별한 HTTP 헤더를 추가해야 한다.
- 필수 HTTP 헤더 설정:
사용 중인 리버스 프록시(Nginx Proxy Manager 등)에서 OpenProject로 요청을 전달할 때, 다음 헤더가 반드시 설정되어 있는지 확인해야 한다.
-
X-Forwarded-Proto: https: 이 헤더는 OpenProject 애플리케이션에 원본 사용자 요청이 HTTPS 프로토콜을 통해 들어왔음을 알려주는 가장 중요한 정보다. 이 헤더가 없으면 OpenProject는 자신이 HTTP 환경에서 실행 중이라고 착각하여 잘못된 URL(http://…)을 생성하거나, 보안 쿠키 설정을 비활성화하는 등 심각한 문제를 일으킬 수 있다.19 -
Host: 이 헤더는 원본 요청의 호스트 이름(예:openproject.example.com)을 그대로 전달하여 OpenProject가 올바른 도메인 컨텍스트에서 작동하도록 한다.19
- OpenProject 환경 변수 설정:
리버스 프록시가 위 헤더들을 올바르게 전달한다는 전제하에, OpenProject의 .env 파일에서도 HTTPS를 사용하도록 명시해야 한다. 이는 OpenProject가 이메일 알림 등 비요청 컨텍스트에서 링크를 생성할 때 https 스킴을 사용하도록 강제하는 역할을 한다.19
#.env 파일 내
OPENPROJECT_HTTPS=true
이 설정은 단순히 컨테이너 내부에서 SSL을 활성화하는 것이 아니라, 애플리케이션 로직이 HTTPS 환경을 인지하도록 만드는 핵심적인 스위치다. 모든 설정이 완료되면 docker compose restart 명령으로 OpenProject 컨테이너를 재시작하여 변경 사항을 적용한다.
3.2 이메일 알림(SMTP) 설정
프로젝트의 변경 사항, 작업 할당 등의 알림을 받기 위해서는 아웃바운드 이메일(SMTP) 설정이 필수적이다. 이 설정은 .env 파일을 통해 이루어진다.23
- SMTP 관련 환경 변수 설정:
.env 파일에 사용하는 SMTP 서비스 제공업체(사내 메일 서버, Gmail, SendGrid 등)의 정보를 정확하게 입력한다.
#.env 파일 내 SMTP 설정 예시 (Gmail)
EMAIL_DELIVERY_METHOD="smtp"
SMTP_ADDRESS="smtp.gmail.com"
SMTP_PORT="587"
SMTP_DOMAIN="gmail.com"
SMTP_AUTHENTICATION="plain"
SMTP_ENABLE_STARTTLS_AUTO="true"
SMTP_USER_NAME="your-email@gmail.com"
SMTP_PASSWORD="your-app-password" # Gmail의 경우 앱 비밀번호 사용
- 설정 확인:
.env 파일 수정 후 docker compose restart로 컨테이너를 재시작한다. 그 다음, OpenProject에 관리자로 로그인하여 Administration > Emails and notifications 메뉴로 이동한다. 페이지 하단에서 ‘Send a test email’ 버튼을 클릭하여 설정이 올바른지 확인할 수 있다.25
3.3 사용자 정의 및 확장
기본 설치만으로 부족한 경우, docker-compose.override.yml 파일이나 커스텀 Docker 이미지를 통해 OpenProject를 확장할 수 있다.
- docker-compose.override.yml을 이용한 설정 변경:
기본 docker-compose.yml을 직접 수정하면 향후 업데이트 시 충돌이 발생할 수 있다. 따라서 사용자 정의 설정은 docker-compose.override.yml 파일에 추가하는 것이 모범 사례다. docker-compose.override.yml.example 파일을 복사하여 이 파일을 생성할 수 있다.4 예를 들어, 특정 서비스의 메모리 제한을 설정하거나 재시작 정책을 변경하려면 다음과 같이 작성할 수 있다.
YAML
# docker-compose.override.yml
services:
web:
mem_limit: 2g
restart: unless-stopped
worker:
mem_limit: 2g
restart: unless-stopped
- 커스텀 Docker 이미지를 이용한 플러그인 추가:
OpenProject는 다양한 플러그인을 지원하지만, 기본 Docker 이미지에는 포함되어 있지 않다. 플러그인을 추가하려면 새로운 Docker 이미지를 빌드해야 한다.13
- 프로젝트 루트에
Gemfile.plugins파일을 생성하고 설치할 플러그인을 명시한다.
Ruby
# Gemfile.plugins
gem "openproject-slack", git: "https://github.com/opf/openproject-slack.git", branch: "stable/16"
- 같은 위치에
Dockerfile.custom과 같은 이름으로 Dockerfile을 작성한다.
Dockerfile
# Dockerfile.custom
FROM openproject/openproject:16
# 플러그인 Gemfile 복사 및 설치
COPY Gemfile.plugins /app/
RUN bundle install
docker-compose.override.yml에서web과worker서비스가 이 커스텀 이미지를 사용하도록build지시어를 추가한다.
YAML
# docker-compose.override.yml
services:
web:
build:
context:.
dockerfile: Dockerfile.custom
worker:
build:
context:.
dockerfile: Dockerfile.custom
# seeder, cron 등 다른 서비스도 동일하게 설정
docker compose build명령으로 이미지를 빌드한 후,docker compose up -d로 실행한다.
4. OpenProject 시스템 운영 및 유지보수
시스템 구축 후에는 안정적인 운영을 위한 지속적인 유지보수가 필요하다. 이 장에서는 시스템 생명주기 동안 필수적인 업그레이드, 백업, 복원 절차와 컨테이너 관리 방법을 다룬다.
4.1 업그레이드 절차: 안정적인 버전 관리
OpenProject는 지속적으로 업데이트되므로, 보안 패치와 새로운 기능을 적용하기 위해 정기적인 업그레이드가 필요하다. 업그레이드는 단순한 명령 실행이 아니라, 데이터의 안전을 보장하는 엄격한 프로세스에 따라 수행되어야 한다.
docker compose pull이라는 간단한 명령 24 이면에는 “메이저 버전을 건너뛰지 말라“는 엄격한 규칙이 존재한다.5 이 두 가지 사이의 간극을 이해하는 것이 중요하다. 예를 들어, PostgreSQL 버전과 같은 핵심 의존성이 변경되는 메이저 업그레이드는 단순한 이미지 교체만으로는 해결되지 않을 수 있으며, 추가적인 데이터 마이그레이션 절차가 필요할 수 있다. 메이저 버전을 건너뛰면 데이터베이스 스키마 마이그레이션 스크립트가 순서대로 실행되지 않아 시스템이 복구 불가능한 상태에 빠질 수 있다. 따라서 강력한 업그레이드 전략은 명령어를 실행하는 것을 넘어, 각 버전의 릴리스 노트를 확인하고, 단계별 업그레이드를 수행하며, 완벽한 백업/복원 계획을 갖추는 것을 의미한다.
- 사전 준비 (필수):
업그레이드 작업 전에는 반드시 시스템 전체를 백업해야 한다. 이는 업그레이드 실패 시 데이터를 복구할 수 있는 유일한 안전장치다.5 백업 절차는 ’4.2. 백업 전략’을 참조하라.
- 마이너 버전 업그레이드 (예: 16.0.x -> 16.1.x):
마이너 버전 업그레이드는 일반적으로 하위 호환성을 유지하며, 비교적 간단한 절차를 따른다.
Bash
# 1. openproject-docker-compose 저장소의 최신 변경 사항을 가져온다.
git pull origin stable/16
# 2. 최신 버전의 Docker 이미지를 다운로드한다.
docker compose pull
# 3. 새 이미지를 사용하여 컨테이너를 다시 시작한다.
# 이 과정에서 필요한 데이터베이스 마이그레이션이 자동으로 수행된다.
docker compose up -d
- 메이저 버전 업그레이드 (예: 15.x.x -> 16.x.x):
메이저 버전 업그레이드는 데이터베이스 스키마 변경 등 중요한 변화를 포함할 수 있으므로 더욱 신중한 접근이 필요하다.
-
단계별 업그레이드: OpenProject는 한 번에 하나의 메이저 버전만 업그레이드할 수 있다. 예를 들어, 버전 14에서 16으로 직접 업그레이드하는 것은 지원되지 않으며, 반드시 14 -> 15 -> 16 순서를 거쳐야 한다.5
-
릴리스 노트 확인: 업그레이드할 각 메이저 버전의 공식 릴리스 노트를 반드시 읽고, 주요 변경 사항, 필수 사전/사후 조치, 의존성 변경 등을 숙지해야 한다.
-
절차:
git clone시점부터 새로운 메이저 버전의stable브랜치를 지정하여 프로젝트를 새로 구성하거나, 기존 프로젝트의git브랜치를 변경하고 관련 설정을 업데이트한 후 마이너 버전 업그레이드와 유사한 절차를 따른다.
4.2 백업 전략: 데이터 보호
정기적인 백업은 데이터 손실로부터 시스템을 보호하는 가장 중요한 활동이다. OpenProject의 백업은 데이터베이스와 첨부 파일 두 부분으로 구성된다.
- 데이터베이스 백업:
docker compose exec 명령어를 사용하여 실행 중인 데이터베이스 컨테이너(db) 내부에서 pg_dump를 실행한다. 이 명령은 데이터베이스의 전체 SQL 덤프를 생성하여 호스트 시스템의 파일로 저장한다.
Bash
# 현재 날짜를 포함한 파일명으로 SQL 덤프를 생성한다.
docker compose exec -T db pg_dump -U postgres -d openproject > openproject_backup_$(date +%F).sql
-T 옵션은 TTY 할당 없이 명령을 실행하여 스크립트에서 사용하기 용이하게 한다.
- 첨부 파일 및 설정 데이터 백업:
사용자가 업로드한 모든 파일과 기타 데이터는 .env의 OPDATA 변수로 지정된 호스트 디렉토리에 저장된다. 이 디렉토리 전체를 아카이빙 도구(예: tar)를 사용하여 압축하거나, rsync를 사용하여 다른 저장소로 동기화한다.16
Bash
# /var/openproject 경로를 백업한다고 가정
sudo tar -czvf openproject_data_$(date +%F).tar.gz /var/openproject
이 두 가지(데이터베이스 덤프, 볼륨 데이터 아카이브)가 함께 있어야만 완전한 상태로 시스템을 복원할 수 있다.
4.3 복원 절차: 재해 복구
시스템 장애나 데이터 손상 시 백업 데이터를 사용하여 시스템을 복원하는 절차는 다음과 같다.
- 복원 환경 준비:
새로운 서버에 Docker를 설치하고, 업그레이드할 때와 동일한 버전의 openproject-docker-compose 프로젝트를 git clone하여 초기화한다.
- 볼륨 데이터 복원:
백업해 둔 볼륨 데이터 아카이브(openproject_data_…tar.gz)의 압축을 풀어 새로운 서버의 OPDATA 경로(예: /var/openproject)에 위치시킨다. 데이터의 소유권과 권한이 올바른지 다시 한번 확인하고 설정한다 (sudo chown 1000:1000 -R /var/openproject).
- 데이터베이스 복원:
이 절차는 데이터베이스 컨테이너를 먼저 실행하고, 그 안에 백업된 SQL 덤프를 주입하는 방식으로 진행된다.
Bash
# 1. 데이터베이스 서비스만 먼저 시작한다.
docker compose up -d db
# 2. 기존에 생성되었을 수 있는 데이터베이스를 삭제하고 깨끗한 상태로 다시 생성한다.
docker compose exec -T db dropdb -U postgres openproject
docker compose exec -T db createdb -U postgres -O openproject openproject
# 3. 호스트에 있는 SQL 덤프 파일을 컨테이너로 복원한다.
cat openproject_backup_YYYY-MM-DD.sql | docker compose exec -T db psql -U postgres -d openproject
# 4. 복원이 완료되면 전체 스택을 시작한다.
docker compose up -d
모든 컨테이너가 시작된 후 웹 인터페이스에 접속하여 데이터가 정상적으로 복원되었는지 확인한다.
4.4 컨테이너 관리 및 모니터링
일상적인 운영 중에는 Docker Compose CLI를 사용하여 컨테이너의 상태를 확인하고 관리한다.
-
docker compose ps: 현재 프로젝트에 속한 모든 서비스(컨테이너)의 상태, 포트 정보 등을 표시한다. -
docker compose logs [서비스명]: 특정 서비스(예:web,worker) 또는 전체 스택의 로그를 실시간으로 확인하여 문제를 진단한다.-f옵션을 추가하면 로그를 계속 스트리밍한다.28 -
docker compose exec [서비스명][명령]: 실행 중인 컨테이너 내부로 들어가 셸(bash)을 실행하거나 특정 명령을 수행할 수 있다. 디버깅에 매우 유용하다.29 -
docker compose restart [서비스명]: 특정 서비스 또는 전체 서비스를 재시작한다. 설정 파일 변경 사항은 반영되지 않으며, 단순히 컨테이너를 껐다 켜는 동작이다. -
docker compose stop: 모든 서비스를 중지한다. 컨테이너는 삭제되지 않고 중지 상태로 남아있다. -
docker compose down: 모든 서비스를 중지하고, 컨테이너와 네트워크를 완전히 제거한다. 주의:-v옵션을 함께 사용하면 데이터 볼륨까지 삭제되므로, 데이터가 저장된 볼륨을 제거할 의도가 아니라면 절대 사용해서는 안 된다.
5. 문제 해결 가이드 (Troubleshooting)
이 장에서는 OpenProject Docker 환경을 운영하면서 마주칠 수 있는 일반적인 문제들과 그 해결 방안을 제시한다.
5.1 일반적인 오류 및 해결책
-
오류:
pull access denied for openproject/proxy, repository does not exist or may require 'docker login' -
원인: Docker Hub에서 이미지를 가져오는 데 실패한 경우다. 일시적인 네트워크 문제이거나, 비공개 이미지에 접근하려 할 때 발생할 수 있다. OpenProject 이미지는 공개되어 있으므로, 대부분 네트워크 문제일 가능성이 높다.
-
해결책: 먼저 인터넷 연결을 확인한다. 프록시 환경에 있다면 Docker가 해당 프록시를 사용하도록 설정해야 한다. 드물게 Docker Hub 인증이 필요한 경우
docker login명령을 실행한다.4 -
오류: 포트 충돌 (Port is already allocated)
-
원인:
.env파일에 설정된PORT(기본값 8080)를 호스트 시스템의 다른 프로세스가 이미 사용하고 있을 때 발생한다. -
해결책:
.env파일의PORT변수 값을 다른 포트(예:8081)로 변경하고docker compose up -d를 다시 실행한다.4 -
오류: 권한 거부 (Permission denied)
-
원인: 컨테이너 시작 시 로그에
Permission denied오류가 발생하거나, 파일 업로드 시 실패하는 경우, 대부분 호스트에 마운트된 볼륨 디렉토리의 소유권 및 권한 문제다. -
해결책: ’2.3. 데이터 영속성 확보’에서 설명한 바와 같이,
OPDATA로 지정된 디렉토리와 그 하위 디렉토리의 소유자를 컨테이너 내부 사용자인 UID 1000, GID 1000으로 설정해야 한다.sudo chown -R 1000:1000 /path/to/opdata명령을 실행하여 권한을 바로잡는다.4 -
오류: SMTP 설정 실패 (
Network is unreachable) -
원인: OpenProject 컨테이너가
.env에 설정된 SMTP 서버(SMTP_ADDRESS)에 접근할 수 없는 경우다. -
해결책: 다음 사항들을 순서대로 점검한다.4
-
호스트 서버의 방화벽(iptables, ufw 등)이 SMTP 포트(예: 587, 465, 25)로의 아웃바운드 트래픽을 허용하는지 확인한다.
-
클라우드 환경(AWS, GCP 등)이라면 보안 그룹 또는 네트워크 ACL에서 해당 포트가 열려 있는지 확인한다.
-
.env파일에 입력한SMTP_ADDRESS와SMTP_PORT가 정확한지 다시 한번 확인한다.
-
오류: 컨테이너 시작 실패 또는 반복적인 재시작
-
원인: 설정 오류, 자원 부족, 데이터베이스 마이그레이션 실패 등 다양한 원인이 있을 수 있다.
-
해결책:
docker compose logs [서비스명]명령을 사용하여 문제가 발생하는 특정 컨테이너의 로그를 상세히 확인하는 것이 문제 해결의 첫걸음이다. 로그의 마지막 부분에 출력된FATAL또는ERROR메시지를 통해 원인을 파악하고 조치한다.
5.2 보안 강화 권장 사항
안정적인 운영을 위해 다음의 보안 권장 사항을 반드시 준수해야 한다.
-
초기 관리자 계정 보안: 최초 로그인 후 즉시
admin계정의 비밀번호를 강력한 암호로 변경한다. -
HTTPS 강제 적용: 모든 프로덕션 환경에서는 리버스 프록시를 통해 HTTPS 통신을 강제하여 데이터 전송을 암호화한다.
-
강력한 비밀 키 사용:
.env파일의OPENPROJECT_SECRET_KEY_BASE에 예측 불가능한 무작위 문자열을 사용한다. -
정기적인 백업: 데이터베이스와 파일 시스템 볼륨에 대한 정기적인 백업 정책을 수립하고, 주기적으로 복원 테스트를 수행하여 백업의 유효성을 검증한다.
-
지속적인 업데이트: OpenProject와 Docker의 최신 안정화 버전을 주시하고, 보안 패치가 포함된 업데이트를 정기적으로 적용하여 알려진 취약점으로부터 시스템을 보호한다.
6. 참고 자료
- Postfix vs Exim vs Sendmail Email MTA - Which One to Use in 2025? - RunCloud, https://runcloud.io/blog/postfix-vs-exim-vs-sendmail
- Everything you need to know about Mail Transfer Agents (MTAs) - Halon Security, https://halon.io/blog/ultimate-guide-to-mail-transfer-agent-mtas
- Postfix vs Sendmail vs Exim - Choosing MTA - Mailtrap, https://mailtrap.io/blog/postfix-sendmail-exim/
- Choosing the Best MTA: Postfix vs Sendmail vs Exim: a Comprehensive Comparison - Plesk, https://www.plesk.com/blog/various/postfix-vs-sendmail-vs-exim/
- Rspamd - Open Source Email Security, https://rspamd.com/
- What is a mail transfer agent (MTA)? - Lenovo, https://www.lenovo.com/us/en/glossary/mail-transfer-agent/
- Message transfer agent - Wikipedia, https://en.wikipedia.org/wiki/Message_transfer_agent
- Exim vs Postfix: A Comparison - Liquid Web, https://www.liquidweb.com/blog/exim-vs-postfix/
- Comparison of email systems: Postfix vs Sendmail vs Exim - MailSlurp, https://www.mailslurp.com/blog/postfix-sendmail-exim/
- Compare Rspamd vs. SpamAssassin in 2025 - Slashdot, https://slashdot.org/software/comparison/Rspamd-vs-SpamAssassin/
- What Is Spam & Email Filtering? Definition | Proofpoint US, https://www.proofpoint.com/us/threat-reference/email-filtering
- Migrating from SpamAssassin - Rspamd Documentation, https://docs.rspamd.com/tutorials/migrate_sa/
- Quick start - Rspamd, https://rspamd.com/doc/tutorials/quickstart.html
- Rspamd vs. SpamAssassin Comparison - SourceForge, https://sourceforge.net/software/compare/Rspamd-vs-SpamAssassin/
- Introducing Advanced Spam and Phishing Filtering | Stalwart Labs, https://stalw.art/blog/spam-filter
- Question - Migration from Plesk Email Security (Amavis, SpamAssassin 3.x) to Rspamd 3.12 – Experiences?, https://talk.plesk.com/threads/migration-from-plesk-email-security-amavis-spamassassin-3-x-to-rspamd-3-12-experiences.378439/
- Rspamd: Fast, free and open-source spam filtering system - Zimbra Forums, https://forums.zimbra.org/viewtopic.php?t=62443
- Rspamd 3.9 Adds New GPT Plugin for Improved Spam Filtering - Linuxiac, https://linuxiac.com/rspamd-3-9-adds-new-gpt-plugin-for-improved-spam-filtering/
- Module rspamd_config - Rspamd Documentation, https://docs.rspamd.com/lua/rspamd_config/
- Writing Rules in SpamAssassin - Confluence Mobile - Apache Software Foundation, https://cwiki.apache.org/confluence/display/SPAMASSASSIN/writingrules
- MTA integration - Rspamd, https://rspamd.com/doc/tutorials/integration.html
- Integrating SpamAssassin into Postfix using spamd - Apache Software Foundation, https://cwiki.apache.org/confluence/display/spamassassin/IntegratedSpamdInPostfix
- Implementing SpamAssassin with Postfix on AlmaLinux 9 | Reintech media, https://reintech.io/blog/implementing-spamassassin-postfix-almalinux-9
- Postfix antispam with Spamassassin - TransIP, https://www.transip.eu/knowledgebase/postfix-antispam-with-spamassassin
- Run Your Own Email Server on CentOS 8/RHEL 8 - Postfix SMTP Server - LinuxBabe, https://www.linuxbabe.com/redhat/run-your-own-email-server-centos-postfix-smtp-server
- How To Secure Postfix Using Let’s Encrypt - UpCloud, https://upcloud.com/resources/tutorials/secure-postfix-using-lets-encrypt/
- Set up Postfix for incoming email - GitLab Docs, https://docs.gitlab.com/administration/reply_by_email_postfix_setup/
- Let’s Encrypt / Dovecot / Postfix / UFW firewall / Certbot - GitHub Gist, https://gist.github.com/mrothNET/cb6f313e9cbe896f3e0fdec80ad2f3fa
- Install and configure Postfix - Ubuntu Server documentation, https://documentation.ubuntu.com/server/how-to/mail-services/install-postfix/
- Postfix Basic Configuration, https://www.postfix.org/BASIC_CONFIGURATION_README.html
- Postfix Virtual Domain Hosting Howto, https://www.postfix.org/VIRTUAL_README.html
- postfix how to setup local domain users as virtual users - Server Fault, https://serverfault.com/questions/620045/postfix-how-to-setup-local-domain-users-as-virtual-users
- 10 Best Self-Hosted Email Server Platforms to Use in 2025 - RunCloud, https://runcloud.io/blog/best-self-hosted-email-server
- Postfix SASL Howto, https://www.postfix.org/SASL_README.html
- Postfix/dovecot SASL and SSL/TLS guide - CentOS Wiki, https://wiki.centos.org/HowTos/postfix_sasl
- Postfix with SASL - ArchWiki, https://wiki.archlinux.org/title/Postfix_with_SASL
- Postfix and Dovecot SASL, https://doc.dovecot.org/main/howto/sasl/postfix.html
- Postfix MySQL Howto, https://www.postfix.org/MYSQL_README.html
- Mail Server Configuration Tutorial: How to Use Postfix, Dovecot, MySQL, and SpamAssassin, https://blog.cloudsigma.com/mail-server-configuration-tutorial-how-to-use-postfix-dovecot-mysql-and-spamassassin/
- Installing and configuring Postfix & Dovecot - TransIP, https://www.transip.eu/knowledgebase/installing-and-configuring-postfix-dovecot
- Setting Up a Secure Email Server with Postfix, Dovecot, and MySQL …, https://raw.org/tutorial/seting-up-email-server-with-postfix-dovecot-and-mysql/
- Rspamd quick start, https://docs.rspamd.com/tutorials/quickstart/
- [Howto] Install Rspamd - CentOS Web Panel Forum, http://forum.centos-webpanel.com/how-to/(howto)-install-rspamd/
- MTA integration - Rspamd Documentation, https://docs.rspamd.com/tutorials/integration/
- Install and Integrate Rspamd - Linuxize, https://linuxize.com/post/install-and-integrate-rspamd/
- postfix + rspamd: postfix does not resolve virtual alias - Server Fault, https://serverfault.com/questions/957440/postfix-rspamd-postfix-does-not-resolve-virtual-alias
- OpenDMARC - ArchWiki, https://wiki.archlinux.org/title/OpenDMARC
- Scanning outbound mail - Rspamd Documentation, https://docs.rspamd.com/tutorials/scanning_outbound/
- Understanding Rspamd, https://docs.rspamd.com/getting-started/understanding-rspamd
- Configuration Guide | Rspamd Documentation, https://rspamd.com/doc/configuration/
- Tutorials and Guides - Rspamd Documentation, https://docs.rspamd.com/tutorials/
- Greylisting module - Rspamd Documentation, https://docs.rspamd.com/modules/greylisting/
- Fuzzy check module - Rspamd Documentation, https://docs.rspamd.com/modules/fuzzy_check/
- Usage of fuzzy hashes | Rspamd Documentation, https://docs.rspamd.com/tutorials/fuzzy_storage/
- Neural network module - Rspamd Documentation, https://docs.rspamd.com/modules/neural/
- Rspamd architecture, https://docs.rspamd.com/developers/architecture/
- Email Authentication Setup for Linux: SPF DKIM DMARC Guide. - Guardian Digital, https://guardiandigital.com/content/linux-email-authentication-postfix-spf-dkim-dmarc
- Hands-on: implementing SPF, DKIM and DMARC in Postfix | Cybersecurity - SIDN, https://www.sidn.nl/en/news-and-blogs/hands-on-implementing-spf-dkim-and-dmarc-in-postfix
- Postfix DKIM and SPF Setup for OpenDKIM on Linux - EasyDMARC, https://easydmarc.com/blog/how-to-add-opendkim-to-dns-on-linux-postfix/
- Complying with DMARC authentication protocol in Amazon SES - AWS Documentation, https://docs.aws.amazon.com/ses/latest/dg/send-email-authentication-dmarc.html
- Postfix TLS Support, https://www.postfix.org/TLS_README.html
- Securing Postfix with a LetsEncrypt Certificate - LucraLogic, https://lucralogic.com/securingPostfix.html
- Using Lets Encrypt With Postfix - Beamtic, https://beamtic.com/lets-encrypt-postfix
- How to Install and Configure SSL Certificate on Postfix? - Certera, https://certera.com/kb/how-to-install-and-configure-ssl-certificate-on-postfix/
- How To Install and Configure DKIM with Postfix on Debian Wheezy - DigitalOcean, https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-dkim-with-postfix-on-debian-wheezy
- Configuring DKIM for Postfix - Jack Stromberg, https://jackstromberg.com/2024/01/configuring-dkim-for-postfix/
- How to Configure DKIM (OpenDKIM) with Postfix | EasyDMARC, https://easydmarc.com/blog/how-to-configure-dkim-opendkim-with-postfix/
- Using DKIM with Postfix - TransIP, https://www.transip.eu/knowledgebase/using-dkim-with-postfix
- Setup DKIM (DomainKeys) with Postfix on Ubuntu & Debian - TecAdmin, https://tecadmin.net/setup-dkim-with-postfix-on-ubuntu-debian/
- How to Install and Configure OpenDKIM in Ubuntu - Tutorial & Documentation, https://www.webhi.com/how-to/install-configure-opendkim-linux-ubuntu-debian/
- opendkim - Debian Wiki, https://wiki.debian.org/opendkim
- Installing OpenDMARC RPM via Yum with Postfix or Sendmail (for …, https://www.stevejenkins.com/blog/2015/03/installing-opendmarc-rpm-via-yum-with-postfix-or-sendmail-for-rhel-centos-fedora/
- Set up DMARC (verification) for Postfix on Ubuntu - blog.matrixpost.net, https://blog.matrixpost.net/set-up-dmarc-for-postfix-on-ubuntu/
- Set Up OpenDMARC with Postfix on Ubuntu to Block Spam/Email Spoofing - LinuxBabe, https://www.linuxbabe.com/mail-server/opendmarc-postfix-ubuntu
- Email Server Test - Online SMTP diagnostics tool - MxToolbox, https://mxtoolbox.com/diagnostic.aspx
- Test SMTP connection and send test email - Febooti, Ltd., https://www.febooti.com/products/automation-workshop/tutorials/test-smtp-connection-send-test-email.html
- Domain Health Check - Online Domain Tools - Blacklist, Email, Website, DNS - MxToolBox, https://mxtoolbox.com/emailhealth
- MxToolbox Use Cases: Setting up a Mail Server, https://blog.mxtoolbox.com/2016/01/05/mxtoolbox-use-cases-setting-up-a-mail-server/
- MxToolbox: MX Lookup Tool - Check your DNS MX Records online, https://mxtoolbox.com/
- Network Tools: DNS,IP,Email - MxToolbox, https://mxtoolbox.com/SuperTool.aspx
- The GTUBE - Apache SpamAssassin, https://spamassassin.apache.org/gtube/
- GTUBE - Wikipedia, https://en.wikipedia.org/wiki/GTUBE
- How to test SpamAssassin or antivirus software in Plesk?, https://www.plesk.com/kb/support/how-to-test-spamassassin-or-antivirus-software-in-plesk/
- GTUBE-like test patterns - Rspamd Documentation, https://docs.rspamd.com/other/gtube_patterns/
- Analyzing Postfix logs: Mail server monitoring and troubleshooting guide - webhosting, https://webhosting.de/en/postfix-logs-analysis-mailserver-analysis-logfiles-guide-optimization/
- SendmailAnalyzer: Sendmail/Postfix log analyser, https://sareport.darold.net/