[ docker ] spring과 redis를 docker compose를 이용해 github actions로 ec2에 cicd 환경 구성하기

선호·2024년 3월 25일

인프라 탐험기

목록 보기
2/2
post-thumbnail

overview

spring boot로 개발한 project를 docker compose를 이용해서 cicd 자동화 환경을 만들어 보았습니다.

이 글을 참고해서 ec2에 redis랑 spring을 actions를 활용해 cicd환경을 구성해보고 싶으신 분들은 참고 하면 좋을 것 같습니다.

이 블로그 글은 github actions, ec2, redis, docker, docker-compose에 대한 사전지식을 먼저 습득하는 것을 권장드립니다.

ec2 설정

  • cicd 환경 구성에 앞서 ec2에 docker와 docker-compose를 설치해주어야합니다.

ec2에 docker 설치

docker-compose 설치

  • Docker-Compose 설치
sudo curl \
    -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" \
    -o /usr/local/bin/docker-compose
  • Docker-Compose 실행권한 주기
sudo chmod +x /usr/local/bin/docker-compose
  • Docker-Compose 설치 및 버전 확인
docker-compose --version

github actions 설정

github actions workflow yml 파일 구성

  • 이 블로그 글을 읽고 나면 아래와 같은 파일의 구성을 이해를 할 수 있을 것 입니다.
# project cicd를 위한 환경설정

name: skilled_project 배포 자동화

# 아래의 브랜치에 해당 트리거가 발생하면 자동 배포
on:
  pull_request:
    branches: [ "develop" ]

# 코드가 변경되면 실행할 작업들
jobs:
  CI-CD:
    runs-on: ubuntu-latest
    # 이 workflow에 리포지토리에 대한 읽기 권한을 부여한다.
    permissions:
      contents: read
    # 단계 설정
    steps:
      - uses: actions/checkout@v4
      #  1. jdk 버전 설정
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      # 2. Github secrets로부터 데이터를 받아서, 워크 플로우에 파일을 생성
      - name: Make application.properties
        run: |
          cd ./src/main/resources
          touch ./application.properties
          echo "${{ secrets.PROPERTIES }}" >> ./application.properties
        shell: bash

      # 3. project에 맞는 gradle 설정
      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

      # 4. gradle build
      - name: gradlew에 실행권한 부여
        run: chmod +x ./gradlew
      # 5. build
      - name: Build with Gradle Wrapper ( 프로젝트 빌드 )
        run: ./gradlew build

      # 6. docker build & push
      - name: docker build & push
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t ${{ secrets.DOCKER_REPO }}/skilled_project:2.0 .
          docker push ${{ secrets.DOCKER_REPO }}/skilled_project:2.0

      # 7. docker deploy to ec2
      - name: Docker deploy to ec2
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.HOST }}
          username: ubuntu
          key: ${{ secrets.SSH_KEY }}
          port: 22
          script: |
            sudo docker rm -f $(docker ps -aq)
            sudo docker pull ${{ secrets.DOCKER_REPO }}/skilled_project:2.0
            docker-compose up -d
            sudo docker image prune -f

1. 이벤트 분기 설정

  • 언제 cicd를 실행할지 분기점을 설정해줍니다.
on:
  pull_request:
    branches: [ "develop" ]
  • cicd의 환경을 설정해줍니다.
runs-on: ubuntu-latest
    permissions:
      contents: read

2. java 설정

  • cicd에서 build를 하기 위한 project와 동일하게 java를 설정해줍니다.
- name: Set up JDK 17
  uses: actions/setup-java@v4
  with:
    java-version: '17'
    distribution: 'temurin'

3. yml, properties 파일 설정

  • 로컬환경에서는 build를 수동으로 하면 application 파일을 따로 뺄 필요가 없이 로컬파일이 그대로 남아있기 때문에 신경쓰지 않고 build가 가능했습니다

  • 하지만 github의 cicd환경에서는 application 파일이 .gitignore에 등록이 되어 github의 repository에 존재하지 않게 됩니다. 그렇기에 actions 파일 설정에 application 파일을 만들어 build 할 수 있도록 설정을 추가해주는 작업이 필요합니다.

  • application 파일은 민감한 정보가 많이 들어있기 때문에 repository에 secret key로 등록을 해주어야합니다.

  • secret key를 기준으로 아래와 같이 작성합니다.
- name: Make application.properties
  run: |
    cd ./src/main/resources
    touch ./application.properties
    echo "${{ secrets.PROPERTIES }}" >> ./application.properties
  shell: bash
  • cd ./src/main/resources
    ㄴ resources 폴더 위치로 이동합니다.

  • touch ./application.properties
    ㄴ application.properties 파일을 생성합니다.

  • echo "${{ secrets.PROPERTIES }}" >> ./application.properties
    ㄴ secrets.PROPERTIES의 내용을 application.properties 파일에 기입합니다.

4. gradle 설정

  • build를 위해 project와 똑같이 gradle 환경설정을 해줍니다.
- name: Setup Gradle
  uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5
  • ubuntu 환경에서 build를 할 수 있게 끔 실행권한을 부여해줍니다.
- name: gradlew에 실행권한 부여
  run: chmod +x ./gradlew

5. project build

  • docker image 파일을 만들기 위해 project를 build합니다.
 - name: Build with Gradle Wrapper ( 프로젝트 빌드 )
   run: ./gradlew build

6. docker build & push to docker hub

  • build된 파일을 기반으로 docker image를 만든뒤 docker hub에 배포합니다.
- name: docker build & push
  run: |
    docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
    docker build -t ${{ secrets.DOCKER_REPO }}/skilled_project:2.0 .
    docker push ${{ secrets.DOCKER_REPO }}/skilled_project:2.0
  • docker build -t [ image name ]
    ㄴ docker image를 만듭니다.

  • docker push [ image name ]
    ㄴ docker image를 docker hub에 push합니다.

7. docker ec2에 배포

  • 만들어진 docker images를 이용해 ec2에 배포합니다.
  • appleboy/ssh-action 을 이용해 ec2와 연결합니다.
- name: Docker deploy to ec2
  uses: appleboy/ssh-action@master
    with:
      host: ${{ secrets.HOST }}
      username: ubuntu
      key: ${{ secrets.SSH_KEY }}
      script: |
        sudo docker rm -f $(docker ps -aq)
        sudo docker pull ${{ secrets.DOCKER_REPO }}/skilled_project:2.0
        docker-compose up -d
        sudo docker image prune -f
  • secrets.HOST
    ㄴ ec2의 주소를 입력해줍니다.

  • username
    ㄴ ec2의 환경이름을 적어줍니다.

위 부분에서 Ubuntu를 선택하였다면 ubuntu라고 적어줍니다.
  • secrets.SSH_KEY
    ㄴ ec2를 접속 할 때 사용한 ssh key를 넣어줍니다.

  • sudo docker rm -f $(docker ps -aq)
    ㄴ 실행하고 있는 모든 docker 파일을 종료합니다.

  • sudo docker pull ${{ secrets.DOCKER_REPO }}/skilled_project:2.0
    ㄴ docker hub에서 docker images를 pull하여 가져옵니다.

  • docker-compose up -d
    ㄴ docker-compose.yml 파일을 사용하여 백그라운드 환경에서 실행시킵니다.

docker-compose 파일이 ec2에 존재하지 않을시 ec2에 업로드를 해주어야합니다.

  • docker-compose 파일은 아래와 같이 구성되어 있습니다.

version: '3.8'

services:
  redis:
    image: redis
    ports:
      - "6379:6379"

  spring:
    image: yiyaaa/skilled-project
    container_name: skilled_project
    ports:
      - "8080:8080"
    depends_on:
      - redis

  • sudo docker image prune -f
    ㄴ ec2에 존재하는 docker iamge파일중에서 사용하지 않는 image파일들을 삭제합니다.

마치며

  • 위와 같이 구성을 하면 ec2에서 docker-compose 환경에서 spring과 redis를 같은 서버내에 위치시켜 실행시키는 것이 가능합니다.
  • 이와 같이 구성하면 따로 redis를 설치하지 않아도 docker container로 redis가 작동하기에 설정측면에서 편의성을 가져갈 수 있다는 점입니다.
  • 하지만 위와 같은 구성의 단점은 서버가 scale up 될 시 redis도 그만큼 늘어나기에 비용적인측면에서 안좋게 작용합니다. 그렇기에 단순 프로젝트 환경구성으로는 나쁘지 않다고 생각하지만 실질적인 서비스 측면으로 생각한다면 좋은 선택이 아닐 수 있습니다.
profile
개발을 하더라도 탄탄하게

0개의 댓글