반응형
기존 Dockfile을 통해 도커 이미지를 빌드하고 푸쉬하는 방식에서 Gradle 플러그인 Jib을 통해 빌드 시간을 단축하고자 빌드 방식을 변경해 보았습니다. Jib을 통해 빌드된 이미지를 실행하면서 겪은 시행착오를 기록하고자 합니다.
트러블 슈팅
문제 상황
Error: Unable to access jarfile app.jar
기존 Dockerfile을 통해 빌드와 이미지를 생성하는 방식에서 JIB 빌드 방식으로 변경하여 이미지를 생성했습니다.
JIB으로 생성한 이미지를 Run 했을 때, 위와 같은 오류가 발생하여 올바르게 Spring Server를 실행시킬 수 없는 오류가 있었습니다.
logs를 찍어봐도 별다른 오류가 없고 app.jar 파일에 접근할 수 없다는 에러 메시지만 있어 당황스러웠습니다.
또한, 인터넷에 나와 같은 문제를 겪는 사람이 없어서 JIB 빌드 방식이 어떤 흐름으로 진행되는지 파악해야 했습니다.
문제 분석
- JIB 방식은 Docker 이미지를 빌드할 때, JAR 파일을 직접 생성하지 않고 Gradle 빌드 과정에서 생성된 JAR 파일을 Docker 이미지에 포함시켜 컨테이너를 실행시키는 흐름입니다.
- 저는 처음에 “docker exec -it “도커 컨테이너ID” /bash” 로 실행한 컨테이너에 접속하여 파일 정보를 확인했습니다.
확인해 본 결과, (1) ‘루트 디렉터리’에 jib 구문에 설정한 app.jar 파일이 존재하지 않고, build/libs라는 디렉터리도 존재하지 않는 점을 확인했습니다. (2) libs 디렉터리에 여러 레이어의 빌드된 jar 파일이 존재하는 것을 확인하고 어떤 형태로 Dokcer 이미지에 JAR 파일이 포함되는지 깨달았습니다.
- 저는 처음에 “docker exec -it “도커 컨테이너ID” /bash” 로 실행한 컨테이너에 접속하여 파일 정보를 확인했습니다.
문제해결
Before - 처음 작성한 코드
jib {
from {
image = 'eclipse-temurin:17-jre'
}
to {
image = '<도커 계정>/<도커 레포지토리명>/<도커 이미지명>'
tags = [project.findProperty('jib.to.tags') ?: 'latest']
}
container {
entrypoint = ['java', '-Dspring profiles.active=prod', '-jar', 'app.jar']
ports = ['8080']
jvmFlags = ['-Xms512m', '-Xmx512m']
environment = [SPRING_OUTPUT_ANSI_ENABLED: "ALWAYS"]
labels = [Iversion: project.version, name: project.name, group: project.group]
format = 'Docker'
}
extraDirectories {
paths {
path {
from = file('build/libs')
}
}
}
}
After - 해결한 코드
jib {
from {
image = 'eclipse-temurin:17-jre'
}
to {
image = '<도커 계정>/<도커 레포지토리명>/<도커 이미지명>'
tags = [project.findProperty('jib.to.tags') ?: 'latest']
}
container {
ports = ['8080']
jvmFlags = ['-Xms512m', '-Xmx512m', '-Dspring.profiles.active=prod']
environment = [SPRING_OUTPUT_ANSI_ENABLED: "ALWAYS"]
labels = [Iversion: project.version, name: project.name, group: project.group]
format = 'Docker'
}
}
Github Actions .yml
- name: Build and push Docker image
run: |
./gradlew jib -x test \\
-Djib.to.tags=${{ github.sha }} \\
-Djib.to.auth.username=${{ secrets.KAKAO_ACCESS_ID }} \\
-Djib.to.auth.password=${{ secrets.KAKAO_ACCESS_SECRET }}
- ./gradlew jib : 해당 애플리케이션을 JIB 방식으로 빌드한다.
- -x test : 테스트 코드 부분을 제거한 채 빌드한다.
- -Djib.to.tags : 생성할 이미지의 태그 값을 전달합니다. github.sha를 통해 깃허브 커밋 번호를 사용했습니다.
- -Djib.to.auth.username(password) : 도커 레지스트리에 해당하는 정보를 작성합니다.
배운 점 및 깨달은 점
- JIB 방식으로 Docker 이미지를 빌드할 때, JAR 파일을 직접 생성하지 않기 때문에 JAR 파일이 실제로 파일 시스템에 존재하지 않는다. 대신, JIB은 Gradle 빌드 과정에서 생성된 JAR 파일을 Docker 이미지에 포함시켜 컨테이너를 실행한다.
- entrypoint로 jar을 실행할 필요가 없어 해당 코드를 지우고, profiles.active를 jvmFlags에서 전달한다.
- extraDirections 부분에서 가져올 JAR 파일이 없으므로 해당 코드를 지운다. (JIB 방식으로 빌드하면 관련 JAR 파일이 이미지에 포함된다.)
반응형