-
Github Actions를 이용한 CI / CD 구현하기GIT 2022. 11. 27. 15:01
이전에 Jenkins를 이용하여 CI / CD를 구현한 적이 있는데,
이 부분을 Github Action을 이용하면 매우 간단하게 진행된다고 하여 aws ec2환경에서 구현해보았다.
Github Action 테스트
먼저 테스트용 Github Action 파일을 작성하여 실행이 되는지 확인하였다. 확인 과정에서는 Ktlint를 이용하여 문법을 체크하도록 설정한다. 프로젝트에 ktlint plugin을 추가해준다.
↓
https://seosh817.tistory.com/154
plugins { id("org.jlleitschuh.gradle.ktlint") version "11.0.0" }
github action파일을 만들어준다.
# This is a basic workflow to help you get started with Actions name: Workflow # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the "main" branch push: branches: [ "main" ] pull_request: branches: [ "main" ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: testing: name: Lint Check and Testing runs-on: ubuntu-latest steps: - name: Clone Repo uses: actions/checkout@v1 - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: '11' - name: Run Kotlin Linter run: ./gradlew ktlintCheck
수정한 코드를 main 브랜치에 push하면 action이 실행된다.
만약 여기서 build.gradle.kts에서 tab 오류가 발생한다면 tab -> 스페이스 4번으로 교체해준다.
↓
CI
이제 프로젝트를 CI 를 구현해보자. CI에서는 프로젝트 commit -> Github Action에서 빌드 -> 빌드된 jar 파일을 docker hub에 이미지 올리기 의 과정을 수행한다.
먼저도커 hub에 가입한다.
여기서 이미지 빌드를 위해서 가입할 때 사용되었던 Docker username(닉네임이나 이메일)과 비밀번호를 github action에 등록해준다.github action은 여기에 저장된 secret값을 이용해서 action을 실행한다.
그다음 build.gradle.kts에 다음과 같이 설정해주는데, 이 부분은 기본적으로 Jar 파일이 실행 가능한 Jar, 비어있는 Jar 2개가 생성되는 것을 방지하고 실행 가능한 Jar만을 생성하도록 설정한다.
↓
https://blog.leocat.kr/notes/2020/01/23/gradle-create-executable-jar-with-spring-boot
tasks.jar { enabled = false } tasks.bootJar { enabled = true }
Docker 이미지 생성 설정을 위해 프로젝트에 다음과 같이 Dockerfile을 만들어준다. 이 Dockerfile의 설정은 생성된 jar 파일을 app.jar로 복사한다.
FROM openjdk:11.0.10-jre-slim-buster ARG JAR_FILE=build/libs/*.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"]
이제 action을 이용해서 이미지를 빌드해보자.
↓
https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action
ktlint로 체크해서 오류가 없는지 검사 후 Docker 이미지를 빌드한다.
# This is a basic workflow to help you get started with Actions name: Workflow # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the "main" branch push: branches: [ "main" ] pull_request: branches: [ "main" ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: '11' distribution: 'adopt' - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Run Kotlin Linter run: ./gradlew ktlintCheck - name: Build with Gradle run: ./gradlew build - name: Docker build run: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} docker build -t spring-cicd . docker tag spring-cicd ${{ secrets.DOCKER_USERNAME }}/spring-cicd:${GITHUB_SHA::7} docker push ${{ secrets.DOCKER_USERNAME }}/spring-cicd:${GITHUB_SHA::7}
main 브랜치에 push 해주면 다음과 같이 잘 실행된다.
도커 Remote repository에서 확인하면 이미지가 잘 들어온 것을 확인할 수 있다.
CD
이제 올라온 이미지를 가지고 ec2에 자동적으로 배포가 이루어지도록 해보자. 먼저 ec2 생성하고 보안규칙은 22 포트와 80(docker 접속)포트를 열어준다.
$ ssh -i [pem키].pem ubuntu@[ec2 public IP] ## 먼저 도커를 설치해준다. $ sudo apt-get update && \ sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \ sudo apt-key fingerprint 0EBFCD88 && \ sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \ sudo apt-get update && \ sudo apt-get install -y docker-ce && \ sudo usermod -aG docker [설정할 사용자 이름] && \ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \ sudo chmod +x /usr/local/bin/docker-compose && \ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose ## 설치된 도커 버전 확인 $ docker --version Docker version 20.10.21, build baeda1f
이제 ssh 키를 이용해서 github action이 ec2 서버에 접근해서 배포를 할 수 있도록 설정해주자. ec2 서버에서 먼저 ssh 키를 생성해준다.
$ ssh-keygen -t rsa -b 4096 -C [사용자이메일] -f [키 이름(여기서는 spring-cicd)] SHA256:Btg5wteZJaErAtLqlFiUqmbKimJ16+71ufU5Mo/vyPY The key's randomart image is: +---[RSA 4096]----+ | .. o.. | | o.. o + = | |o.o + B + | |++. o + | |+o. . . S | |+o o o . | |=.. . .. . | |+o .. . +++.. | |* ++ +o+BE. | +----[SHA256]-----+ ## 키 생성 확인 $ ls spring-cicd spring-cicd.pub
생성된 공개키를 authorized_keys에 추가해준다. ( ssh 키로 접속이 가능하도록)
$ cat spring-cicd.pub //나오는 내용 복사 ## authorized_keys에 위의 복사 $ cd ~/.ssh $ vi authorized_keys
이제 개인키는 github action secrets에 등록해주자.
$ cat spring-cicd // 복사할 private key
도커와 같이 secrets에 private 키를 등록해준다.
이제 모든 설정이 완료되었으니 github action에 다음과 같이 CD 부분을 추가해준다.
↓
https://github.com/marketplace/actions/docker-metadata-action
# This is a basic workflow to help you get started with Actions name: Workflow # Controls when the workflow will run on: # Triggers the workflow on push or pull request events but only for the "main" branch push: branches: [ "main" ] pull_request: branches: [ "main" ] # Allows you to run this workflow manually from the Actions tab workflow_dispatch: # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: '11' distribution: 'adopt' - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Run Kotlin Linter run: ./gradlew ktlintCheck - name: Build with Gradle run: ./gradlew build - name: Docker build run: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} docker build -t spring-cicd . docker tag spring-cicd ${{ secrets.DOCKER_USERNAME }}/spring-cicd:${GITHUB_SHA::7} docker push ${{ secrets.DOCKER_USERNAME }}/spring-cicd:${GITHUB_SHA::7} - name: Deploy uses: appleboy/ssh-action@master with: host: [ec2~로 시작하는 ec2 서버명] username: [위에서 설정한 docker 사용자 이름] key: ${{ secrets.SSH_PRIVATE_KEY }} envs: GITHUB_SHA script: | docker pull ${{ secrets.DOCKER_USERNAME }}/spring-cicd:${GITHUB_SHA::7} docker tag ${{ secrets.DOCKER_USERNAME }}/spring-cicd:${GITHUB_SHA::7} spring-cicd docker stop server // 미리 올라가있는 서버가 존재하면 일단 내리고 docker run -d --rm --name server -p 80:8080 spring-cicd // 다시 실행
빌드 및 배포가 잘 성공한다.
ec2 서버에서 확인해보자. 컨테이너가 잘 실행되는 것을 확인할 수 있다.
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES fe4a81a25afb spring-cicd "java -jar /app.jar" 3 minutes ago Up 3 minutes 0.0.0.0:80->8080/tcp, :::80->8080/tcp server
여기서 권한 오류가 발생한다면 다음과 같이 해준다.
$ docker ps -a Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/containers/json?all=1": dial unix /var/run/docker.sock: connect: permission denied $ sudo usermod -aG docker [위에서 생성한 사용자 이름] $ newgrp docker
로그를 확인해보면 잘 실행되는 것을 확인할 수 있다.
http://[ec2 public IP]:80으로 접속해도 잘 되는 것을 확인할 수 있다. 완성 ! ✨
(참고한 사이트)
https://seulcode.tistory.com/557
https://umanking.github.io/2021/07/11/spring-boot-docker-starter/
https://itcoin.tistory.com/685
https://goodgid.github.io/Github-Action-CI-CD-Workflows/👍
'GIT' 카테고리의 다른 글
github으로 maven repo 만들기 (5) 2024.10.09 맥에서 Git Error permission denied to <Unknown User> 문제 발생시 (0) 2022.11.15 Github Actions (0) 2022.11.03 git 기능 구현을 다른 브랜치에서 작성했을 때 (0) 2022.01.25 Git Commit Convention (0) 2021.12.14