티스토리 뷰

Github Action을 통해 Docker 환경을 Elastic Beanstalk에 배포해보자. 이번 글에서는 Github Action으로 CI 환경을 구축하고, Docker hub에 docker 이미지를 올리는 것까지 해보려 한다. 전체적인 구조는 아래와 같다.

[ 아키텍처 ]

[ CI/CD 과정 ]

1. Github 에 코드를 push

2. Github Action job 수행

    2-1. Spring boot 코드 build 

    2-2. Dockerfile 빌드

    2-3. Docker Hub에 이미지 push

    2-3. AWS EB에 docker-compose 업로드

5. AWS EB는 docker-compose를 실행해 배포

[ 구현 과정 ]

1. Spring Boot 프로젝트 세팅

2. Dockerfile 작성

3. Github Action yml 파일 작성

4. AWS Elastic BeanStalk 환경 세팅

5. RDS 환경 세팅

6. docker-compose 파일 작성

7. Github Action yml 배포 스크립트 추가

8. Github Action 실행시켜 배포

 

1.  Spring Boot 프로젝트 세팅


1-1. 프로젝트 생성

  • Spring Boot  3.0.5 
  • Java 17

build.gradle 의존성은 아래와 같이 추가해주었다.

dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
   implementation 'org.springframework.boot:spring-boot-starter-web'
   compileOnly 'org.projectlombok:lombok'
   annotationProcessor 'org.projectlombok:lombok'
   runtimeOnly 'com.mysql:mysql-connector-j'
   testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

1-2. 코드 작성

@Entity
@Getter
@NoArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    public User(String name) {
        this.name = name;
    }
}

 

public interface UserRepository extends JpaRepository<User, Long> {
}
@RestController
@RequiredArgsConstructor
public class HelloController {

    private final UserRepository userRepository;

    @GetMapping("/")
    public String healthCheck() {
        return "health check OK !";
    }

    @GetMapping("/hello")
    public String hello() {
        User user = new User("twoosky");
        User newUser = userRepository.save(user);

        return "Id : " + newUser.getId() + " Name : " + newUser.getName();
    }
}

Elastic beanstalk의 health check 경로는 '/' 이다. 해당 경로의 api를 작성하지 않으면 404로 인해 health check에 실패하고, 배포가 불가능하다. (중요) 이러한 이유로 간단히 health check를 위한 api를 작성했다.

그리고, RDS에 데이터가 저장되는지 확인하기 위해 User 저장 후 id와 name을 출력하는 api를 작성했다.

 

1-3. application.yml 작성

spring:
    datasource:
        url: jdbc:mysql://${rds.hostname}:${rds.port}/${rds.db.name}?serverTimezone=UTC&characterEncoding=UTF-8
        username: ${rds.username}
        password: ${rds.password}
        driver-class-name: com.mysql.cj.jdbc.Driver

    jpa:
        show-sql: true
        hibernate:
            ddl-auto: create
        database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
        properties:
            hibernate:
                dialect: org.hibernate.dialect.MySQL57Dialect

 

docker-compose 파일로부터 RDS 환경변수를 받아 데이터베이스를 세팅하기 위해 위와 같이 환경변수를 사용했다.

2. Dockerfile 작성


nginx, spring boot 컨테이너를 띄우고, nginx를 Reverse Proxy로 사용할 것이다. 즉, nginx 80 포트로 들어오는 요청을 spring boot 컨테이너의 8080포트로 넘겨줄 것이다. 

2-1. nginx default.conf 작성

nginx 디렉토리를 생성해 그 안에 작성하면 된다. default.conf에서 nignx Reverse Proxy 설정을 해준다.

upstream spring-app {
    server springboot:8080;
}

server {
    listen 80;

    location / {
        proxy_pass http://spring-app;
    }
}

요청을 전달할 upstream 블럭을 정의한다. springboot는 docker-compose의 spirng boot 서비스명이다

nginx는 기본적으로 80번 포트를 사용하므로 listen 80포트로 구성

nginx는 해당 location 블럭 내 proxy_pass  주소로 요청을 전달해준다. upstream명으로 지정 

 

nginx upstream 이란? upstream 서버는 다른 말로 Origin 서버라고도 부른다. proxy_pass를 통해 nginx 웹서버가 받은 요청들을 여러 대의 애플리케이션 서버로 넘겨주는 역할을 한다.

2-2. nginx Dockerfile 작성

FROM nginx

COPY default.conf /etc/nginx/conf.d/default.conf

 

2-3. spring boot Dockerfile 작성

FROM openjdk:17-jdk-slim-buster

WORKDIR /app

COPY build/libs/demo-0.0.1-SNAPSHOT.jar app.jar

CMD ["java", "-jar", "app.jar"]

 

3. Github Action yml 파일 작성


3-1. GitHub Action yml 파일 작성

name: deploy

on:
  push:
    branches:
      - 'main'

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - 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: Build with Gradle
        run: ./gradlew clean build -x test

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}


      - name : Build Docker Image & Push to Docker Hub
        run: |
          docker build . -t twoosky/docker-springboot
          docker build ./nginx -t twoosky/docker-nginx
          docker push twoosky/docker-springboot
          docker push twoosky/docker-nginx

 

각 job을 자세히 알아보자.

  • actions/checkout@v3 : 프로젝트 코드를 checkout 한다.
  • actions/setup-java@v3 : Github Action이 실행될 OS에 Java 설치, (참고)
  • run: chmod +x ./gradlew : gradlew wrapper를 실행할 수 있도록 실행 권한(+x) 부여, 권한이 있어야 build 가능
  • run: ./gradlew clean build : gradlew wrapper를 통해 해당 프로젝트 build
  • docker/login-action@v2 : docker hub 로그인 (참고)  
  • docker build {Dockerfile 경로} -t {Image 이름} : Dockerfile 빌드해 해당 이름으로 docker Image 생성
  • docker push {Image 이름} : 해당 docker Image를 docker hub에 푸시

3-2. Docker Hub 로그인 위한 secrets key 등록

3-3. Github Action 실행

여기서는 on: push: main 으로 설정했으므로, main 브랜치에 코드가 push되면 아래와 같이 Github Action이 실행된다.

정상적으로 실행이 완료되었다면, Docker Hub에 Docker Image가 올라와 있는 것을 확인할 수 있다.

 

이번 글에서는 Nginx, Spring boot Dockerfile을 작성하고 Github Action을 통해 프로젝트 빌드 및 Docker hub 이미지 푸시까지 진행했다. 다음 글에서 AWS Elastic Beanstalk과 RDS 환경 세팅을 해보자.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함