본문 바로가기
개발/트러블슈팅

[Docker] NCP 환경에서 Github Actions을 활용한 CI/CD 구축하기

by char_lie 2024. 11. 26.
반응형

🫗 Docker

- 컨테이너 기술을 사용하여 애플리케이션의 실행, 배포, 관리 등을 할 수 있게 해주는 오픈 소스 플랫폼

- 애플리케이션에 필요한 구성 요소를 독립적 환경에서 실행할 수 있게 도와줌

- 이식성, 빠른 시작, 자원 효율성 등의 장점이 있음.

 

도커? 그거 VM이랑 뭐가 다른데?

 

⚒️ 적용 순서

우선 도커 공식 사이트 에서 도커 계정을 생성하고 설치한다.

도커 계정을 만들었다면 계정 관리 항목에 들어가서 Personal access tokens를 생성한다. 추후에 도커를 활용한 배포에 꼭 필요하니 발급 받아두자.

이때, 발급받을 때 Optional을 선택해주고, 키를 발급 받아서 저장하여 사용하도록 한다. 한번 발급 이후 페이지를 나가면 다시 볼 수 없으니, 따로 적어서 저장하여 갖고 있어야한다.

여기까지 했다면, 기본적인 Docker 사용 세팅은 완료되었고, 배포를 위한 서버 (여기서는 NCP) 에서 도커를 설치하고, 사용할 포트를 개방해줘야 한다.

 

NCP 환경에서의 세팅

sudo apt update
sudo apt install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker

해당 명령어 들을 순서대로 입력하면 도커 설치가 완료되고, 실행할 수 있다. 여기까지가 기본 세팅이고, 이후에 배포 시에 ufw 명령어로 방화벽을 열어주어야 한다.

sudo ufw enable
sudo ufw allow 포트번호

본인이 사용할 포트번호를 열어, 이후 배포 시에도 정상 동작하는지 체크하면 된다.

 

📍 Dockerfile 구성하기

이제 기본 환경 세팅을 완료했다면, 도커 파일 이미지를 빌드 하기 위한 스크립트를 구성해야한다. 배포를 위해서 Dockerfile을 생성함으로써 일관성있게 이미지 생성을 자동화 할 수 있다. 보통은 아래와 같은 형태의 구조를 갖는다.

# 1. 베이스 이미지 설정
FROM node:18

# 2. 작업 디렉토리 설정
WORKDIR /app

# 3. 종속성 설치
COPY package.json .
RUN npm install

# 4. 소스 코드 복사
COPY . .

# 5. 포트 노출
EXPOSE 3000

# 6. 컨테이너 실행 명령어
CMD ["npm", "start"]

 

반응형

📌 CI / CD

CI (지속적인 통합)

- 개발 팀이 코드를 지속적으로 통합하고, 자동으로 테스트하여 통합 버그를 최소화하는 프로세스

- 코드 변경 사항이 발생할 때마다 자동으로 빌드 및 테스트 실행

- 이를 통해 프로덕트의 품질 관리 가능

 

CI (지속적인 배포)

- 코드 변경 사항을 테스트 및 승인을 거쳐 프로덕션 환경에서 배포하는 프로세스

- 실제 사용자에게 새로운 기능과 수정 사항을 빠르게 제공

- 사용자 피드백을 수집하고 이를 활용하여 속도 개선 가능

 

🚀 우리팀에 CI / CD를 구축할 필요한 이유가 무엇일까?

github의 Issue 기능을 사용하지만..

분명 깃허브의 이슈와 백로그 등을 활용하여 API를 구성하고 소통하는 방식은 꽤 도움이 되는 방식이라고 생각한다. 그러나, 실제 개발 기능 구현 단계에서는 기존에 지정된 DTO 형태가 바뀌거나 오타 등의 이슈로 개발이 지연되거나 문제가 발생할 수 있다고 생각했다. 그렇기에 이런 상황을 최소화하기 위해 스웨거를 적극 채용하여 활용할 수 있게 만들고자 하였고, api가 개발될 떄마다 스웨거를 갱신하고 배포함으로써 프론트가 어떤 api가 완성되었고 사용할 수 있는지, 데이터 타입은 어떻게 되는지를 명확하게 보여줄 수 있다고 생각하여 자동화 할 필요가 있다고 생각했다.

 

수동 배포의 비효율성

자동화 프로세스를 통해 수동 작업을 줄일 수 있기에 불필요한 시간 낭비를 많이 줄일 수 있다고 생각했고, github actions라는 강력한 툴을 사용함으로써 개발 업무 효율의 상승이 기대되었다.

 

⚒️ github actions 그거 어떻게 쓰는건데?

공식 문서에 설명이 잘 되어있꼬, 기본적인 프로젝트에 대한 CI/CD 템플릿을 어느정도 제공하고 있는 상태고, 이를 활용하면 어느 정도 편하게 구축할 수 있다.

다만, 나는 워크플로우를 직접 구성하여 NCP 서버와 연동하는 과정을 통해 CI/CD를 구축할 수 있었다.

이를 위해 Github actions 파이프라인을 만들기 위한 순서로 적용할 수 있다.

 

🚫 Github Secrets

배포에 앞서 노출되면 안되는 중요한 Key 데이터 들을 Github에 등록해서 사용해 주어야한다. 해당 키들은 외부로 유출이 일어날 경우 악용될 수 있고, AWS나 NCP 같은 클라우드의 key가 노출될 경우 고액의 비용이 청구 될 수 있기에 절대 외부적으로 드러나지 않도록 Secret을 통해 관리해야한다.

여기에 사전에 받은 서버 key와 도커의 엑세스 토큰 등을 등록해주자.

파이프라인을 구축할 때, Secret 데이터 들은 {{ secrets.등록한비밀키 }}의 형태로 읽어서 사용할 수 있다.

 

🔗 .github/workflows/deploy.yml

 .github
 ├── workflows
 │   └── deploy.yml
 │
...

yaml 문법을 통해 파이프라인을 구축할 수 있다. 여기서 나는 편의상 파일 이름을 deploy.yml로 지었고, 파일명은 본인이 원하는 이름으로 지으면 된다.

해당 파일이 .github의 workflows 디렉토리 내부에 존재하는지 확인하고, 이를 통해 파이프라인을 구축할 수 있다.

이후 파일 구성에 따른 파이프라인 동작은 Actions에서 확인해볼 수 있다.

 

✨ 실제 파일 구성하기

name: CI/CD 파이프라인

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main 

jobs:
  build:
    runs-on: ubuntu-latest 

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: 18 
          cache: 'npm'

      - name: Install dependencies
        run: npm install

      - name: Run tests
        run: npm test

      - name: Build project
        run: npm run build

  docker:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v4
        with:
          context: . 
          push: true
          tags: ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest

  deploy:
    runs-on: ubuntu-latest
    needs: docker

    steps:
      - name: Deploy to server
        uses: appleboy/ssh-action@v0.1.6
        with:
          host: ${{ secrets.SERVER_IP }}
          username: ${{ secrets.SERVER_USER }} 
          password: ${{ secrets.SERVER_PASSWORD }}
          script: |
            echo "Pulling latest Docker image..."
            docker pull ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest

            echo "Stopping old container..."
            docker stop my-app || true
            docker rm my-app || true

            echo "Starting new container..."
            docker run -d --name my-app -p 80:3000 ${{ secrets.DOCKER_HUB_USERNAME }}/my-app:latest

 

1. on

- 파이프라인 실행 조건을 정의하는 부분

- push는 특정 브랜치에 코드가 푸시 될 경우 실행

- pull_request는 PR 생성 시 실행

 

2. jobs

- 파이프 라인의 각 작업을 정의하는 부분

- 위 예시는 build, docker, deploy 3부분으로 작업

 

3. steps

- 각 작업 단계의 실행할 세부 명령어를 정의하는 부분

- docker에 이미지를 빌드하거나 docker hub에 푸시하는 등의 작업

 

 

반응형

'개발 > 트러블슈팅' 카테고리의 다른 글

[Docker] 도커 이미지 크기 줄이기  (0) 2024.11.26

댓글