안녕세계
[Spring] Docker 컨테이너 배포 (with. Gradle) 본문
[Spring] Docker 컨테이너 배포 (with. Gradle)
Junhong Kim 2020. 1. 5. 22:58
SpringBoot 앱을 개발환경(Development/Production)을 나누어 배포하는 방법에 대해 알아봅니다 🤩
(본 포스팅에서는 SpringBoot + Gradle + Docker를 사용합니다.)
1. Spring Initializr에서 dependency로 Spring Web만 추가하여 Gradle Project를 생성합니다.
2. application.properties를 application.yaml 파일로 변경후 application-{profile}.yaml 형식의 파일을 생성합니다.
(properties 파일을 선호하는 경우 변경하지 않아도 됩니다.)
3. application-dev.yaml과 application-prod.yaml 파일은 개발환경과 운영환경의 셋팅을 달리하기 위함입니다.
각 파일에 spring.profiles.active에 활성화할 profile명을 다음과 같이 설정합니다.
# application-dev.yaml
spring:
profiles:
active: dev
# application-prod.yaml
spring:
profiles:
active: prod
여기까지 진행하셨다면 SpringBoot에서 할 일은 끝났습니다. 😎
자! 그럼 Docker 컨테이너를 개발환경별로 배포하기 위해 프로젝트 최상위 디렉토리에 Dockerfile을 생성합시다.
4. Dockerfile에 Multi-Stage Build를 사용하는 다음 코드를 작성합니다.
FROM adoptopenjdk:8-jdk-hotspot AS builder # 베이스 이미지 + 이미지 별칭
COPY gradlew . # gradlew 복사
COPY gradle gradle # gradle 복사
COPY build.gradle . # build.gradle 복사
COPY settings.gradle . # settings.gradle 복사
COPY src src # 웹 어플리케이션 소스 복사
RUN chmod +x ./gradlew # gradlew 실행권한 부여
RUN ./gradlew bootJar # gradlew를 사용하여 실행 가능한 jar 파일 생성
FROM adoptopenjdk:8-jdk-hotspot # 베이스 이미지
COPY --from=builder build/libs/*.jar app.jar # builder 이미지에서 build/libs/*.jar 파일을 app.jar로 복사
EXPOSE 8080 # 컨테이너 Port 노출
ENTRYPOINT ["java","-jar","/app.jar"] # jar 파일 실행
5. 작성한 도커파일을 빌드하고 실행해봅시다.
# Dockerfile 이미지 빌드
$ docker build -t deploy-test:0.0.1 .
# Docker 컨테이너 실행
$ docker run -d -p 8080:8080 deploy-test:0.0.1
6. http://localhost:8080으로 접속하여 다음 페이지가 출력되면 정상입니다.
(profiles를 명시하지 않았기 때문에 기본적으로 application.yaml 설정 파일을 읽습니다.)
7. SampleController와 개발환경별 변수(sample.value)를 다르게하여 로컬에서 실행해봅니다.
// SampleController.java
@RestController
@RequestMapping("/sample")
public class SampleController {
@Value("${sample.value}")
private String sample;
@GetMapping
private String getSample() {
return sample;
}
}
# application.yaml
sample:
value: default
# application-dev.yaml
spring:
profiles:
active: dev
sample:
value: dev
# application-prod.yaml
spring:
profiles:
active: prod
sample:
value: prod
>> 다음 명령어를 사용하면 환경변수에 따라 application-{profile}.yaml 파일이 읽히는 것을 확인할 수 있습니다.
(http://localhost:8080/sample 페이지에서 default가 찍히는 것을 확인합니다.)
# 실행가능한 jar 파일 빌드
$ ./gradlew bootJar
# jar 파일 실행시 application-dev.yaml 파일을 읽도록 한다.
$ java -Dspring.profiles.active=dev -jar build/libs/*.jar
[2021.03.21 updated]
2.4.x 이후부터 기존 spring.profiles.active가 deprecated 되었습니다.
기존 spring.profiles.active 를 사용하여 jar 파일 실행시 다음에러가 발생하는 것을 확인했습니다.
Property 'spring.profiles.active' imported from location 'class path resource [application-dev.yml]' is invalid in a profile specific resource ...
spring.config.active.on-profile로 변경하면 정상동작하니, SpringBoot 2.4.x 버전은 다음과 같이 변경해주세요.
(config 파일 관련해서 한 번 정리해야겠네요 ㅠ)
# application-dev.yaml
spring:
config:
activate:
on-profile: dev
sample:
value: dev
---
# application-prod.yaml
spring:
profiles:
active: prod
sample:
value: prod
8. 위와 같은 작업을 Dockerfile에서는 --build-arg 옵션을 사용하여 가능합니다.
>> 우선 Dockerfile이 argument를 받아서 profile을 설정할 수 있도록 다음과 같이 변경합니다.
FROM adoptopenjdk:8-jdk-hotspot AS builder
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
COPY src src
RUN chmod +x ./gradlew
RUN ./gradlew bootJar
FROM adoptopenjdk:8-jdk-hotspot
COPY --from=builder build/libs/*.jar app.jar
# ENVIRONMENT라는 이름의 argument를 받을 수 있도록 설정
ARG ENVIRONMENT
# argument로 받은 ENVIRONMENT 값을 SPRING_PROFILES_ACTIVE에 적용
ENV SPRING_PROFILES_ACTIVE=${ENVIRONMENT}
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
>> argument를 받을 설정이 완료되었으면 이미지를 다시 빌드하고 컨테이너를 실행합니다.
(http://localhost:8080/sample 페이지에서 dev가 찍히는 것을 확인합니다.)
# ENVIRONMENT argument를 넘겨서 이미지 빌드
$ docker build --build-arg ENVIRONMENT=dev -t deploy-dev:0.0.1 .
# 컨테이너 실행
$ docker run -d -p 8080:8080 deploy-dev:0.0.1
이로써 SpringBoot에서 Profiles를 활용하여 개발환경을 구분하고,
Dockerfile에서 원하는 환경으로 이미지를 빌드하는 방법에 대해 알아보았습니다. 🥰
참고
https://wfreud.tistory.com/277
https://blusky10.tistory.com/404
https://docs.docker.com/develop/develop-images/multistage-build/
'Server > Spring' 카테고리의 다른 글
[Spring] 그라파나와 로키로 애플리케이션 로그 조회하기 (0) | 2023.04.22 |
---|---|
[Spring] 그라파나와 프로메테우스로 애플리케이션 모니터링하기 (0) | 2023.04.09 |
[Spring] EventListener vs TransactionalEventListener (0) | 2023.03.08 |
[Spring] MyBatis API 개발 예제 (0) | 2020.09.27 |
[Spring] MyBatis 데이터베이스 연동 (0) | 2020.09.26 |