본문 바로가기
Cloud/AWS

EC2 생성하고 Spring Boot 프로젝트 도커로 배포하기

by 민휘 2023. 10. 29.

기존 프로젝트를 리팩토링하기 전에 도커, AWS, Github Actions를 이용해 배포 파이프라인을 만들어보려고 한다. 이 글을 그중 첫번째인 EC2 세팅과 스프링 부트 도커라이즈를 다룬다.

 

순서

  1. ec2 인스턴스와 고정 Ip 할당, 보안 그룹 생성
  2. ec2에 깃허브와 도커 설치
  3. 로컬에서 Spring Boot 프로젝트에 hello world api 추가
  4. 로컬에서 Spring Boot 프로젝트 도커라이즈하고 깃허브에 푸시
  5. ec2에서 깃허브 클론해서 도커 이미지 빌드하고 컨테이너 실행

 

ec2 인스턴스와 보안 그룹 생성

프리티어 계정에서 진행한다.

ec2 대시보드 ui는 자주 변경되어서, 캡쳐 대신 지정해야할 항목만 작성했다.

  • 태그 : Name : 서비스이름
  • AMI : Amazon Linux2 AMI (HVM)
  • 인스턴스 유형 : t2.micro
  • 키 페어 : RSA pem키 생성, 추후 로컬에서 가상머신으로 ssh 접속할 때 사용 예정
  • 네트워크 보안그룹 추가
    • 규칙1 로컬에서 ssh 접속 : 내IP:22
    • 규칙2 외부에서 애플리케이션 접속 : 모든IP:8080
  • 스토리지 : 30 GiB

 

탄력적 IP 할당

가상머신 인스턴스가 고정 IP를 가지도록 탄력적 IP를 할당하고 인스턴스를 연결한다.

  • 왼쪽 카테고리 > 탄력적 IP > 새 IP 할당
  • IP 선택 후 작업 > 인스턴스, 프라이빗 IP 주소 선택 > 연결

ec2 대시보드로 돌아가서 퍼블릭, 탄력적 IP가 잘 연결되었는지 확인한다.

생성한 탄력적 IP는 무조건 EC2에 바로 연결하고, EC2를 삭제할 때 반드시 함께 삭제한다. 안하면 비용 청구됨!!

 

ec2 접속 (MAC)

다운받은 pem 키 ~/.ssh에 복사하고 권한 부여

cp zerozone-service.pem ~/.ssh
cd ~/.ssh
ls | grep *.pem
chmod 600 ~/.ssh/zerozone-service.pem

 

~/.ssh에 config 파일 생성하고 권한 설정, ssh 접속

vim ~/.ssh/config

# 작성
HOST 서비스명
        HostName 탄력적IP
        User ec2-user
        IdentityFile ~/.ssh/zerozone-service.pem

# 권한 변경
chmod 700 ~/.ssh/config

# ssh 접속
ssh 서비스명

 

타임존 KST로 변경

sudo rm /etc/localtime
sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

 

호스트네임 변경

sudo hostnamectl set-hostname 호스트네임
sudo reboot
ssh 서비스명

 

/etc/hosts에 호스트네임 추가

sudo vim /etc/hosts

# 작성
127.0.0.1   zerozone

# 호스트네임 등록 확인
curl zerozone

# 정상적으로 등록되었다면 80 에러 발생 (아직 80 포트에서 돌고 있는 서비스가 없으므로)
curl: (7) Failed to connect to zerozone port 80 after 0 ms: Couldn't connect to server

 

ec2에 도커 설치

AWS Linux2가 제공하는 amazon-linux-extras 패키지를 이용해 도커를 설치한다.

# 설치
sudo amazon-linux-extras install docker

# 설치 확인
docker -v

 

이렇게 해서 도커 컨테이너가 실행될 환경 세팅을 마쳤다. 서버를 만들 때마다 이 작업을 하는 것이 귀찮다면, 세팅해둔 EC2의 AMI를 생성해 이 AMI로 가상 머신을 시작하는 것을 추천한다. (Golden AMI!)

 

hello world!

스프링 부트 프로젝트를 생성한다.

  • Java 17
  • 빌드툴 : Gradle
  • 패키징 : Jar

 

dependency

  • Spring Web
  • Spring Data Jpa
  • Lombok
  • H2 Database

 

Hello World API 추가

package com.example.zerozonerefactoring.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello World!";
    }
}

 

 

스프링 부트 프로젝트 도커라이즈

도커파일 작성

# 멀티 스테이징, gradle 기반의 build 이미지
FROM gradle:7.6.1-jdk17-alpine as build

ENV APP_HOME=/apps
WORKDIR $APP_HOME

# gradle로 프로젝트 의존성 설치
COPY build.gradle settings.gradle gradlew $APP_HOME/
RUN gradle build --parallel --continue > /dev/null 2>&1 || true

# Gradle 관련 설정 파일들을 컨테이너 내부로 복사
COPY gradle $APP_HOME/gradle
RUN chmod +x gradlew

# jar 생성
RUN ./gradlew build || return 0

# 소스 코드 복사
COPY src $APP_HOME/src

# jar을 제외한 빌드 결과 제거
RUN ./gradlew clean build

FROM openjdk:17-jdk-slim

ENV APP_HOME=/apps
ARG ARTIFACT_NAME=app.jar
ARG JAR_FILE_PATH=build/libs/ZeroZoneRefactoring-1.0.jar

WORKDIR $APP_HOME

COPY --from=build $APP_HOME/$JAR_FILE_PATH $ARTIFACT_NAME

EXPOSE 8080

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

 

로컬에서 이미지 빌드

  • m1에서 빌드한다면 --platform linux/x86_64 옵션을 붙여서 실행한다. vm에서 빌드할 때는 옵션 넣으면 안된다.
  • gradle:7.6.1-jdk17-alpine 이미지가 없는 문제가 있었는데, 아직 arm64가 지원하지 않는 듯 하다. https://velog.io/@kikiki0611/Mac-M1-docker-build-문제
docker build -t mingadinga/zerozone:1.0 . --platform linux/x86_64
docker run -p 8080:8080 -d mingadinga/zerozone:1.0

도커 컨테이너가 로컬에서 잘 실행된 모습이다.