[Infra] GitHub Actions + DockerHub + AWS EC2 로 프로젝트 CI/CD 구축
여러 프로젝트를 만들면서 배포를 할 때 '젠킨스 + Gitlab' 또는 'Gitlab'으로 CI/CD를 구축하여 배포하였다.
이건 프로젝트가 gitlab 저장소로 관리되어있어야 하는데 초반에 만들어둔 프로젝트는 github 저장소에 있다보니 기존 방법 대로 CI/CD를 하려면 gitlab으로 프로젝트를 옮기는 과정이 필요했다.
gitlab 👉 github 미러링은 해봤는데 github 👉 gitlab 미러링은 처음...
방법은 비슷하겠거니하고 찾아봤는데 "pull mirroring"을 하면된다고한다.(참고로 깃랩에서 깃헙은 push mirroring)
gitlab 미러링으로 들어가 pull로 변경하려고 보니
변경해야하는 Mirror direction이 비활성화되어 클릭이 안되는것...
찾아보니 github actions 쉘스크립트로 gitlab에 미러링(?) 되게 할 수 있으나,
위의 내용을 보면 무료버전에서는 지원이 안되는것 같다.
github actions를 이용해야한다면 미러링이아닌 CI/CD를 구축해야겠다고 판단!
해당 내용을 기억하기 위해 포스팅한다.
🛠 필요한 환경
- Docker Hub
- AWS EC2 (Ubuntu)
- 프로젝트가 저장되어있는 Github 레포지토리
1. CI Workflow 생성
github repository(배포할 프로젝트가 커밋되어있는) > Actions
Java + gradle로 빌드할 것이기 때문에 해당 Configure 클릭
아래와 같은 화면이 나오는데 gradle.yml < 이부분은 원하는 title로 변경할 수 있음
.yml 파일은 자신의 환경과 맞춰서 커스텀해줘야함
완료되면 start commit 클릭
2. .yml 파일 작성
# github repository actions 페이지에 나타낼 이름
name: Java CI with Gradle
# event trigger - 이벤트가 정의되는 부분
# 'main' branch로 push 또는 pull request가 일어나 경우 해당 workflow가 실행된다.
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# workflow는 여러개의 job으로 구성되고 job는 또 여러개의 steps로 이루어진다.
jobs:
build:
# 어떤 OS 환경에서 실행되는지
runs-on: ubuntu-latest
# JDK 설정
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
# 자바버전은 11
java-version: '11'
# 이전에는 'adopt'를 사용했는데 현재는 temurin을 사용하기를 권장하고 있음
distribution: 'temurin'
# Gradle build
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: run build
# test는 건너뛰고 build
run: ./gradlew clean build -x test
gradle build 부분에서 아래 세 가지 경우를 확인하여 원하는 걸로 변경해주면된다.
난 test 수정이 좀 필요해서 test는 건너뛰고 빌드로 선택했다.
# build + test
- name: Build with Gradle
run: ./gradlew build
# test에서 에러나는지 확인
- name: run test
run: ./gradlew test
# test는 건너뛰고 build -> build에서 에러나는지 확인
- name: run build
run: ./gradlew clean build -x test
✅ 에러
처음에 jdk 설정 부분 checkout@3 을 checkout@2로 해서 입력했는데
Node.js 12 actions are deprecated. Please update the following actions to use Node.js 16: actions/checkout@v2, actions/setup-java@v2. For more information see: https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/.
위와 같은 에러가 났다.
찾아보니 더이상 v2를 사용하지 않기 때문에 위의 버전을 사용하라는 뜻
v2 > v3 로 변경하니 해결되었다.
3. Docker Hub 가입
docker hub에 내 프로젝트를 빌드하고 빌드한 도커 이미지를 저장해서 사용할 수 있도록 한다.
4. Github Acitons Docker 이미지 push 하기
github repository > Settings > Secrets and variables > Actions > New repository secret
secret 값을 입력해준다.
- DOCKERHUB_USERNAME : Docker Hub에 등록된 유저 이름을 등록한다.
- DOCKERHUB_TOKEN : Docker Hub에서 발행한 token 값을 등록한다.
value 값은 한번 넣으면 그 뒤로 볼 수 없기 때문에 저장 관리를 잘해두면 좋다.
5. Docker 관련 step 추가 .yml 파일 수정
- docker login step
- yml 파일 > 도커 이미지 빌드 > docker hub push step
위 두가지 step 을 추가한다.
name: Java CI with Gradle
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: run build
run: ./gradlew clean build -x test
# docker login 설정
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{secrets.DOCKERHUB_USERNAME}}
password: ${{secrets.DOCKERHUB_TOKEN}}
# docker 이미지 빌드 + docker hub push
- name: build and release to DockerHub
env:
NAME: [계정명]
REPO: [docker hub에 만들어둔 레포이름]
run: |
docker build -t $REPO .
docker tag $REPO:latest $NAME/$REPO:latest
docker push $NAME/$REPO:latest
docker hub 에 github 프로젝트 레포와 동일한 이름의 레포를 만들어두었다.
해당 레포로 빌드된 이미지를 push하고 추후 EC2로 이미지를 pull 받아올 수 있게 관리할 수 있다.
빌드하면 위와 같이 docker hub에 이미지가 생성되는걸 확인 할 수 있다.
6. Dockerfile 작성
5번으로 docker 빌드 이미지를 만들려면 아래의 Dockerfile이 프로젝트 안에 있어야한다.
나는 8080 포트를 사용중이기 때문에 8081로 실행했다.
***-0.0.1-SNAPSHOT.jar < 이 .jar 파일은 프로젝트에서 build 하면 build > libs 에 저장된다.
해당 파일명을 확인해서 변경해준다.
# APP
FROM openjdk:11-jdk
#컨테이너 안에 .jar 파일을 app.jar 파일로 복사
COPY build/libs/***-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8081
# root 대신 nobody 권한으로 실행
USER nobody
ENTRYPOINT ["java", "-jar", "app.jar"]
7. .yml 에 deploy 관련 내용 추가하기
github aciton의 yml 파일에 deploy 관련 내용을 추가하여 내 프로젝트를 컨테이너 서버에 올린다.
name: Java CI with Gradle
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: run build
run: ./gradlew clean build -x test
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{secrets.DOCKERHUB_USERNAME}}
password: ${{secrets.DOCKERHUB_TOKEN}}
- name: build and release to DockerHub
env:
NAME: [계정명]
REPO: [docker hub에 만들어둔 레포이름]
run: |
docker build -t $REPO .
docker tag $REPO:latest $NAME/$REPO:latest
docker push $NAME/$REPO:latest
# 배포 스크립트 작성
deploy:
needs: build
name: Deploy
runs-on: [ self-hosted, label-development ]
steps:
- name: Docker run
run: |
# 컨테이너명으로 된 컨테이너가 올라와있으면 stop > rm > rmi 명령어를 사용하여 컨테이너와 이미지를 삭제한다.
docker ps -q --filter "name=[컨테이너명]" | grep -q . && docker stop "[컨테이너명]" && docker rm "[컨테이너명]" && docker rmi "[docker hub에 올라와있는 도커 이미지명]"
# 새로운 버전의 이미지를 컨테이너에 올린다.
docker run -d --name [컨테이너명] [필요한 환경변수가 있으면 -e를 사용하여 넣어준다(ex)db서버 등] -p 8080:8080 [docker hub에 올라와있는 도커 이미지명]
8. runners 설정
Settings > Actions > Runners > New self-hosted runner
Download / Configure 에 적힌 명령어를 차례대로 EC2에 입력해서 실행한다.
Configure의 첫 번재 코드까지 입력하면 아래 두가지를 입력해야하는 상황이 발생
1번은 복수개의 runner를 등록하게 될 때 github 상에서 구분할 수 있는 runner의 이름을 지정
2번은 실행되는 runner를 구분하기 위한 것으로 yml 파일의 deploy에서 runs-on에 설정해주었던 label-development를 입력
1,2번으로 설정한 이름들은 Settings > Actions에서 확인 할 수 있다.
여기서 중요! ./run.sh 로 실행하면 실행 후 다른 명령어를 입력할 수 없다.
nohup ./run.sh &
위 nohup 명령어를 사용하여 백그라운드로 runner를 실행시킨다.
이렇게 나오는데 해당 프로세스 아이디 이름으로 돌아가고 있다는 것을 뜻한다.
확인해보고 싶다면, 위 명령어를 입력한 위치에 nohub.out 이라는 파일이 생겼을 텐데
cat nohup.out
위의 명령어를 입력하여 보면 돌아가는 내용을 확인 할 수 있다.
📚 참고블로그
https://insight-bgh.tistory.com/474
https://zzang9ha.tistory.com/404