본문 바로가기

배포운영

[스프링] 도커(docker) + EC2 + github actions 배포

흐름도

전체 yml 파일

# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle

# Repo Action 페이지에 나타날 이름 
name: Spring Boot & Gradle CI/CD 

# Event Trigger 
# dev branch에 push 또는 pull request가 발생할 경우 동작
# branch 단위 외에도, tag나 cron 식 등을 사용할 수 있음 
on:
  push:
    branches: [ develop ]
  pull_request:
    branches: [ develop ]

jobs:
  build:

    # 실행 환경 지정
    runs-on: ubuntu-latest

    # Task의 sequence를 명시한다.
    # 브랜치를와 마찬가지로 checkout을 한다.
    # 누군가 만들어 놓은 Actions를 사용하기 위해 uses 키워드 사용
    steps:
    - uses: actions/checkout@v3

    # push 할때마다 다시 gradle을 install하지 않기 위한 설정
    # 해당 프로젝트의 gradle값이 변경됐을 경우에만 install
    - name: Cache Gradle packages
      uses: actions/cache@v3
      with:
        path: |
          ~/.gradle/caches
          ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
        restore-keys: |
          ${{ runner.os }}-gradle-

    # CI 시작
    - name: Set up JDK 17
      uses: actions/setup-java@v3

      # with로 Actions에 값 전달
      with:
        java-version: 17
        distribution: 'temurin'

    ## create application.properties
    - name: make application.properties
      if: contains(github.ref, 'develop') # branch가 develop 때
      run: |

        # spring의 resources 경로로 이동
        cd ./src/main/resources 

        # application.properties 파일 생성
        touch ./application.properties 

        # GitHub-Actions에서 설정한 값을 application.properties 파일에 쓰기
        echo "${{ secrets.PROPERTIES_DEV }}" >> ./application.properties 
      shell: bash

       ## gradle build
    - name: Build with Gradle
      run: 
        chmod +x ./gradlew

        ./gradlew build

      # Spring 어플리케이션 Docker Image 빌드
      # CD 시작
    - name: Docker build
      if: contains(github.ref, 'develop')
      run: |          
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build --build-arg DEPENDENCY=build/dependency -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }} .
          docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}


      # 서버에서 Docker 이미지 실행
      # HOST_DEV = 퍼블릭 IPv4 DNS , USERNAME = ubuntu, KEY = pem 키 전체( 만약 안될시 ubuntu에서 password 생성)
    - name: EC2 Docker Run
      uses: appleboy/ssh-action@master
      if: contains(github.ref, 'develop')
      with:
        host: ${{ secrets.HOST_DEV }}
        username: ${{ secrets.USERNAME }}
        password: ${{ secrets.KEY }}
        port: 22
        script: |
          sudo docker stop $(docker ps -a -q) 
          sudo docker rm $(docker ps -a -q)
          sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}
          sudo docker run -d -p 80:8080 ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}

 

 

# Repo Action 페이지에 나타날 이름 
name: Spring Boot & Gradle CI/CD 

# Event Trigger 
# dev branch에 push 또는 pull request가 발생할 경우 동작
# branch 단위 외에도, tag나 cron 식 등을 사용할 수 있음 
on:
  push:
    branches: [ ci-cd-test ]
  pull_request:
    branches: [ ci-cd-test ]

jobs:
  build:

    # 실행 환경 지정
    runs-on: ubuntu-latest

    # Task의 sequence를 명시한다.
    # 브랜치를와 마찬가지로 checkout을 한다.
    # 누군가 만들어 놓은 Actions를 사용하기 위해 uses 키워드 사용
    steps:
    - uses: actions/checkout@v3

ci-cd-test라는 브랜치에 push나 pull_request가 발생하면 workflow를 실행합니다.

# push 할때마다 다시 gradle을 install하지 않기 위한 설정
    # 해당 프로젝트의 gradle값이 변경됐을 경우에만 install
    - name: Cache Gradle packages
      uses: actions/cache@v3
      with:
        path: |
          ~/.gradle/caches
          ~/.gradle/wrapper
        key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
        restore-keys: |
          ${{ runner.os }}-gradle-

공부 필요.

## create application.properties
    - name: make application.properties
      if: contains(github.ref, 'develop') # branch가 develop 때
      run: |

        # spring의 resources 경로로 이동
        cd ./src/main/resources 

        # application.properties 파일 생성
        touch ./application.properties 

        # GitHub-Actions에서 설정한 값을 application.properties 파일에 쓰기
        echo "${{ secrets.PROPERTIES_DEV }}" >> ./application.properties 
      shell: bash

깃허브 파일에 resources란 경로가 존재하지 않으면 에러가 발생하니 resources 파일을 미리 만들어 두어야 합니다.

PROPERTIES_DEV에는 gitIgnore 처리 되어 있는 application.properties 내용들이 들어가 있습니다.

## gradle build
    - name: Build with Gradle
      run: 
        chmod +x ./gradlew

        ./gradlew build

gradlew는 권한 설정이 기본으로 644로 설정되어 있기때문에 실행까지 가능한 775 권한으로 설정을 해주었습니다.

예를들어 755는 rwxr-xr-x 로 소유자는 모든 권한이 있고 그룹 소유자 및 일반 사용자는 읽기와 실행 권한만 있습니다. 644는 rw-r—r—로 소유자는 읽고쓰기, 그룹과 일반사용자는 읽기만 가능인 권한입니다. chmod 명령어 사용법은 아래에 조그맣게 기술해 놓겠습니다.

# Spring 어플리케이션 Docker Image 빌드
    - name: Docker build & push to ci-cd-test
      if: contains(github.ref, 'ci-cd-test')
      run: |          
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build --build-arg DEPENDENCY=build/dependency -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }} .
          docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}

DOCKER_USERNAME 은 가입한 도커허브의 아이디를, DOCKER_USERNAME 는 도커허브의 비밀번호를, DOCKER_REPO 는 도커 허브의 repository의 이름을 깃허브 해당 Repo에서 settings - Secrets and variables - Actions -New repository secret으로 생성하면 됩니다.

위 명령어는 차례대로 도커에 로그인을 하고 도커 이미지를 만든 후 도커허브 레포에 저장하는 명령어입니다.

# 서버에서 Docker 이미지 실행
      # HOST_DEV = 퍼블릭 IPv4 DNS , USERNAME = ubuntu, KEY = pem 키 전체( 만약 안될시 ubuntu에서 password 생성)
    - name: EC2 Docker Run
      uses: appleboy/ssh-action@master
      if: contains(github.ref, 'ci-cd-test')
      with:
        host: ${{ secrets.HOST_DEV }}
        username: ${{ secrets.USERNAME }}
        password: ${{ secrets.KEY }}
        port: 22
        script: |
          sudo docker stop $(docker ps -a -q) 
          sudo docker rm $(docker ps -a -q)
          sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}
          sudo docker run -d -p 80:8080 ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}
  • sudo docker stop 컨테이너 ID : 해당 컨테이너 중지
  • docker rm 컨테이너 ID : 해당 컨테이너를 삭제
  • docker ps -qa : 실행중인 모든 컨테이너 ID 출력
  • docker pull : 해당 도커 레포에 있는 이미지 파일 pull
  • docker run -d -p : 백그라운드 배포

파일 권한 변경 방법

터미널에서 ls -al (list segments, a : ‘.’으로 시작하는 파일이름을 포함해 디렉토리내의 모든 파일을 표시, l : 파일 권한과 파일 용량을 표시하는 포맷)명령어를 사용하면 아래와 같이 파일 권한 정보와 파일이 출력됩니다.

여기서 ..파일을 보면 d = 파일 타입(d = 디렉토리 , - = 파일, l = 파일 링크)

rwx = 소유자 권한을 보여주며, r-x는 그룹권한을, r-x는 그외 유저 권한을 의미합니다.

(각각 읽기와 쓰기 실행을 의미합니다.)

5는 링크 갯수를, 앞의 ubuntu는 소유자, 뒤의 ubuntu는 소유 그룹, 4096은 파일크기, 그뒤는 파일 생성 날짜, 그 뒤는 파일명을 의미합니다.

현재 644인 파일의 권한을 777로 변경하는 예제 (rw-r—r—)

chmod 777 index.html —> index 파일의 권한을 755로 설정

chmod u+x, g+wx, o+wx index.html (u : 소유자, g : 그룹, : o : 그외, a : u+g+o)

( + : 권한 추가, - : 권한 삭제, = 기입한 권한대로 설정)

chmod +x 파일명은 파일의 u와g와o에게 x권한을 추가한다는 뜻입니다.