스프링 부트 프로젝트를 도커에 올려보자

문지은·2021년 10월 19일
0

Docker

목록 보기
1/5
post-thumbnail

회사에서 이번에 진행하는 프로젝트의 요구 사항 중 하나가 DB를 도커에 올리는 것이었다. 그래서 MySQL과 Redis를 도커에 올리고 이를 실행하여 스프링 부트 어플리케이션을 실행할 수 있었다. 로컬이나 다른 사람 컴퓨터에서도 따로 환경 설정 필요 없이 어플리케이션이 실행된다니..! 신세계였다. 그런데 더 찾아보니 애플리케이션 자체를 올릴 수도 있는 것 같아서 알아보려고 한다.

Docker의 필요성

소프트웨어 패키징에 용이
도커로 이미지를 만든 뒤에 해당 이미지를 컨테이너에 올려서 쉽게 애플리케이션 구동 가능

예를 들자면 내가 내 컴퓨터에서 만든 프로그램을 다른 컴퓨터에서 실행시키고 싶다면 MySQL이나 Redis, Jenkins 등등 필요한 프로그램들을 모두 버전에 맞게 다시 다운 받아야 한다. 하지만 도커를 이용하면 내 컴퓨터에서 프로그램의 상태를 고대로 찰칵 찍어서 도커 허브라는 곳에 이미지로 저장해놓고 필요할 때마다 별도의 설치나 연결 없이 꺼내 쓸 수 있다!

또한 내 컴퓨터에 자바 버전이 다른 여러 프로그램을 실행시키고 싶을 때도 도커는 각각의 이미지들을 컨테이너에 넣어서 별도로 실행하기 때문에 구애 받지 않고 실행이 가능하다.

Spring Boot with Docker
해당 글을 참고하며 실습을 진행했다.

실습에 필요한 것

위의 글을 참고하여 이번 실습에 사용할 준비물을 써보았다.

  • 15분의 시간(정말...?)

  • IntelliJ

  • JDK 11

  • Gradle

  • Spring Boot

  • 리눅스 머신을 사용중이 아니므로 virtualized server

  • 그리고 가장 중요한 Docker

Spring Boot Application 작성

스프링 initializer 를 사용하면 기본으로 생성되는 application 코드에 rest controller 를 추가로 작성했다.

@SpringBootApplication
@RestController
public class DockerApplication
{
    // rest controller 추가 작성
    @RequestMapping("/")
    public String home()
    {
        return "Hello Docker World";
    }

    public static void main(String[] args)
    {
        SpringApplication.run(DockerApplication.class, args);
    }

}

이제 작성한 스프링 파일을 로컬에서 실행해보자.

./gradlew build && java -jar build/libs/docker-0.0.1-SNAPSHOT.jar
위의 명령어를 터미널에 입력하여 작성한 파일을 빌드하고 실행 파일을 실행한다.

로컬호스트로 접속시 결과가 잘 나온다!

Containerize - 1

이제 위에서 실행한 어플리케이션을 컨테이너에 올려보자.
그러려면 docker file을 생성해서 도커 이미지를 생성할 수 있어야 한다.

먼저 오직 jar 파일을 실행하게 하는 docker file을 작성해보자.

FROM openjdk:8-jdk-alpine

ARG JAR_FILE=target/*.jar

COPY ${JAR_FILE} app.jar
# 빌드된 jar 파일을 app.jar이란 이름으로 container에 복사

ENTRYPOINT ["java","-jar","/app.jar"]
# ENTRYPOINT는 해당 컨테이너가 수행될 때 반드시 지정한 명령을 수행하게 됨
# 위의 경우에서는 container에서 app.jar 파일을 실행

위와 같이 Dockerfile을 작성하고 해당 위치에서 docker를 이용해서 jar 파일을 빌드한다. 이 때 docker는 켜져있어야 한다. 상단 바에 이런 표시가 있으면 도커가 켜진 것!

docker build --build-arg JAR_FILE=build/libs/\*.jar -t springio/gs-spring-boot-docker .
위 명령어로 도커에서 jar 파일 실행

Containerize - 2

FROM openjdk:8-jdk-alpine

# 그룹, 유저 추가
# S 옵션으로 그룹과 유저 생성
# G 옵션으로 생성한 유저를 생성한 그룹에 포함시킴
RUN addgroup -S spring && adduser -S spring -G spring

# 위에서 생성한 그룹 추가하기
USER spring:spring

ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

이 때 수정된 내용을 적용하려면 기존의 container를 종료하고 다시 rebuild하여 이미지를 재생성해야 한다. 이 부분을 몰라서 아무리 실행해도 로컬 호스트에서 접속이 안되서 삽질을 많이 했다..🙀

(스프링 파일 내용 변동 있을 경우 jar 파일 삭제한 뒤 다시 빌드)

컨테이너 조회 : docker container ls -a
컨테이너 종료 : docker container rm (container ID)

이미지 조회 : docker image ls -a
이미지 종료 : docker image rm (image ID)

rebuild : docker build --build-arg JAR_FILE=build/libs/\*.jar -t springio/gs-spring-boot-docker .
컨테이너 실행 : docker run -p 8080:8080 springio/gs-spring-boot-docker

도커에서 실행한 모습
INFO의 첫번째 줄에서 접속자 로그를 볼 수 있다.

도커에서 어플리케이션을 실행하고 로컬 호스트로 접속하자 결과창이 잘 뜬다! 만세~ 😹

스프링 튜토리얼 글에서는 스프링 부트 jar 파일과 dependency를 깨끗하게 분리했다고 되어 있다. 여기서 더 perfomance를 발전할 수 있는데 container file system에서 레이어들을 생성하여 수정되지 않은 레이어들은 캐시되어 더 빠르게 실행할 수 있다.

실행된 컨테이너와 이미지의 모습

현재는 로컬에 있는 이미지만 보여지지만 이미지를 도커 허브에 올려서 필요할 때만 사용하게끔 할 수도 있다!

profile
백엔드 개발자입니다.

0개의 댓글