Skip to main content

GitHub Actions를 이용한 도커 자동 배포 가이드

등록일: 2026-04-27


NEXUS 프로젝트는 GitHub Actions를 통해 CI/CD 파이프라인을 구축함. 코드가 push 되거나 PR이 머지될 때 자동으로 빌드 및 배포가 수행되며, 필요 시 특정 모듈만 수동으로 배포할 수 있는 기능을 제공함.

1. 사전 준비 사항 (서버 설정)

자동 배포 스크립트가 서버의 자원을 제어하기 위해 반드시 선행되어야 하는 설정임.

1-1. sudoers 권한 설정 (포트 강제 해제용)

GitHub Actions 로봇은 비밀번호를 입력할 수 없으므로, fuser 명령어를 비밀번호 없이 실행할 수 있도록 허용해야 함.

  • 서버 접속 후 명령어 실행: sudo visudo
  • 파일 맨 아랫줄에 다음 내용 추가 (사용자 계정이 sleepzz인 경우):
sleepzz ALL=(ALL) NOPASSWD: /usr/bin/fuser

1-2. 디렉토리 구조

서버의 배포 경로는 /sorc001/nexus를 기준으로 함.

  • /sorc001/nexus/docker-compose.yml: 배포 스크립트에 의해 자동 갱신됨.
  • /sorc001/nexus/secrets/: 보안 민감 파일(global-secrets.yml)을 수동으로 위치시켜야 함.
  • /logs001/: 모든 컨테이너의 로그가 저장되는 절대 경로임.

2. GitHub Secrets 설정

GitHub 저장소의 Settings > Secrets and variables > Actions에 아래 항목들을 등록해야 함.

이름설명값 예시
GHCR_TOKENGitHub Container Registry 푸시 권한 토큰Personal Access Token (classic)
SSH_HOST배포 서버 주소sleepzz.xyz
SSH_PORTSSH 접속 포트200
SSH_USERSSH 접속 계정sleepzz
SSH_KEY서버 접속용 Private Keyid_rsa 파일 내용 전체

3. 워크플로우 로직 설명 (deploy.yml)

3-1. 변경 감지 (Detect Changes)

  • main 브랜치에 변경이 발생하면 어떤 모듈이 수정되었는지 확인함.
  • module-common이나 Gradle 설정 파일이 변경되면 모든 모듈을 재빌드 대상으로 선정함.
  • 그 외에는 수정된 디렉토리(예: module-system/)에 해당하는 모듈만 빌드 대상으로 선정함.

3-2. 빌드 및 푸시 (Build & Push)

  • Matrix 전략을 사용하여 선택된 모듈들을 병렬로 빌드함.
  • 빌드된 이미지는 GHCR에 latest 태그와 github.sha 태그를 달아 푸시함.
  • 이미지명 규칙: nexus-{name} (예: nexus-system, nexus-workout)

3-3. 서버 배포 (Deploy to Server)

배포 안정성을 위해 다음 프로세스를 순차적으로 수행함.

  1. SCP: 최신 docker-compose.yml 파일을 서버로 전송함.
  2. Down: docker compose down {service}를 통해 기존 컨테이너 및 네트워크 자원 정리함.
  3. Wait: 커널이 포트를 완전히 해제할 수 있도록 5초(sleep 5) 대기함.
  4. Kill: 유령 프로세스 방지를 위해 sudo fuser -k -9 {port}/tcp를 실행하여 포트를 강제로 확보함.
  5. Pull & Up: GHCR에서 최신 이미지를 가져와 컨테이너를 재생성함.

4. 수동 배포 방법 (Workflow Dispatch)

특정 모듈만 강제로 재배포하고 싶을 때 사용함.

  1. GitHub 저장소의 Actions 탭으로 이동함.
  2. 좌측 목록에서 Nexus CI/CD Pipeline을 선택함.
  3. Run workflow 드롭다운을 클릭함.
  4. 배포하고자 하는 모듈(예: nexus-system) 또는 all을 선택하고 버튼을 클릭함.

5. 트러블슈팅 및 팁

5-1. "Port is already allocated" 에러 발생 시

  • 배포 스크립트의 fuser 단계가 정상적으로 작동했는지 로그를 확인함.
  • sudoers 설정이 누락되어 "암호가 필요합니다" 메시지가 출력되는지 확인함.

5-2. 컨테이너 이름 뒤에 -1이 붙는 문제

  • docker-compose.yml에서 각 서비스에 container_name 속성을 명시하여 해결함.
  • 예: container_name: nexus-system

5-3. 로그 실시간 확인

서버에서 실시간 로그를 확인하고 싶을 때 아래 명령어를 사용함.

  • Docker 로그: docker logs -f nexus-system
  • 파일 로그: tail -f /logs001/nexus-system/output.log