diff --git a/DOCKER_GUIDE.md b/DOCKER_GUIDE.md new file mode 100644 index 00000000..df230529 --- /dev/null +++ b/DOCKER_GUIDE.md @@ -0,0 +1,1008 @@ +# PR-Agent Docker 사용 가이드 + +이 가이드는 PR-Agent를 Docker로 빌드하고 실행하는 방법을 상세히 설명합니다. + +## 목차 +- [사전 요구사항](#사전-요구사항) +- [Docker 이미지 빌드](#docker-이미지-빌드) +- [실행 방법](#실행-방법) +- [환경 변수 설정](#환경-변수-설정) +- [배포 타입별 가이드](#배포-타입별-가이드) +- [Docker Compose 사용](#docker-compose-사용) +- [문제 해결](#문제-해결) + +--- + +## 사전 요구사항 + +### 1. Docker 설치 +```bash +# Docker 버전 확인 +docker --version + +# Docker Compose 버전 확인 (선택사항) +docker compose version +``` + +### 2. 필요한 API 키/토큰 +- **OpenAI API Key**: [https://platform.openai.com/api-keys](https://platform.openai.com/api-keys) +- **GitHub Personal Access Token**: [https://github.com/settings/tokens](https://github.com/settings/tokens) + - 필요한 권한: `repo` (전체 저장소 접근) + +### 3. 프로젝트 클론 +```bash +git clone https://github.com/Codium-ai/pr-agent.git +cd pr-agent +``` + +--- + +## Docker 이미지 빌드 + +PR-Agent는 **멀티 스테이지 빌드**를 사용하여 여러 배포 타입을 지원합니다. + +### 사용 가능한 빌드 타겟 + +| 타겟 | 용도 | 포트 | 실행 방식 | +|------|------|------|-----------| +| `cli` | CLI 명령어 실행 | - | 일회성 | +| `github_app` | GitHub 웹훅 서버 | 3000 | 데몬 | +| `gitlab_webhook` | GitLab 웹훅 서버 | 3000 | 데몬 | +| `bitbucket_app` | Bitbucket 앱 서버 | 3000 | 데몬 | +| `gitea_app` | Gitea 앱 서버 | 3000 | 데몬 | +| `azure_devops_webhook` | Azure DevOps 웹훅 | 3000 | 데몬 | +| `github_polling` | GitHub 폴링 서버 | - | 데몬 | +| `test` | 테스트 실행 | - | 일회성 | + +### 1. CLI 용 빌드 (권장 - 시작용) + +```bash +docker build \ + -f docker/Dockerfile \ + -t pr-agent:cli \ + --target cli \ + . +``` + +**설명:** +- `-f docker/Dockerfile`: Dockerfile 경로 지정 +- `-t pr-agent:cli`: 이미지 이름과 태그 +- `--target cli`: 빌드할 스테이지 지정 +- `.`: 빌드 컨텍스트 (프로젝트 루트) + +### 2. GitHub App 서버 빌드 + +```bash +docker build \ + -f docker/Dockerfile \ + -t pr-agent:github_app \ + --target github_app \ + . +``` + +### 3. GitLab Webhook 서버 빌드 + +```bash +docker build \ + -f docker/Dockerfile \ + -t pr-agent:gitlab_webhook \ + --target gitlab_webhook \ + . +``` + +### 4. 모든 타겟 한번에 빌드 + +```bash +#!/bin/bash +# build-all.sh + +TARGETS=("cli" "github_app" "gitlab_webhook" "bitbucket_app" "gitea_app" "test") + +for target in "${TARGETS[@]}"; do + echo "Building $target..." + docker build \ + -f docker/Dockerfile \ + -t pr-agent:$target \ + --target $target \ + . +done + +echo "All images built successfully!" +docker images | grep pr-agent +``` + +### 5. ARM Mac에서 AMD64 빌드 (배포용) + +```bash +# Apple Silicon Mac에서 x86_64용 빌드 +docker buildx build \ + --platform linux/amd64 \ + -f docker/Dockerfile \ + -t pr-agent:github_app \ + --target github_app \ + . +``` + +--- + +## 실행 방법 + +### 1. CLI 모드로 실행 + +#### 기본 사용법 +```bash +docker run --rm -it \ + -e OPENAI.KEY=sk-xxxxxxxxxxxxx \ + -e GITHUB.USER_TOKEN=ghp_xxxxxxxxxxxxx \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + review +``` + +**옵션 설명:** +- `--rm`: 컨테이너 종료 시 자동 삭제 +- `-it`: 대화형 모드 (로그 출력) +- `-e`: 환경 변수 설정 + +#### 다양한 명령어 예제 + +```bash +# PR 리뷰 +docker run --rm -it \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e GITHUB.USER_TOKEN=$GITHUB_TOKEN \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + review + +# PR 설명 생성 +docker run --rm -it \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e GITHUB.USER_TOKEN=$GITHUB_TOKEN \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + describe + +# 코드 개선 제안 +docker run --rm -it \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e GITHUB.USER_TOKEN=$GITHUB_TOKEN \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + improve + +# PR에 질문하기 +docker run --rm -it \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e GITHUB.USER_TOKEN=$GITHUB_TOKEN \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + ask "이 PR의 주요 변경사항은?" + +# 확장 모드로 개선 제안 (더 자세한 분석) +docker run --rm -it \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e GITHUB.USER_TOKEN=$GITHUB_TOKEN \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + improve --extended +``` + +### 2. 웹훅 서버 모드로 실행 + +#### GitHub App 서버 + +```bash +docker run -d \ + --name pr-agent-github \ + -p 3000:3000 \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e GITHUB.USER_TOKEN=$GITHUB_TOKEN \ + --restart unless-stopped \ + pr-agent:github_app +``` + +**옵션 설명:** +- `-d`: 백그라운드 실행 (데몬 모드) +- `--name`: 컨테이너 이름 지정 +- `-p 3000:3000`: 포트 매핑 (호스트:컨테이너) +- `--restart unless-stopped`: 자동 재시작 + +**서버 관리 명령어:** +```bash +# 로그 확인 +docker logs -f pr-agent-github + +# 컨테이너 중지 +docker stop pr-agent-github + +# 컨테이너 시작 +docker start pr-agent-github + +# 컨테이너 재시작 +docker restart pr-agent-github + +# 컨테이너 삭제 +docker rm -f pr-agent-github +``` + +#### GitLab Webhook 서버 + +```bash +docker run -d \ + --name pr-agent-gitlab \ + -p 3000:3000 \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e CONFIG.GIT_PROVIDER=gitlab \ + -e GITLAB.PERSONAL_ACCESS_TOKEN=$GITLAB_TOKEN \ + -e GITLAB.URL=https://gitlab.com \ + --restart unless-stopped \ + pr-agent:gitlab_webhook +``` + +#### Bitbucket App 서버 + +```bash +docker run -d \ + --name pr-agent-bitbucket \ + -p 3000:3000 \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e CONFIG.GIT_PROVIDER=bitbucket \ + -e BITBUCKET.BEARER_TOKEN=$BITBUCKET_TOKEN \ + --restart unless-stopped \ + pr-agent:bitbucket_app +``` + +### 3. 테스트 실행 + +```bash +# 전체 테스트 실행 +docker run --rm \ + pr-agent:test \ + pytest tests/ + +# 특정 테스트만 실행 +docker run --rm \ + pr-agent:test \ + pytest tests/unittest/test_configuration.py + +# 커버리지와 함께 실행 +docker run --rm \ + pr-agent:test \ + pytest --cov=pr_agent tests/ +``` + +--- + +## 환경 변수 설정 + +### 1. .env 파일 사용 (권장) + +`.env` 파일 생성: +```bash +cat > .env <" + exit 1 +fi + +PR_URL=$1 + +docker run --rm -it \ + --env-file .env \ + pr-agent:cli \ + --pr_url "$PR_URL" \ + review + +echo "Review completed for $PR_URL" +``` + +**실행:** +```bash +chmod +x review-pr.sh +./review-pr.sh https://github.com/owner/repo/pull/123 +``` + +**GitHub Actions 통합:** +```yaml +# .github/workflows/pr-agent-docker.yml +name: PR Agent Docker Review + +on: + pull_request: + types: [opened, synchronize] + +jobs: + review: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Build PR-Agent + run: | + docker build \ + -f docker/Dockerfile \ + -t pr-agent:cli \ + --target cli \ + . + + - name: Run PR Review + run: | + docker run --rm \ + -e OPENAI.KEY=${{ secrets.OPENAI_KEY }} \ + -e GITHUB.USER_TOKEN=${{ secrets.GITHUB_TOKEN }} \ + pr-agent:cli \ + --pr_url ${{ github.event.pull_request.html_url }} \ + review +``` + +### 2. GitHub App 서버 (웹훅) + +**사용 사례:** +- PR 이벤트에 자동 응답 +- 조직 전체에 배포 +- 지속적인 모니터링 + +**프로덕션 배포:** +```bash +# 1. 이미지 빌드 +docker build -f docker/Dockerfile -t pr-agent:github_app --target github_app . + +# 2. 서버 실행 +docker run -d \ + --name pr-agent-prod \ + -p 3000:3000 \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e GITHUB.USER_TOKEN=$GITHUB_TOKEN \ + -e CONFIG.LOG_LEVEL=INFO \ + --restart unless-stopped \ + --health-cmd "curl -f http://localhost:3000/health || exit 1" \ + --health-interval=30s \ + --health-timeout=10s \ + --health-retries=3 \ + pr-agent:github_app + +# 3. 로그 모니터링 +docker logs -f pr-agent-prod +``` + +**nginx 리버스 프록시 설정:** +```nginx +# /etc/nginx/sites-available/pr-agent +server { + listen 80; + server_name pr-agent.yourdomain.com; + + location / { + proxy_pass http://localhost:3000; + 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; + } +} +``` + +### 3. GitLab Webhook 서버 + +```bash +docker run -d \ + --name pr-agent-gitlab \ + -p 3000:3000 \ + -e OPENAI.KEY=$OPENAI_KEY \ + -e CONFIG.GIT_PROVIDER=gitlab \ + -e GITLAB.PERSONAL_ACCESS_TOKEN=$GITLAB_TOKEN \ + -e GITLAB.URL=https://gitlab.mycompany.com \ + -e GITLAB.SHARED_SECRET=$WEBHOOK_SECRET \ + --restart unless-stopped \ + pr-agent:gitlab_webhook +``` + +### 4. 테스트 환경 + +```bash +# 개발 환경에서 빌드 +docker build -f docker/Dockerfile -t pr-agent:test --target test . + +# 전체 테스트 스위트 실행 +docker run --rm \ + -v $(pwd)/test-results:/app/test-results \ + pr-agent:test \ + pytest --junit-xml=/app/test-results/junit.xml tests/ + +# 특정 테스트만 실행 +docker run --rm -it \ + pr-agent:test \ + pytest -v tests/unittest/test_configuration.py::test_settings +``` + +--- + +## Docker Compose 사용 + +### 1. 기본 docker-compose.yml + +```yaml +version: '3.8' + +services: + # CLI 서비스 (일회성 실행용) + pr-agent-cli: + build: + context: . + dockerfile: docker/Dockerfile + target: cli + image: pr-agent:cli + env_file: .env + profiles: ["cli"] + + # GitHub App 서버 + pr-agent-github: + build: + context: . + dockerfile: docker/Dockerfile + target: github_app + image: pr-agent:github_app + container_name: pr-agent-github + ports: + - "3000:3000" + env_file: .env + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/health"] + interval: 30s + timeout: 10s + retries: 3 + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + profiles: ["github"] + + # GitLab Webhook 서버 + pr-agent-gitlab: + build: + context: . + dockerfile: docker/Dockerfile + target: gitlab_webhook + image: pr-agent:gitlab_webhook + container_name: pr-agent-gitlab + ports: + - "3001:3000" + environment: + - CONFIG.GIT_PROVIDER=gitlab + env_file: .env + restart: unless-stopped + profiles: ["gitlab"] + + # 테스트 서비스 + pr-agent-test: + build: + context: . + dockerfile: docker/Dockerfile + target: test + image: pr-agent:test + volumes: + - ./test-results:/app/test-results + command: pytest --junit-xml=/app/test-results/junit.xml tests/ + profiles: ["test"] +``` + +### 2. Docker Compose 명령어 + +```bash +# 빌드 +docker compose build + +# GitHub App 서버 시작 +docker compose --profile github up -d + +# GitLab Webhook 서버 시작 +docker compose --profile gitlab up -d + +# 로그 확인 +docker compose logs -f pr-agent-github + +# 서버 중지 +docker compose --profile github down + +# 테스트 실행 +docker compose --profile test run --rm pr-agent-test + +# CLI 실행 (일회성) +docker compose run --rm pr-agent-cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + review + +# 모든 서비스 중지 및 삭제 +docker compose down +``` + +### 3. 프로덕션용 docker-compose.yml + +```yaml +version: '3.8' + +services: + pr-agent: + build: + context: . + dockerfile: docker/Dockerfile + target: github_app + image: pr-agent:github_app + container_name: pr-agent-production + ports: + - "3000:3000" + env_file: .env + restart: always + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "5" + deploy: + resources: + limits: + cpus: '2' + memory: 2G + reservations: + cpus: '0.5' + memory: 512M + networks: + - pr-agent-network + volumes: + - pr-agent-logs:/var/log/pr-agent + + # 선택사항: nginx 리버스 프록시 + nginx: + image: nginx:alpine + container_name: pr-agent-nginx + ports: + - "80:80" + - "443:443" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + - ./ssl:/etc/nginx/ssl:ro + depends_on: + - pr-agent + restart: always + networks: + - pr-agent-network + +networks: + pr-agent-network: + driver: bridge + +volumes: + pr-agent-logs: +``` + +**실행:** +```bash +# 프로덕션 환경 시작 +docker compose -f docker-compose.prod.yml up -d + +# 스케일 아웃 (여러 인스턴스) +docker compose -f docker-compose.prod.yml up -d --scale pr-agent=3 + +# 로그 확인 +docker compose -f docker-compose.prod.yml logs -f + +# 중지 및 정리 +docker compose -f docker-compose.prod.yml down -v +``` + +--- + +## 고급 사용법 + +### 1. 볼륨 마운트로 설정 파일 사용 + +```bash +# 설정 파일을 호스트에서 관리 +docker run --rm -it \ + -v $(pwd)/pr_agent/settings/.secrets.toml:/app/pr_agent/settings/.secrets.toml:ro \ + -v $(pwd)/custom-config.toml:/app/pr_agent/settings/configuration.toml:ro \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + review +``` + +### 2. 로그 파일 수집 + +```bash +docker run -d \ + --name pr-agent-github \ + -p 3000:3000 \ + -v $(pwd)/logs:/var/log/pr-agent \ + --env-file .env \ + pr-agent:github_app +``` + +### 3. 네트워크 격리 + +```bash +# 네트워크 생성 +docker network create pr-agent-net + +# 컨테이너 실행 +docker run -d \ + --name pr-agent \ + --network pr-agent-net \ + -p 3000:3000 \ + --env-file .env \ + pr-agent:github_app +``` + +### 4. 리소스 제한 + +```bash +docker run -d \ + --name pr-agent \ + --memory="2g" \ + --memory-swap="2g" \ + --cpus="1.5" \ + -p 3000:3000 \ + --env-file .env \ + pr-agent:github_app +``` + +### 5. 보안 강화 + +```bash +docker run -d \ + --name pr-agent \ + --read-only \ + --tmpfs /tmp \ + --security-opt no-new-privileges:true \ + --cap-drop ALL \ + -p 3000:3000 \ + --env-file .env \ + pr-agent:github_app +``` + +--- + +## 문제 해결 + +### 1. 빌드 실패 + +**문제:** `ERROR [internal] load metadata for docker.io/library/python:3.12.10-slim` + +**해결:** +```bash +# Docker 데몬 재시작 +sudo systemctl restart docker + +# 또는 캐시 없이 빌드 +docker build --no-cache -f docker/Dockerfile -t pr-agent:cli --target cli . +``` + +### 2. 실행 시 모듈 없음 에러 + +**문제:** `ModuleNotFoundError: No module named 'litellm'` + +**원인:** 잘못된 빌드 타겟 또는 불완전한 빌드 + +**해결:** +```bash +# 이미지 삭제 후 재빌드 +docker rmi pr-agent:cli +docker build -f docker/Dockerfile -t pr-agent:cli --target cli . +``` + +### 3. 권한 에러 + +**문제:** `403 {"message": "Must have admin rights to Repository."}` + +**원인:** GitHub 토큰의 권한 부족 + +**해결:** +1. GitHub 토큰 재생성 시 `repo` 전체 권한 선택 +2. Organization 저장소의 경우 `read:org` 권한 추가 +3. 토큰 확인: +```bash +curl -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user +``` + +### 4. API 키 에러 + +**문제:** `APIError: OpenAIException - Connection error` + +**해결:** +```bash +# 환경 변수 확인 +docker run --rm -it \ + --env-file .env \ + pr-agent:cli \ + env | grep -E "OPENAI|GITHUB" + +# 직접 환경 변수로 테스트 +docker run --rm -it \ + -e OPENAI.KEY=sk-test123 \ + -e GITHUB.USER_TOKEN=ghp-test123 \ + pr-agent:cli \ + --pr_url https://github.com/owner/repo/pull/123 \ + review +``` + +### 5. 포트 충돌 + +**문제:** `Error starting userland proxy: listen tcp4 0.0.0.0:3000: bind: address already in use` + +**해결:** +```bash +# 포트 사용 중인 프로세스 확인 +lsof -i :3000 + +# 다른 포트 사용 +docker run -d -p 3001:3000 --env-file .env pr-agent:github_app +``` + +### 6. 컨테이너 로그 확인 + +```bash +# 실시간 로그 +docker logs -f pr-agent-github + +# 최근 100줄 +docker logs --tail 100 pr-agent-github + +# 타임스탬프 포함 +docker logs -t pr-agent-github + +# 에러만 필터링 +docker logs pr-agent-github 2>&1 | grep -i error +``` + +### 7. 컨테이너 디버깅 + +```bash +# 실행 중인 컨테이너 접속 +docker exec -it pr-agent-github /bin/bash + +# 컨테이너 내부 확인 +docker exec pr-agent-github ls -la /app/pr_agent +docker exec pr-agent-github cat /app/pr_agent/settings/configuration.toml + +# 환경 변수 확인 +docker exec pr-agent-github env +``` + +### 8. 네트워크 문제 + +```bash +# 컨테이너 네트워크 확인 +docker inspect pr-agent-github | grep -A 10 Networks + +# 포트 매핑 확인 +docker port pr-agent-github + +# 컨테이너 내부에서 테스트 +docker exec pr-agent-github curl -I http://localhost:3000/health +``` + +--- + +## 유용한 스크립트 + +### 1. 완전 정리 스크립트 + +```bash +#!/bin/bash +# cleanup.sh - PR-Agent Docker 완전 정리 + +echo "Stopping all PR-Agent containers..." +docker ps -a | grep pr-agent | awk '{print $1}' | xargs -r docker stop + +echo "Removing all PR-Agent containers..." +docker ps -a | grep pr-agent | awk '{print $1}' | xargs -r docker rm + +echo "Removing all PR-Agent images..." +docker images | grep pr-agent | awk '{print $3}' | xargs -r docker rmi -f + +echo "Removing unused volumes..." +docker volume prune -f + +echo "Cleanup complete!" +docker images | grep pr-agent +``` + +### 2. 빠른 재배포 스크립트 + +```bash +#!/bin/bash +# redeploy.sh - GitHub App 빠른 재배포 + +set -e + +echo "Stopping existing container..." +docker stop pr-agent-github 2>/dev/null || true +docker rm pr-agent-github 2>/dev/null || true + +echo "Rebuilding image..." +docker build -f docker/Dockerfile -t pr-agent:github_app --target github_app . + +echo "Starting new container..." +docker run -d \ + --name pr-agent-github \ + -p 3000:3000 \ + --env-file .env \ + --restart unless-stopped \ + pr-agent:github_app + +echo "Waiting for container to be healthy..." +sleep 5 + +docker logs --tail 20 pr-agent-github + +echo "Deployment complete!" +``` + +### 3. 헬스 체크 스크립트 + +```bash +#!/bin/bash +# health-check.sh - 서버 상태 확인 + +CONTAINER_NAME="pr-agent-github" +HEALTH_URL="http://localhost:3000/health" + +if ! docker ps | grep -q $CONTAINER_NAME; then + echo "❌ Container $CONTAINER_NAME is not running" + exit 1 +fi + +if curl -sf $HEALTH_URL > /dev/null; then + echo "✅ PR-Agent is healthy" + exit 0 +else + echo "❌ PR-Agent health check failed" + docker logs --tail 50 $CONTAINER_NAME + exit 1 +fi +``` + +--- + +## 참고 자료 + +- [Dockerfile 문서](docker/Dockerfile) +- [공식 문서](https://qodo-merge-docs.qodo.ai/) +- [GitHub 설치 가이드](https://qodo-merge-docs.qodo.ai/installation/github/) +- [GitLab 설치 가이드](https://qodo-merge-docs.qodo.ai/installation/gitlab/) +- [설정 옵션](pr_agent/settings/configuration.toml) + +--- + +## 라이선스 + +Apache 2.0 - 자세한 내용은 [LICENSE](LICENSE) 참조