OpenProject: 엔터프라이즈급 오픈소스 프로젝트 관리 소프트웨어 Docker 설치 가이드




개요

OpenProject는 독일에서 개발된 선도적인 오픈소스 프로젝트 관리 소프트웨어로, GNU GPL v3 라이선스로 배포됩니다. 클래식, 애자일, 하이브리드 프로젝트 관리를 모두 지원하며, Gantt 차트, 작업 관리, 팀 협업, 시간/비용 추적 기능을 제공합니다. 유럽의 데이터 보호 기준을 충족하며, 데이터 주권이 중요한 조직에 적합합니다.

OpenProject의 핵심 철학

OpenProject는 “데이터 보호와 정보 보안”을 최우선으로, 오픈소스의 투명성과 엔터프라이즈급 기능을 결합했습니다. 독일 베를린에 본사를 둔 회사가 개발하여 EU 데이터 보호 규정을 완벽히 준수합니다.

주요 특징

기능설명
Gantt 차트프로젝트 타임라인 시각화, 의존성 관리
애자일 보드Scrum/Kanban 지원, 스프린트 관리
작업 패키지이슈/태스크/버그 통합 관리
팀 플래너주간/격주 캘린더로 리소스 할당
시간 추적작업별 시간 기록 및 보고서
비용 관리예산 설정 및 비용 추적
위키프로젝트 문서화
포럼팀 토론 공간
미팅 관리회의록 및 일정 관리
뉴스프로젝트 공지사항
BIM 지원건설/건축 프로젝트 지원 (Enterprise)

프로젝트 관리 도구 비교

기능OpenProjectJiraMS ProjectPlane
오픈소스
셀프호스팅제한적
Gantt 차트제한적
애자일 보드
시간 추적플러그인
비용 관리플러그인
위키Confluence
EU 데이터 준수
무제한 사용자제한적

에디션 비교

기능Community (무료)Enterprise
기본 프로젝트 관리
Gantt 차트
애자일 보드
시간/비용 추적
위키/포럼
고급 보고서
LDAP/SAML SSO
2FA
문서 관리 (실시간 협업)
전문 지원

시스템 요구 사항

항목최소 사양권장 사양 (200+ 사용자)
RAM4GB8GB+ (더 많은 워커 필요)
CPU2 코어4+ 코어
저장소20GB50GB+
PostgreSQL13+16+ 권장
Docker20.10+최신 버전

Docker Compose 설치

방법 1: All-in-One 컨테이너 (간단한 설치)

mkdir -p ~/openproject && cd ~/openproject

# 단일 컨테이너 실행
docker run -d \
  --name openproject \
  -p 8080:80 \
  -e OPENPROJECT_SECRET_KEY_BASE=your-secret-key-here \
  -e OPENPROJECT_HOST__NAME=openproject.yourdomain.com \
  -v openproject-pgdata:/var/openproject/pgdata \
  -v openproject-assets:/var/openproject/assets \
  openproject/openproject:15

방법 2: Docker Compose (프로덕션 권장)

1) 디렉토리 및 환경 변수 설정

mkdir -p ~/openproject && cd ~/openproject

.env 파일 생성:

# 도메인 설정
OPENPROJECT_HOST__NAME=openproject.yourdomain.com
OPENPROJECT_HTTPS=true

# Secret Key (필수 - 랜덤 문자열 생성)
OPENPROJECT_SECRET_KEY_BASE=your-very-long-random-secret-key-here-at-least-64-chars

# 데이터베이스
POSTGRES_USER=openproject
POSTGRES_PASSWORD=your_secure_db_password
POSTGRES_DB=openproject
DATABASE_URL=postgres://openproject:your_secure_db_password@db:5432/openproject

# 이메일 설정 (선택사항)
OPENPROJECT_EMAIL__DELIVERY__METHOD=smtp
OPENPROJECT_SMTP__ADDRESS=smtp.example.com
OPENPROJECT_SMTP__PORT=587
OPENPROJECT_SMTP__USER__NAME=your-email@example.com
OPENPROJECT_SMTP__PASSWORD=your-email-password
OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO=true
OPENPROJECT_MAIL__FROM=openproject@example.com

# 기타 설정
OPENPROJECT_DEFAULT__LANGUAGE=ko
OPENPROJECT_LOG__LEVEL=info

2) docker-compose.yml

version: "3.8"

x-op-app: &app
  image: openproject/openproject:15
  restart: unless-stopped
  environment:
    OPENPROJECT_HOST__NAME: ${OPENPROJECT_HOST__NAME}
    OPENPROJECT_HTTPS: ${OPENPROJECT_HTTPS:-false}
    OPENPROJECT_SECRET_KEY_BASE: ${OPENPROJECT_SECRET_KEY_BASE}
    DATABASE_URL: ${DATABASE_URL}
    OPENPROJECT_EMAIL__DELIVERY__METHOD: ${OPENPROJECT_EMAIL__DELIVERY__METHOD:-}
    OPENPROJECT_SMTP__ADDRESS: ${OPENPROJECT_SMTP__ADDRESS:-}
    OPENPROJECT_SMTP__PORT: ${OPENPROJECT_SMTP__PORT:-}
    OPENPROJECT_SMTP__USER__NAME: ${OPENPROJECT_SMTP__USER__NAME:-}
    OPENPROJECT_SMTP__PASSWORD: ${OPENPROJECT_SMTP__PASSWORD:-}
    OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO: ${OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO:-}
    OPENPROJECT_MAIL__FROM: ${OPENPROJECT_MAIL__FROM:-}
    OPENPROJECT_DEFAULT__LANGUAGE: ${OPENPROJECT_DEFAULT__LANGUAGE:-en}
  volumes:
    - openproject-assets:/var/openproject/assets

services:
  db:
    image: postgres:15-alpine
    container_name: openproject-db
    restart: unless-stopped
    stop_grace_period: "3s"
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - openproject-pgdata:/var/lib/postgresql/data
    networks:
      - openproject-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5

  cache:
    image: memcached:alpine
    container_name: openproject-cache
    restart: unless-stopped
    networks:
      - openproject-network

  web:
    <<: *app
    container_name: openproject-web
    command: "./docker/prod/web"
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
      seeder:
        condition: service_completed_successfully
    networks:
      - openproject-network
    labels:
      - autoheal=true

  worker:
    <<: *app
    container_name: openproject-worker
    command: "./docker/prod/worker"
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
      seeder:
        condition: service_completed_successfully
    networks:
      - openproject-network

  cron:
    <<: *app
    container_name: openproject-cron
    command: "./docker/prod/cron"
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
      seeder:
        condition: service_completed_successfully
    networks:
      - openproject-network

  seeder:
    <<: *app
    container_name: openproject-seeder
    command: "./docker/prod/seeder"
    restart: on-failure
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    networks:
      - openproject-network

  proxy:
    image: nginx:alpine
    container_name: openproject-proxy
    restart: unless-stopped
    ports:
      - "8080:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - openproject-assets:/var/openproject/assets:ro
    depends_on:
      - web
    networks:
      - openproject-network

volumes:
  openproject-pgdata:
  openproject-assets:

networks:
  openproject-network:
    driver: bridge

3) Nginx 설정 파일 (nginx.conf)

upstream openproject {
    server openproject-web:8080;
}

server {
    listen 80;
    server_name _;

    client_max_body_size 100M;

    location / {
        proxy_pass http://openproject;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 300;
        proxy_connect_timeout 300;
    }

    location /assets {
        alias /var/openproject/assets;
        expires max;
        add_header Cache-Control public;
    }
}

4) 실행

docker-compose up -d

# 로그 확인
docker-compose logs -f

# 초기화 완료 확인 (seeder 완료까지 대기)
docker-compose logs seeder

Traefik 리버스 프록시 설정

services:
  proxy:
    image: nginx:alpine
    container_name: openproject-proxy
    restart: unless-stopped
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.openproject.rule=Host(`openproject.yourdomain.com`)"
      - "traefik.http.routers.openproject.entrypoints=websecure"
      - "traefik.http.routers.openproject.tls.certresolver=myresolver"
      - "traefik.http.services.openproject.loadbalancer.server.port=80"
    networks:
      - openproject-network
      - traefik-network

초기 설정

1) 웹 접속

브라우저에서 http://localhost:8080 또는 설정한 도메인으로 접속합니다.

2) 기본 관리자 계정

  • 사용자명: admin
  • 비밀번호: admin

첫 로그인 시 비밀번호 변경이 요구됩니다.

3) 시스템 설정

관리자로 로그인 후 Administration 메뉴에서:

  1. General settings: 언어, 시간대 설정
  2. Email settings: SMTP 설정 확인
  3. Users: 사용자 추가 및 권한 설정
  4. Roles and permissions: 역할별 권한 정의

주요 기능 활용

Gantt 차트 사용법

  1. 프로젝트 > Gantt charts 모듈 선택
  2. 작업 패키지 생성 및 시작/종료일 설정
  3. 드래그 앤 드롭으로 일정 조정
  4. 의존성 설정: 선행/후행 작업 연결
  5. PDF 내보내기 가능

애자일 보드 설정

  1. 프로젝트 > Boards 모듈 선택
  2. Action board 또는 Basic board 생성
  3. 컬럼 추가/수정 (To Do, In Progress, Done 등)
  4. 작업 패키지를 카드로 드래그 앤 드롭

팀 플래너

  1. 프로젝트 > Team planner 선택
  2. 팀원별 주간/격주 캘린더 뷰
  3. 작업 할당 및 일정 시각화
  4. 리소스 충돌 확인

작업 패키지 유형

유형용도
Task일반 작업
Feature새 기능 개발
Bug버그 수정
User Story사용자 스토리
Epic대규모 작업 그룹
Milestone주요 이정표
Phase프로젝트 단계

트러블슈팅

seeder 실패

# seeder 로그 확인
docker-compose logs seeder

# seeder 재실행
docker-compose restart seeder

데이터베이스 연결 오류

# DB 상태 확인
docker-compose exec db psql -U openproject -d openproject -c "SELECT 1"

# 마이그레이션 실행
docker-compose exec web bundle exec rails db:migrate

파일 업로드 실패

# assets 볼륨 권한 확인
docker-compose exec web ls -la /var/openproject/assets

# 권한 수정
docker-compose exec web chown -R app:app /var/openproject/assets

성능 최적화

# docker-compose.yml에서 워커 수 조정
environment:
  OPENPROJECT_WEB__WORKERS: 4
  OPENPROJECT_WEB__TIMEOUT: 300

백업 및 복원

데이터베이스 백업

# PostgreSQL 백업
docker-compose exec db pg_dump -U openproject openproject > openproject_backup_$(date +%Y%m%d).sql

# 복원
cat openproject_backup.sql | docker-compose exec -T db psql -U openproject openproject

Assets 백업

# assets 볼륨 백업
docker run --rm -v openproject_openproject-assets:/data -v $(pwd):/backup alpine tar czf /backup/assets_$(date +%Y%m%d).tar.gz /data

전체 백업 스크립트

#!/bin/bash
BACKUP_DIR="/backups/openproject/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR

# 데이터베이스
docker-compose exec -T db pg_dump -U openproject openproject > $BACKUP_DIR/database.sql

# Assets
docker run --rm -v openproject_openproject-assets:/data -v $BACKUP_DIR:/backup alpine tar czf /backup/assets.tar.gz /data

# 환경 변수
cp .env $BACKUP_DIR/

echo "Backup completed: $BACKUP_DIR"

업그레이드

# 백업 먼저 수행
./backup.sh

# 이미지 업데이트
docker-compose pull

# 서비스 재시작
docker-compose down
docker-compose up -d

# 마이그레이션 (자동 실행되지만 확인)
docker-compose logs seeder

Nextcloud 연동

OpenProject는 Nextcloud와 통합하여 파일 관리 기능을 확장할 수 있습니다:

  1. Nextcloud에 Team folders 앱 설치
  2. OpenProject 관리 > File storages에서 Nextcloud 연결
  3. 프로젝트별 자동 폴더 관리 가능 (Enterprise)



댓글 남기기