GithubActions + Docker + EC2 로 CI/CD

wangjh789·2022년 9월 17일
1

발표 주제


💡 Docker 와 Github Actions 를 이용한 CI/CD

발표 내용


CI/CD 란?

지속적 통합(Continuous integration, CI)과 지속적 제공(Continuous delivery, CD), 줄여서 CI/CD는 애플리케이션 개발팀이 더 자주, 안정적으로 코드 변경을 제공하기 위해 사용하는 문화와 운영 원칙, 일련의 작업 방식

CI/CD는 데브옵스을 위한 권장 사항이자 애자일 방법론의 권장 사항이기도 하다. CI/CD는 통합과 제공을 자동화함으로써 소프트웨어 개발팀이 코드 품질과 소프트웨어 보안을 보장하는 동시에 비즈니스 요구사항을 충족하는 데 집중할 수 있게 해준다.

CI : 빌드/테스트 자동화 과정
CD : 배포 자동화 과정

1. 개발자들이 개발하여 feature브랜치에 코드를 push합니다.
2. git push를 통해 Trigger되어 **CI서버**에서 알아서 Build, Test, Lint를 실행하고 결과를 전송합니다.
3. 개발자들은 결과를 전송받고 에러가 난 부분이 있다면 에러부분을 수정하고 코드를 master 브랜치에 merge합니다.
4. master 브랜치에 코드를 merge하고 Build, Test가 정상적으로 수행이 되었다면 **CI서버**에서 알아서 Deploy 과정을 수행합니다.

Github Actions

// action의 이름(별칭)
**name**: CI/CD

// action 트리거
**on**:
  push:
    branches: [ "prod" ]

// action이 가진 repo에 대한 권한
**permissions**:
  contents: read

// 해야하는 작업들을 명시 (CI-CD : current-time)
**jobs**:
  CI-CD:
	
		// [runner](https://github.com/actions/runner) 의 가상머신 환경 
    runs-on: ubuntu-latest

		// CI-CD 작업 순서
    steps:

		// action marketplace (오픈소스) 사용
    - **uses**: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
			
			// 옵션
      **with**:
        java-version: '11'
        distribution: 'temurin'

		- name: Build with Gradle
      run: ./gradlew clean bootJar
  
    - name: Docker build & push to prod

			// 수행할 스크립트 명시
      **run**: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }} .
          docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}
    
    - name: Deploy to prod
      uses: appleboy/ssh-action@master
      id: deploy-prod
      with:
          host: ${{ secrets.EC2_HOST }}
          username: ec2-user
          key: ${{ secrets.EC2_PRIVATE_KEY }}
          envs: GITHUB_SHA
          script: |
              sudo docker rm -f $(docker ps -qa)
              sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPO }}
              docker-compose up -d
              docker image prune -f
        
  current-time:
		// 동기적으로 실행하기 위해 순서 지정
    **needs**: CI-CD
    runs-on: ubuntu-latest
    steps:
      - name: Get Current Time
        uses: 1466587594/get-current-time@v2
        id: current-time
        with:
          format: YYYY-MM-DDTHH:mm:ss
          utcOffset: "+09:00" # 기준이 UTC이기 때문에 한국시간인 KST를 맞추기 위해 +9시간 추가

      - name: Print Current Time
        run: echo "Current Time=${{steps.current-time.outputs.formattedTime}}" # current-time 에서 지정한 포맷대로 현재 시간 출력
        shell: bash

Dockerfile

도커 이미지는 호스트와는 독립된 자체 디렉토리를 가지기 때문에 필요한 의존성을 모두 끌어와야 한다.
도커 컨테이너는 호스트와 독립된 덕분에 호스트에 설치된 python, java, node 버전과 독립적인 환경에서 개발이 가능하다.

// 도커허브에서 공개된 자바 11버전 jdk 이미지를 가져오기
// 스프링에서 gradle로 의존성 끌어오는 것
FROM [openjdk:11-jdk-slim](https://hub.docker.com/_/openjdk)

// 8080번 포트를 열어야한다는 명시
EXPOSE 8080

// images 폴더를 만든다.
RUN mkdir "images"

// 이미지 빌드 할 때 커스텀하기 위해
ARG BUILD_DIR=/build

// 컨테이너가 stop 하면 컨테이너 내의 모든 데이터가 유실되기 때문에 docker platform에 저장하기 위함
// 컨테이너가 다시 run 할때 docker platform에 있는 볼륨과 /var/log 가 싱크를 이룸
VOLUME ["/var/log"]

// 로컬의 /build 디렉토리를 도커 이미지의 /build 로 복사하겠다.
COPY ${BUILD_DIR} /build

// 컨테이너를 run 할때 실행되는 커맨드
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod","/build/libs/matdongsan-0.0.1-SNAPSHOT.jar"]
sudo docker run \
				-p 8080:8080 \
        —build-arg BUILD_DIR=/build \
        -v /home/ec2-user/log:/var/log \
				--name matdongsan \
				--env TZ=Asia/Seoul
        .

docker-compose.yaml

version: '3'

services:
  woowang:
    image: wangjh789/matdongsan
    container_name: matdongsan
    ports:
      - 8080:8080
    environment:
      - TZ=Asia/Seoul
    volumes:
      - /home/ec2-user/log:/var/log
profile
기록

0개의 댓글