본문 바로가기
Cloud | CICD/Deploy

[Deploy] Github Actions + Docker + EC2 자동 배포 #2 | Docker 설정

by seoyamin 2023. 2. 28.

1. Dockerfile 작성

- 스프링 프로젝트 최상단 경로에 Dockerfile 추가

 

 

FROM adoptopenjdk/openjdk11
ARG JAR_FILE=./build/libs/프로젝트명-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

 

 

2. Ubuntu EC2에 Docker 설치

- EC2 인스턴스에 접속하여 수행

 

$ sudo apt-get update

 

$ sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common

 

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

ok가 뜨면 성공


 

3. Docker Repository 등록

- EC2 인스턴스에 접속하여 수행

 

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 docker-ce

 

▷ 설치 확인

$ docker -v

 

 

4. Docker 실행

- EC2 인스턴스에 접속하여 수행

 

▷ Docker 실행

$ sudo systemctl enable docker

 

▷ Docker 활성화

$ sudo service docker start

 


5. Github Action 설정

Github Action의 CICD를 위한 설정 파일을 작성해줄 것이다. 

 

등장한 yml 파일을 각자 상황에 맞게 설정해주면 된다.

 

▶ 전체 yml

name: Babyak CI/CD with Gradle

on:
  push:
    branches: [ "main" ]

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    
    # Checkout
    - name: Checkout
      uses: actions/checkout@v3
    
    # JDK Set-up
    - 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
    
    # Gradle caching
    - name: Gradle Caching
      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-secret.yml
    - name: Create application-secret.yml
      run: |
        # application-secret.yml 생성
        touch ./src/main/resources/application-secret.yml 
        
        # Secrets의 APPLICATION_SECRET 값을 application-secret.yml에 쓰기
        echo "${{ secrets.APPLICATION_SECRET }}" > ./src/main/resources/application-secret.yml
      shell: bash
    
    # Build with Gradle
    - name: Build with Gradle
      run: ./gradlew build -x test
    
    # Docker Image Build
    - name: Web Docker Build & Push
      run: |
        docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
        docker build -t ${{ secrets.DOCKER_REPO }} .
        docker push ${{ secrets.DOCKER_REPO }}
    
    # EC2 접속 & Pull & 실행
    - name: executing remote ssh commands using password
      uses: appleboy/ssh-action@v0.1.6
      with:
        host: ${{ secrets.EC2_HOST }}
        username: ubuntu
        key: ${{ secrets.EC2_KEY }}
        port: 22
        script: |
          sudo docker stop $(docker ps -a -q)
          sudo docker rm $(docker ps -a -q)
          sudo docker rmi $(sudo docker images -q)
          sudo docker pull ${{ secrets.DOCKER_REPO }}
          sudo docker run -d -p 80:8080 ${{ secrets.DOCKER_REPO }}

 

▶ yml 뜯어보기

◑ 형식
- name : 옵션의 이름 (간략한 설명)
- run : 직접 작성한 명령어 실행
- uses : 시중에 만들어져 있는 명령어 가져다가 실행

※ steps 아래에 빌드 시 수행할 명령어 목록을 작성해주면 된다.

 

(1) name, on, permission

  • name : 전체 파일에 대한 간략한 설명
  • on : 이 설정 파일이 언제 실행될 것인지 (내 경우 'main' 브랜치에 푸쉬된 경우 실행)
  • permissions : read

name: Babyak CI/CD with Gradle

on:
  push:
    branches: [ "main" ]

permissions:
  contents: read

 

(2) checkout, set-up, gradlew permission

  • checkout : 매 푸쉬마다 깃허브 레포지토리 내용을 runner로 옮겨준다.
  • set up : 각자 프로젝트에 필요한 요소들을 준비 (내 경우 JDK 11이 필요해서 다운로드)
  • gradlew permission : 빌드를 위해 gradlew의 권한을 열어준다. 

gradlew permission 설정 안했다가 빌드 실패했었다...

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    
    # Checkout
    - name: Checkout
      uses: actions/checkout@v3
    
    # JDK Set-up
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    
    # Gradlew Permission
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew

 

 

(3) gradle caching 

- 빌드 속도가 향상된다고 하여 추가

 

# Gradle caching
- name: Gradle Caching
  uses: actions/cache@v3
  with:
    path: |
      ~/.gradle/caches
      ~/.gradle/wrapper
    key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
    restore-keys: |
      ${{ runner.os }}-gradle-

 

(4) create application-secret.yml

Github Secrets에 있는 APPLICATION_SECRET 파일을 이용해서 application-secret.yml 만들기

 

# create application-secret.yml
- name: Create application-secret.yml
  run: |
    # application-secret.yml 생성
    touch ./src/main/resources/application-secret.yml 

    # Secrets의 APPLICATION_SECRET 값을 application-secret.yml에 쓰기
    echo "${{ secrets.APPLICATION_SECRET }}" > ./src/main/resources/application-secret.yml
  shell: bash

 

(5) Spring Boot 프로젝트 빌드

# Build with Gradle
- name: Build with Gradle
  run: ./gradlew build -x test

 

(6) Docker Image 빌드

# Docker Image Build
- name: Web Docker Build & Push
  run: |
    docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
    docker build -t ${{ secrets.DOCKER_REPO }} .
    docker push ${{ secrets.DOCKER_REPO }}

 

(7) EC2 접속 후 pull & run

- 기존에 돌아가고 있는 애들을 삭제한 다음, 새로운 이미지를 pull & run 

 

# EC2 접속 & Pull & 실행
- name: executing remote ssh commands using password
  uses: appleboy/ssh-action@v0.1.6
  with:
    host: ${{ secrets.EC2_HOST }}
    username: ubuntu
    key: ${{ secrets.EC2_KEY }}
    port: 22
    script: |
      sudo docker stop $(docker ps -a -q)
      sudo docker rm $(docker ps -a -q)
      sudo docker rmi $(sudo docker images -q)
      sudo docker pull ${{ secrets.DOCKER_REPO }}
      sudo docker run -d -p 80:8080 ${{ secrets.DOCKER_REPO }}

 

 

 

※ 참고 | Github Secrets 설정하기

깃허브에 그대로 올리면 안되는 env 파일이나 변수들을 Github Secrets로 저장할 수 있다.

 

Secrets 소개 형식
APPLICATION_SECRET application-secret.yml 파일 application-secret.yml 복붙
DOCKER_USERNAME 내 Docker 계정 상 유저이름  
DOCKER_PASSWORD 내 Docker 계정 비밀번호  
DOCKER_REPO 내 Docker Repository 주소 DOCKER_USERNAME/Repository명
EC2_HOST EC2 퍼블릭 DNS ec2-1-23-45-678.ap.northeast-2.compute.amazonaws.com
EC2_KEY EC2 Pem Key -----BEGIN RSA PRIVATE KEY----- 부터
-----END RSA PRIVATE KEY----- 까지 (전부 포함)