Springboot + docker compose + github actions를 이용해 EC2에 배포하기

일단 해볼게·2023년 11월 17일
0

Springboot

목록 보기
4/26

Docker Image 저장 선택지


Dockerhub Public Repository에 빌드된 파일 저장

  • 단점
    • public Respository는 누구나 접근할 수 있어 application.yml 같은 환경변수가 노출될 수 있다. → Private으로 저장하는 방법이 필요하다.

Github packages의 컨테이너 레지스트리에 저장

  • 장점

    • private Repository를 docker hub보다 많이 만들 수 있다.
    • 대학교 계정으로 인증할 경우 유료계정으로 전환되어 2GB까지 사용할 수 있다. (Github Pro 뱃지)
  • 단점


Amazon Elastic Container Registry에 저장

  • 단점
    • AWS 프리 티어에서 Private 리포지토리에 대한 월 500MB의 스토리지를 1년간 받습니다.
    • 500MB 넘어가면 유료로 전환된다.

Dockerhub Private Repository에 빌드된 파일 저장

  • 장점
    • Private Repository라 환경변수가 유출되지 않는다.
  • 단점
    • Dockerhub Private Repository는 계정 당 하나만 생성할 수 있다.

채택한 방법 (Dockerhub Private Repository)

보안을 챙기기 위해 팀 계정을 만들어서 Dockerhub Private Repository에 빌드된 파일 저장하는 방법 채택했다.

Dockerhub에 Private Repository 생성

Dockerhub에 로그인해서 Create repository를 클릭하고, 레포지토리를 Private으로 설정 후 생성한다. 필자는 이미 private repository가 존재해서 생성이 불가능하다.

pem 파일에 권한 설정

chomod 400 {파일명}

권한 설정 후 EC2에 접속한다. EC2 인스턴스 연결을 누르면 ssh로 연결하는 방법이 나와있다.

ssh -i ~

EC2에 docker, docker-compose 설치

sudo yum update -y

Docker 그룹에 sudo 추가 (인스턴스 접속 후 도커 바로 제어할 수 있도록)

sudo usermod -aG docker ec2-user

ec2-user는 인스턴스에 접속하면 나오는 유저네임이다. 변경하지 않는 한 그대로다.

인스턴스 재접속 후 Docker 명령어 실행해보기

sudo reboot
docker run hello-world

최신 docker-compose 설치하기

sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose

권한 부여

sudo chmod +x /usr/local/bin/docker-compose

설치 확인

docker-compose version

github actions yml 내용 분석

name: cd-dev-docker

on:
  push:
    branches: [ "dev" ]

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          token: ${{secrets.ACTION_TOKEN}}
          submodules: true

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Make directory for deliver
        run: mkdir deploy

      - name: Build with Gradle
        run: ./gradlew clean build

      - name: Copy jar
        run: cp ./build/libs/*.jar ./deploy/

      # 도커 컴포즈 설정 파일 서버로 전달하기(복사 후 붙여넣기)
      - name: Send docker-compose.yml
        uses: appleboy/scp-action@master
        with:
          username: ec2-user
          host: ${{ secrets.AWS_DEV_HOSTNAME }}
          key: ${{ secrets.AWS_DEV_PRIVATE_KEY }}
          source: "./src/main/resources/backend-config/docker-compose.yml"
          target: "/home/ec2-user/"

      # nginx 설정 파일 서버로 전달하기(복사 후 붙여넣기)
      - name: Send nginx.conf
        uses: appleboy/scp-action@master
        with:
          username: ec2-user
          host: ${{ secrets.AWS_DEV_HOSTNAME }}
          key: ${{ secrets.AWS_DEV_PRIVATE_KEY }}
          source: "./nginx/nginx.conf"
          target: "/home/ec2-user/"

      ## springboot 도커 이미지 빌드 후 도커허브에 push하기
      - name: web springboot docker build and push
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t ${{ secrets.DOCKER_REPOSITORY }}:backend .
          docker push ${{ secrets.DOCKER_REPOSITORY }}:backend

      ## nginx 도커 이미지 빌드 후 도커허브에 push하기
      - name: web nginx docker build and push
        run: |
          cd ./nginx
          docker build -t ${{ secrets.DOCKER_REPOSITORY }}:nginx .
          docker push ${{ secrets.DOCKER_REPOSITORY }}:nginx

      # nginx.conf 경로 변경 후 도커 컴포즈 실행하기
      # 도커 허브에서 jar파일 및 pull후에 컴포즈 up
      - name: Deploy to Dev
        uses: appleboy/ssh-action@master
        with:
          username: ec2-user
          host: ${{ secrets.AWS_DEV_HOSTNAME }}
          key: ${{ secrets.AWS_DEV_PRIVATE_KEY }}
          script: |
            docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
            sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_REPOSITORY }}
            cd src/main/resources/backend-config
            sudo cp /home/ec2-user/nginx/nginx.conf /home/ec2-user/src/main/resources/backend-config/nginx/nginx.conf
            docker-compose down
            docker rmi $(docker images -q)
            docker-compose up -d

ACTION_TOKEN : 개인 깃허브 토큰

AWS_DEV_HOSTNAME : EC2 인스턴스 퍼블릭 DNS (탄력적 ip)

AWS_DEV_PRIVATE_KEY : .pem 키 내용 (vi, cat으로 확인 가능)

DOCKER_REPOSITORY : Dockerhub에 push한 레포지토리 이름

DOCKER_USERNAME : Dockerhub 사용자 이름

DOCKER_PASSWORD : Dockerhub 비밀번호


메인 레포지토리에 서브모듈을 활성화한다.

steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          token: ${{secrets.ACTION_TOKEN}}
          submodules: true

서브모듈은 github private repository라서 사용하기 위해 개인 깃허브 토큰이 필요하다.


docker-compose 파일을 ec2에 전달한다.

- name: Send docker-compose.yml
        uses: appleboy/scp-action@master
        with:
          username: ec2-user
          host: ${{ secrets.AWS_DEV_HOSTNAME }}
          key: ${{ secrets.AWS_DEV_PRIVATE_KEY }}
          source: "./src/main/resources/backend-config/docker-compose.yml"
          target: "/home/ec2-user/"

source는 docker-compose의 로컬 경로이다.

target은 ec2 경로이다.

이 상황에서 ec2의 /home/ec2-user/src/main/resources/backend-config 에 docker-compose.yml 파일이 생긴다.

별도 설정 파일이 있으면 docker-compose의 경로와 ec2의 경로를 동일하게 설정해야한다.

필자의 경우 nginx.conf이 필요해서 ec2의 /home/ec2-user/src/main/resources/backend-config/nginx 경로에 nginx.conf를 전달했다.


이미지를 도커 허브에 push한다.

## springboot 도커 이미지 빌드 후 도커허브에 push하기
      - name: web springboot docker build and push
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t ${{ secrets.DOCKER_REPOSITORY }}:backend .
          docker push ${{ secrets.DOCKER_REPOSITORY }}:backend

      ## nginx 도커 이미지 빌드 후 도커허브에 push하기
      - name: web nginx docker build and push
        run: |
          cd ./nginx
          docker build -t ${{ secrets.DOCKER_REPOSITORY }}:nginx .
          docker push ${{ secrets.DOCKER_REPOSITORY }}:nginx

Dockerhub Repository가 Private이기 때문에 이미지를 pull 받기 위해 로그인을 수행해야한다.

dockerhub에 두 이미지를 푸시하기 위해 태그로 구분했다.

docker build -t {DOCKER_REPOSITORY}:{태그명} .
docker push {DOCKER_REPOSITORY}:{태그명}

참고

적용한 프로젝트 : https://github.com/Anifriends/Anifriends-Backend

EC2에 Docker 설치 : https://jinjinyang.tistory.com/46

EC2에 docker compose 설치 : https://narup.tistory.com/223

profile
시도하고 More Do하는 백엔드 개발자입니다.

0개의 댓글