[TIL] Spring Boot Application 환경 구성 with Dockerfile

su·2024년 9월 10일
0

TIL

목록 보기
93/93
post-thumbnail

기본 Spring Boot 생성

https://start.spring.io/
위의 사이트에 접속하여, gradle에 Spring Web을 추가해준 후 프로젝트를 만든다.

기본 세팅으로 두고 프로젝트를 만들었다.
(Gradle-Groovy, Java, Jar, Java-17 | Dependencies - Spring Web)

프로젝트를 다운받으면, 압축을 해제하고 IntelliJ에서 열어준다.

API 테스트를 위한 Endpoint 생성

배포 후 테스트를 위해서 간단한 Endpoint를 생성해준다.
따로 복잡하게 구성하지는 않고, Controller를 생성하여 코드를 작성해주었다.

@RestController
@RequestMapping("/api")
public class Controller {

    @GetMapping("/connection")
    public ResponseEntity<Object> getConnection() {
        String result = "Success";
        return new ResponseEntity<>(result, HttpStatus.OK);
    }
}

배포가 성공했다면, /api/connection 으로 접속했을 때 Success라는 글자가 보여야 한다.

Dockerfile 생성

이제 배포를 위한 Dockerfile을 생성해보자.
Dockerfile은 프로젝트의 루트 경로에 생성해야 한다.

그리고 Dockerfile의 내용을 채워보자 !

FROM bellsoft/liberica-openjdk-alpine:17

CMD ["./gradlew", "clean", "build"]

VOLUME /tmp

ARG JAR_FILE=build/libs/*.jar

COPY ${JAR_FILE} app.jar

EXPOSE 8080

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

각 코드의 의미는 아래와 같다.

코드내용
FROM bellsoft/liberica-openjdk-alpine:17Java 17버전이 포함된 Docker 이미지
CMD ["./gradlew", "clean", "build"]Gradle로 빌드 실행
VOLUME /tmp컨테이너 내에 /tmp 디렉터리를 볼륨으로 설정
ARG JAR_FILE=build/libs/*.jar빌드된 JAR 파일 경로를 변수로 설정
COPY ${JAR_FILE} app.jar빌드된 JAR 파일을 컨테이너 내의 app.jar로 복사
EXPOSE 8080컨테이너에서 8080번 포트를 노출
ENTRYPOINT ["java","-jar","/app.jar"]컨테이너가 시작되면 java -jar /app.jar 명령을 실행하여 애플리케이션을 시작

VOLUME /tmp

VOLUME 부분이 이해가 잘 되지 않아서 추가로 검색해봤다 ..!

볼륨(Volume) 은,
데이터를 영구적으로 보관하기 위해 사용
일반적으로 컨테이너 내부 파일 시스템이 비휘발성이므로,
컨테이너가 삭제되거나 재시작할 경우 내부 저장 데이터가 사라짐.
이 때, VOLUME을 사용하면 지정된 디렉토리를 외부 스토리지로 연결해 컨테이너 종료 후에도 데이터가 유지됨

/tmp 디렉토리
/tmp는 리눅스 환경에서 임시 파일을 저장하는 디렉토리
자바 어플리케이션이나 웹 서버의 경우, 실행 중에 임시 파일이나 캐시 데이터를 /tmp에 저장할 수 있음
임시 데이터를 저장하는 /tmp 디렉토리에 볼륨을 설정하면, 컨데이너가 재시작되더라도 해당 데이터를 유지할 수 있음
특히, 컨데이너를 여러 번 재시작하거나 업데이트하는 경우 중요한 임시 데이터(세션 데이터, 캐시 등)를 잃지 않도록 해줌

호스트와의 데이터 공유
Docker가 이 디렉토리를 호스트 시스템의 디렉토리에 자동으로 연결해줌
이 경우, 호스트 시스템의 지정된 경로에 있는 데이터와 /tmp 디렉토리의 데이터가 동기화됨
또한, 다른 컨테이너가 동일한 볼륨을 사용할 수 있어 컨테이너 간 데이터 공유에도 사용 가능

데이터 보존의 이점
만일 컨테이너를 삭제하더라도 /tmp 디렉토리에 저장된 파일은 외부 볼륨에 남아있으므로 재시작 시 이 데이터를 그대로 사용 가능

=> VOLUME /tmp /tmp 디렉토리에 저장된 임시 데이터가 컨테이너가 종료되거나 삭제되더라도 유지되도록 외부 스토리지와 연결하는 설정

생성한 Dockerfile 실행

먼저, 이미지를 생성한다.
터미널에 아래의 명령어를 입력한다.

$ docker build -t [컨테이너 이미지 이름] .

[컨테이너 이미지 이름] 부분에는 본인이 생성할 이미지의 이름을 넣으면 된다.

위의 명령어를 실행하면 Docker에 이미지가 뜬 것을 확인할 수 있다.

그리고 컨테이너를 생성하고 실행하는 명령어를 입력한다.

$ docker run -d --name [컨테이너 이름] -p 8080:8080 [실행할 컨테이너 이미지 이름]

원하는 [컨테이너 이름] 으로 [실행할 컨테이너 이미지 이름]을 실행하는데, 호스트 기기의 8080 포트와 컨테이너의 8080 포트를 연결한다.

그런데 ...
뭔가 수월하다 했다 ... 오류가 난다 ! ㅎ.ㅎ

 => ERROR [2/2] COPY build/libs/*.jar app.jar
------
 > [2/2] COPY build/libs/*.jar app.jar:
------
Dockerfile:9
--------------------
   7 |     ARG JAR_FILE=build/libs/*.jar
   8 |     
   9 | >>> COPY ${JAR_FILE} app.jar
  10 |     
  11 |     EXPOSE 8080
--------------------
ERROR: failed to solve: lstat /var/lib/docker/tmp/buildkit-mount336840728/build/libs: no such file or directory

해당 파일이나 디렉토리를 찾을 수 없다는 내용인데, jar 파일이 없는건가 ..?

일단 생성한 컨테이너와 이미지를 차례로 삭제하고 다시 실행해봤더니,

Error: Unable to access jarfile /app.jar

이번엔 다른 오류가 난다 .. jar 파일에 접근할 수가 없다고 ?

이럴 때는 내가 설정한 경로로 들어가서 jar 파일을 찾아보면 된다고 하던데,
아니... 왜 build/libs에 jar 파일이 없나요 ..
보니까 libs 폴더도 만들어져 있지 않았다는 사실 ..! 정말 ㅜㅜ

이럴 때는 Gradle > Tasks > build > bootJar를 실행해주면 된다 !

이미지에 보이는 bootJar를 실행해주면,
build/libs에 jar 파일이 생성된 것을 확인할 수 있다.

그 후 명령어를 다시 실행했더니, 문제 없이 잘 실행되었다 !

설정해둔 Endpoint도 원하는 대로 잘 나오는 것을 확인할 수 있었다

참고

profile
(❁´◡`❁)

0개의 댓글