[DevOps] Synology NAS, Github Action으로 CI/CD(자동배포) 구축

Intro

안녕하세요 Noah입니다

오늘은 제가 최근에 진행한 프로젝트 중 하나인 Synology NAS에 Github Action을 이용한 CI/CD(자동배포) 구축에 대해 공유하고자 합니다.
3번정도 시도했다가 포기하고 마지막으로 해보잔 심정으로 도전했다가 성공한 내용이라 더욱 뿌듯하게 느껴지는 것 같습니다.

목차는 아래와 같습니다. ^^

본문

1. NAS 내 Docker 설치

  • 다양한 인터넷 예시가 존재하니 확인하시고 먼저 Docker부터 NAS에 설치해주시면 됩니다.
    예시) Synology NAS에 Docker 설치하는 방법

  • 설치 CLI로 NAS에 접속해 docker 설치 여부 확인

      docker --version
    

    DockerVersion.png


2. NAS 내 Key발급

  1. 계정의 root 디렉토리에 .ssh 폴더 내 Key 파일 생성
     ssh-keygen
    

    KeyFile.png


3. Repository 내 Docker Action Script 작성

Repository 내 .github/workflows 폴더 생성
  • 디렉토리 경로
    YMLFile.png
해당 폴더 내 .yml 파일 생성
  • 어떤 branches가 변경될 때 해당 Action을 실행할 것인지, 어떤 환경변수를 사용할 것인지 등을 정의합니다.
  • 여기서 SSH 연결하는 부분을 집중해서 봐주세요. 저는 여러 시도 끝에 이 부분을 해결하는 데에 많은 시간을 소비했었습니다. ㅠㅠ
  • “Build and Deploy Docker Image” 이 부분은 본인의 환경에 맞게 수정해주시면 됩니다. 저는 혹시 모를 상황을 대비해 배포 시 마다 폴더 자체를 삭제하고 다시 생성하도록 설정했습니다.
    • 이 부분은 본인의 환경에 맞게 수정하셔야 합니다.
  • 예시 코드
      name: Deploy to NAS Server
        
      on:
      push:
      branches: [ "dev" ]
        
      env:
      REGISTRY: ghcr.io
      IMAGE_NAME: $
        
      jobs:
      deploy:
      runs-on: ubuntu-latest
      steps:
      - name: Checkout code
      uses: actions/checkout@v2
        
            - name: Set up SSH connection
              uses: webfactory/ssh-agent@v0.5.3
              with:
                ssh-private-key: $
        
            - name: Build and Deploy Docker Image
              run: |
                ssh -o StrictHostKeyChecking=no $@$ -p $ << 'EOF'
                  cd /volume1/web/APP_PATH
                  rm -rf SERVER_NAME
                  mkdir SERVER_NAME
                  git clone -b dev --single-branch https://$:$@github.com/SERVER_NAME.git
                  cd SERVER_NAME
                  docker stop SERVER_DOCKER_IMG_NAME || true
                  docker rm SERVER_DOCKER_IMG_NAME || true
                  sleep 30
                  docker build -t SERVER_DOCKER_IMG_NAME:latest -f dev.Dockerfile . && \
                  docker run -d --name SERVER_DOCKER_IMG_NAME -e SPRING_PROFILES_ACTIVE=dev -e SPRING_DATASOURCE_PASSWORD=$ -e JWT_SECRET=$ -p 8080:8080 SERVER_DOCKER_IMG_NAME:latest
                EOF
    
파일 배포 전 확인 사항
  1. SSH_USERNAME으로 등록된 유저에게 폴더 관리 및 docker 명령어 실행 권한이 있는지 확인이 필요합니다.
  2. GIT_PASSWORD는 Token으로 발급받아 사용해야 합니다.
  3. SSH_PRIVATE_KEY는 NAS에서 만든 Private Key를 사용해야 합니다.(위 코드에선 Public Key로는 인증이 불가합니다.)


4. Repository 내 Secret Key 입력

  • 위 YML 파일에서 중괄호에 담아 사용한 환경변수들(ex- $)은 Repository 내 Action용 Secret Key를 등록하여 사용합니다.
    이를 통해 중요 KEY들이 외부로 노출되는 것을 막을 수 있습니다.
  • 등록 방법
    SecretKeyPath.png

    AddSecretKey.png


5. Dockerfile 작성

  • 본인 환경에 맞게 Dockerfile을 작성합니다. 이 때 Dockerfile용 폴더를 구분하실 거면 위 YML 파일에서 해당 폴더로 이동하는 부분을 수정해주셔야 합니다.
  • 아래는 Dockerfile 예시 코드입니다.
      # 베이스 이미지로 OpenJDK 17을 사용
      FROM openjdk:17-slim as build
        
      # Gradle 래퍼를 사용하기 위한 준비
      WORKDIR /app
      COPY gradlew .
      COPY gradle gradle
      COPY build.gradle .
      COPY settings.gradle .
      COPY src src
        
      # gradlew에 실행 권한 부여(이 부분을 제거하면 권한 부족으로 Build 불가)
      RUN chmod +x ./gradlew
        
      # 애플리케이션 빌드
      RUN ./gradlew build -x test
        
      # 빌드 결과물을 실행할 새로운 스테이지
      FROM openjdk:17-slim
      WORKDIR /app
      COPY --from=build /app/build/libs/APP_NAME.jar APP_NAME.jar
        
      # docker run 시 선언했던 환경 변수를 사용하여 애플리케이션 실행
      ENTRYPOINT java -jar app.jar -Dspring.profiles.active=${SPRING_PROFILES_ACTIVE} -Dspring.datasource.password=${SPRING_DATASOURCE_PASSWORD} -Djwt.secret=${JWT_SECRET}
    

6. Dockerfile 배포 확인

Github Console에서 Action 확인
  • Github Action으로 접근해 해당 Action이 정상적으로 동작하는지 확인합니다. 이 때 SSH 권한 관련해서 문제가 발생할 수 있으니 이 부분을 반드시 확인해야 합니다.
  • 각 권한 설정은 NAS마다 다르기 때문에 각자가 해결하셔야 하는 부분이라 이 부분은 생략하겠습니다. 다만 체크해보셔야 할 부분들을 조금 정리해보겠습니다.
    1. SSH 접속 유저에게 각종 명령어에 대한 권한이 있는지 확인
      배포 시 문제 해결을 위해 저는 ROOT 권한으로 설정했을 때도 되는지, 안되는지 체크하면서 권한을 하나씩 설정했습니다.
      안된다고 포기하지 마시고 우선 Root권한으로 설정해서 확인해보시고 되면 해당 유저에게 필요한 권한을 부여하시면 됩니다. 화이팅!
    2. 생성했던 Private Key가 정상적으로 맵핑되었는지 확인
      Private Key가 정상적인데도 SSH 연결 시 오류가 있다면 NAS에서 해당 키를 인식하지 못할 수 있습니다. 관련 내용을 잘 확인해보세요!!
  • 최종적으로 아래처럼 성공이 돼야합니다.
    GithubActionConsole.png
NAS에서 Docker 실행 확인
  • 위에서 정상적으로 동작했다면 NAS에서 해당 Docker Container가 실행되는지 확인합니다.
# 실행 중인 컨테이너 목록 확인
docker ps

DockerRunCheck.png

7. Port Open

  • 해당 서버의 포트를 열어주어야 외부에서 접속이 가능합니다.
  • 다음은 Synology NAS에서 포트를 열어주는 방법입니다.

CreateRouterRule.png

CreateRouterRule2.png

CreateRouterRule3.png

CreateRouterRule4.png


8. 서버 오픈 확인

  • 모든 작업을 완료하셨다면 지정한 포트로 정상 작동하는지 확인해주시면 되겠습니다.

ServerCheck.png



글을 마치며

오늘 소개해드린 Synology NAS와 Github Action을 이용한 CI/CD 구축 방법을 통해, 여러분도 자동화된 배포 과정을 경험해보실 수 있을 것입니다. 이 글이 도전적인 프로젝트에 직면하거나, 효율적인 개발 환경을 모색하는 분들께 도움이 되었기를 바랍니다.

실제로 구축 과정에는 여러 난관이 있었지만, 그만큼 성공했을 때의 성취감은 이루 말할 수 없었습니다. 이러한 경험을 통해 기술의 끝은 정말로 무궁무진하다는 것을 다시 한번 깨달았습니다.

앞으로도 개발과 관련된 다양한 지식과 경험을 공유할 예정이니, 관심 있으신 분들은 자주 방문해 주세요. 또한, 이 포스트를 통해 생긴 궁금증이나 추가적으로 알고 싶은 내용이 있다면 언제든지 댓글로 남겨주세요. 여러분의 피드백은 제가 더 나은 콘텐츠를 만드는 데 큰 도움이 됩니다.

이 글이 여러분의 프로젝트에 도움이 되길 바라며, 글을 마치겠습니다. 건승하세요! ^^