본문 바로가기

Docker

Docker CI/CD 진행하기

1. 개요

지금까지 docker의 동작 방식을 이해하고 프로젝트를 띄워 보았다. 이제 이를 이용하여 자동화시켜보자.

2. scripts

name: CICD Test
run-name: Running
on:
  push:
    branches:
      - master


jobs:
  build-with-gradle:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout master branch
      uses: actions/checkout@v3
          
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'corretto'
          
    - name: gradlew 실행 권한 부여
      run: chmod +x ./gradlew
        
    - name: 프로젝트 빌드(테스트 코드 제외)
      run: |
        ./gradlew clean build --exclude-task test --stacktrace

    # docker login -u username -p password
    - name: docker 로그인
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}


    - name: docker 이미지 빌드
      run: docker build -t ${{ secrets.DOCKER_USERNAME }}/gugumo-test .


    - name: docker push
      run: docker push ${{ secrets.DOCKER_USERNAME }}/gugumo-test:latest

    - name: Deploy to ec2
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST_TEST }} # EC2 퍼블릭 IPv4 DNS
        username: ubuntu
        key: ${{ secrets.PRIVATE_KEY }}
        port: 22

        script: |
          
          
          sudo touch .env
          echo "${{ secrets.ENV_VARS }}" | sudo tee .env > /dev/null
          
          sudo touch docker-compose.yml
            echo "${{ vars.DOCKER_COMPOSE }}" | sudo tee docker-compose.yml > /dev/null
          
          sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          sudo docker rm -f $(sudo docker ps -qa)
          sudo docker pull ${{ secrets.DOCKER_USERNAME }}/gugumo-test:latest
          docker compose -f docker-compose.yml --env-file ./.env up -d
          sudo docker image prune -f
        # 도커에서 사용하지 않는 리소스 삭제

 

잘라서 살펴보자.

2-1 project build

jobs:
  build-with-gradle:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout master branch
      uses: actions/checkout@v3
          
    - name: Set up JDK 17
      uses: actions/setup-java@v3
      with:
        java-version: '17'
        distribution: 'corretto'
          
    - name: gradlew 실행 권한 부여
      run: chmod +x ./gradlew
        
    - name: 프로젝트 빌드(테스트 코드 제외)
      run: |
        ./gradlew clean build --exclude-task test --stacktrace

여기까지는 code deploy를 사용했을 때와 동일하다. 자바 환경을 세팅하고, gradle 실행 권한을 부여한 뒤 프로젝트를 빌드하여 실행 파일을 생성한다.

2-2 Docker build image and push

    # docker login -u username -p password
    - name: docker 로그인
      uses: docker/login-action@v2
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}


    - name: docker 이미지 빌드
      run: docker build -t ${{ secrets.DOCKER_USERNAME }}/gugumo-test .


    - name: docker push
      run: docker push ${{ secrets.DOCKER_USERNAME }}/gugumo-test:latest

우선 도커에 사용하는 계정으로 로그인한 후, 앞서 만든 실행파일로 이미지를 빌드한 후, 도커 리포지토리에 push 한다.

2-3 pull and execute

    - name: Deploy to ec2
      uses: appleboy/ssh-action@master
      with:
        host: ${{ secrets.HOST_TEST }} # EC2 퍼블릭 IPv4 DNS
        username: ubuntu
        key: ${{ secrets.PRIVATE_KEY }}
        port: 22

        script: |
          
          
          sudo touch .env
          echo "${{ secrets.ENV_VARS }}" | sudo tee .env > /dev/null
          
          sudo touch docker-compose.yml
            echo "${{ vars.DOCKER_COMPOSE }}" | sudo tee docker-compose.yml > /dev/null
          
          sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          sudo docker rm -f $(sudo docker ps -qa)
          sudo docker pull ${{ secrets.DOCKER_USERNAME }}/gugumo-test:latest
          docker compose -f docker-compose.yml --env-file ./.env up -d
          sudo docker image prune -f
        # 도커에서 사용하지 않는 리소스 삭제

이제 스크립트에서 ec2에 직접 연결하여 아래 스크립트를 실행하게 될 것이다. host 주소에 key를 가지고 ssh 연결을 진행할 수 있다. 각 변수들은 깃허브 설정의 secrets and variables/actions에서 등록할 수 있다.

          
          sudo touch .env
          echo "${{ secrets.ENV_VARS }}" | sudo tee .env > /dev/null
          
          sudo touch docker-compose.yml
            echo "${{ vars.DOCKER_COMPOSE }}" | sudo tee docker-compose.yml > /dev/null

그대로 사용하면 위험하여 secrets에 저장한 환경변수를 .env 파일로 만들고, 마찬가지로 docker-compose 파일도 만들어준다.

Variables를 선택하여 new repository variable을 누르면 변수를 만들어 저장할 수 있다.

          sudo docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          sudo docker rm -f $(sudo docker ps -qa)
          sudo docker pull ${{ secrets.DOCKER_USERNAME }}/gugumo-test:latest
          docker compose -f docker-compose.yml --env-file ./.env up -d
          sudo docker image prune -f

이제 해당 ec2에 로그인, 리포지토리에서 이미지를 받고 docker compose 명령어를 사용하여 실행, image prune -f를 사용하여 사용하지 않는 이미지를 제거한다.

 

CI/CD에 성공한 것을 확인할 수 있었다.

 

 

3. 후기

CI/CD가 처음에는 어려웠지만 두 가지 방법(codedeploy, docker)을 사용하여 진행하면서 단순히 통합, 배포를 위해 사람이 직접 실행해야 하는 스크립트를 대신 실행해준다는 느낌을 강하게 받았다. 또, docker를 기초부터 다져 이 기술 스택에 대해 이해할 수 있었고 그럼에 CI/CD를 더 수월하게 진행할 수 있었던 것 같다.

 

그러나..

도커 이미지 자체는 실행할 수 있었지만 애플리케이션 실행 시 한 가지 문제가 발생했다. 이에 대해서는 다음 포스트에서 다뤄보도록 하겠다.

'Docker' 카테고리의 다른 글

Trouble Shooting: 배포 시 env 관리하기  (0) 2024.12.30
Docker-compose 사용하기  (1) 2024.12.11
Hello Docker! : 프로젝트 EC2에 배포해보기  (2) 2024.11.02