일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- aws
- Zeppelin
- 로그인
- gradle
- java
- ec2
- Mac
- 머신러닝
- 자동
- 간단
- SpringBoot
- fastcampus
- 예제
- EMR
- vue
- hive
- Docker
- spring
- Redis
- 젠킨스
- Jenkins
- 클러스터
- Cluster
- 레디스
- config
- Kafka
- redash
- 설정
- 자바
- login
- Today
- Total
코알못
[Docker] Docker 빌드를 위한 Jenkins 활용 - 도커 이미지 빌드 본문
이번 시간에는 docker 컨테이너 이미지 빌드 실습을 진행할 예정이며 아래 순서로 진행 해보자!
1. gradle 설치
2. gradle 프로젝트 생성
3. docker hub repository 생성
4. docker build & push
5. docker pull & run
6. 4번을 jib를 통해 진행후 5번 진행
실습 진행하기 앞서 gradle 프로젝트 생성시 만들어지는 파일에 대해 알아보도록 하며 아래와 같다.
구분 | 내용 |
build.gradle | 프로젝트 내 소스코드에 대한 라이브러리 의존성, 플러그인, 라이브러리 저장소 등을 설정 할 수 있는 빌드 스크립트 파일 |
settings.gradle | 빌드 대상 모듈의 구성 정보를 정의 하는 파일 (루트, 하위 모듈을 정의 하며 빌드 대상에서 하위 모듈을 제외할 수 있어 주로 멀티 모듈 프로젝트의 경우 사용된다) |
gradlew | 리눅스 또는 맥OS 용 gradle 실행 스크립트 파일 (따로 gradle을 설치 하지 않아도 해당 스크립트로 실행 가능) 내장 그래들인 gradlew(gradle wrapper)는 로컬 환경(java, gradle 설치 안되어 있거나 버전이 다름)에 상관없이 빌드 할 수 있도록 한다. |
gradlew.bat | 윈도우용 gradle 실행 스크립트 파일 |
gradle 디렉토리 | gradlew 를 실행 시키기 위한 wrapper 파일 |
추가로 실습 내용중 jib 라는것이 등장하는데 이는 구글에서 만든 오픈 소스로 Docker 설치 없이 컨테이너 빌드 할 수 있는 도구이며 gradle 설정을 통해 바로 컨테이너 배포 가능하다.
기존에는 dockerfile이 프로젝트에 있고 docker를 설치한뒤 docker 명령어를 통해 배포가 이뤄졌다면 해당 과정이 생략된 형태이다.
Jib 사용을 위해서는 아래와 같이 gradle 설정 파일에 플러그인을 정의하며
plugin{
...
id 'com.google.cloud.tools.jib' version '3.3.1'
}
어떻게 배포할건지에 대해 정의 한다.
jib {
from {
// 배포 대상
}
to {
// 배포 목적지
}
container {
// 컨테이너 설정
}
extraDirectories {
paths {
path {
// 배포 경로를 지정
}
}
}
}
이제 어느정도 개념을 알았다면 실습을 진행해보자!
이전 시간에 생성한 EC2 에서 진행하도록 한다.
apt 를 통해 gradle 설치시 버전 4가 설치되며 해당 버전은 제약 사항이 많기 때문에 저장소를 추가하여 버전 7을 설치한다.
아래와 같이 입력하여 저장소를 추가한다.
$ sudo apt -y install vim apt-transport-https dirmngr wget software-properties-common
$ sudo add-apt-repository ppa:cwchien/gradle
apt 를 업데이트 하고 gradle 을 설치한다.
$ sudo apt update
$ sudo apt install -y gradle
정상적으로 설치 되었는지 확인 하면 정상적으로 버전 7이 설치 되었다.
$ gradle -v
Welcome to Gradle 7.4.2!
Here are the highlights of this release:
- Aggregated test and JaCoCo reports
- Marking additional test source directories as tests in IntelliJ
- Support for Adoptium JDKs in Java toolchains
For more details see https://docs.gradle.org/7.4.2/release-notes.html
------------------------------------------------------------
Gradle 7.4.2
------------------------------------------------------------
Build time: 2022-03-31 15:25:29 UTC
Revision: 540473b8118064efcc264694cbcaa4b677f61041
Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 11.0.18 (Ubuntu 11.0.18+10-post-Ubuntu-0ubuntu122.04)
OS: Linux 5.15.0-1028-aws amd64
이제 gradle 프로젝트가 담길 디렉토리 하나 생성한다.
$ mkdir test
$ cd test
프로젝트를 생성 하기 위해 gradle 프로젝트 생성 명령어를 호출 한다.
$ gradle init --dsl=groovy --type=java-application --test-framework=junit --package=com.corin --project-name=docker-corin
Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no]
> Task :init
Get more help with your project: https://docs.gradle.org/7.4.2/samples/sample_building_java_applications.html
BUILD SUCCESSFUL in 4s
2 actionable tasks: 2 executed
gradle init 에 사용한 옵션은 아래와 같으며 참고 하도록 한다.
구분 | 내용 |
--dsl | 특정 분야의 최적화된 언어라는 뜻으로 gradle 빌드 정의 하기 위해 Groovy, Kotlin 언어를 사용할 수 있다. Groovy 의 경우 형식이 자유로워 개발자 마다 다른 코드로 작성이 가능하다. 예를 들어 아래와 같이 다양한 문법으로 표현 가능하다. dependencies { compile '', compile "", compile () } Kotlin의 경우 형식이 "" 로 정해져 있으며 이에 따른 장점은 자동 완성, 코드 통일성, 오류 코드 강조가 있다. |
--type | 생성할 프로젝트 유형 선택할 수 있으며 선택에 맞게 프로젝트가 구성 된다. java-application : 자바 어플리케이션 java-library : 자바 라이브러리용 groovy-application : 그루비 어플리케이션 groovy-library : 그루비 어플리케이션 pom : 이미 생성된 maven 프로젝트를 gradle 프로젝트로 마이그레이션 할 때 사용 |
--test-framework | 테스트에 사용할 프레임워크 정의 junit or TestNg |
--package | 패키지 경로 지정 |
--project-name | 프로젝트명 지정 |
디렉토리에 어떠 파일이 생성 되었는지 확인 한다.
$ ll
total 44
drwxrwxr-x 5 ubuntu ubuntu 4096 Mar 14 12:24 ./
drwxr-x--- 6 ubuntu ubuntu 4096 Mar 14 12:20 ../
-rw-rw-r-- 1 ubuntu ubuntu 154 Mar 14 12:24 .gitattributes
-rw-rw-r-- 1 ubuntu ubuntu 103 Mar 14 12:24 .gitignore
drwxrwxr-x 2 ubuntu ubuntu 4096 Mar 14 12:24 .gradle/
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 app/
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 gradle/
-rwxrwxr-x 1 ubuntu ubuntu 8070 Mar 14 12:24 gradlew*
-rw-rw-r-- 1 ubuntu ubuntu 2763 Mar 14 12:24 gradlew.bat
-rw-rw-r-- 1 ubuntu ubuntu 376 Mar 14 12:24 settings.gradle
$ cd app/
$ ll
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 ./
drwxrwxr-x 5 ubuntu ubuntu 4096 Mar 14 12:24 ../
-rw-rw-r-- 1 ubuntu ubuntu 854 Mar 14 12:24 build.gradle
drwxrwxr-x 4 ubuntu ubuntu 4096 Mar 14 12:24 src/
$ cd src/
$ ll
drwxrwxr-x 4 ubuntu ubuntu 4096 Mar 14 12:24 ./
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 ../
drwxrwxr-x 4 ubuntu ubuntu 4096 Mar 14 12:24 main/
drwxrwxr-x 4 ubuntu ubuntu 4096 Mar 14 12:24 test/
$ cd main/
$ ll
drwxrwxr-x 4 ubuntu ubuntu 4096 Mar 14 12:24 ./
drwxrwxr-x 4 ubuntu ubuntu 4096 Mar 14 12:24 ../
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 java/
drwxrwxr-x 2 ubuntu ubuntu 4096 Mar 14 12:24 resources/
$ cd java/
$ ll
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 ./
drwxrwxr-x 4 ubuntu ubuntu 4096 Mar 14 12:24 ../
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 com/
$ cd com/
$ ll
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 ./
drwxrwxr-x 3 ubuntu ubuntu 4096 Mar 14 12:24 ../
drwxrwxr-x 2 ubuntu ubuntu 4096 Mar 14 12:24 corin/
이렇게 프로젝트 직접 들어가서 프로젝트 구조를 확인 할 수도 있지만 쉽게 보기 위해 tree 를 설치 한다.
$ sudo apt install tree
설치가 완료 되었으니 구조를 확인 하면 정상적으로 구조가 생성 되었음을 알 수 있다.
$ tree
.
├── app
│ ├── build.gradle
│ └── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── corin
│ │ │ └── App.java
│ │ └── resources
│ └── test
│ ├── java
│ │ └── com
│ │ └── corin
│ │ └── AppTest.java
│ └── resources
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
14 directories, 8 files
이대로 사용하게 되면 java 메인 코드 실행하고 프로세스가 종료 되기 때문에 스프링 웹 의존성을 추가하여 웹 페이지를 만들자!
각각의 파일을 아래와 같이 수정한다.
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.1'
id 'io.spring.dependency-management' version '1.0.12.RELEASE'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:2.7.1'
testImplementation 'junit:junit:4.13.2'
}
repositories {
mavenCentral()
}
version = '0.0.1-SNAPSHOT'
description = 'test-docker-spring-boot'
group = 'com.corin'
java.sourceCompatibility = JavaVersion.VERSION_11
jar {
enabled = false
}
bootJar{
archiveFileName = 'app.jar'
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
App.java
package com.corin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
@SpringBootApplication
@RestController
public class App {
@GetMapping("/")
public String getGreeting() {
return "hello corin";
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
수정 완료 하였으면 gradle 빌드를 진행한다.
$ gradle clean build --info
BUILD SUCCESSFUL in 14s
7 actionable tasks: 7 executed
빌드가 완료 되면 실행 가능한 jar 파일은 '/app/build/libs' 경로에서 확인 가능하다.
$ cd app/build/libs
$ ls
drwxrwxr-x 2 ubuntu ubuntu 4096 Mar 14 13:00 ./
drwxrwxr-x 10 ubuntu ubuntu 4096 Mar 14 13:00 ../
-rw-rw-r-- 1 ubuntu ubuntu 954 Mar 14 13:00 app.jar
이제 도커 허브 계정을 생성하고 해당 계정에 로그인 한다. (생성하는것은 어렵지 않아 넘어 가도록 한다.)
로그인 하는 방법은 아래와 같다.
$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: [id 입력]
Password:
WARNING! Your password will be stored unencrypted in /home/ubuntu/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
이제 프로젝트 내에 아래와 같이 프로젝트에서 생성한 jar 파일을 실행하는 dockerfile 을 만든다.
FROM openjdk:11
RUN mkdir /app
WORKDIR /app
ADD ./app/build/libs/app.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
도커 파일 명령어의 의미는 [[Docker] Docker 빌드를 위한 Jenkins 활용 - 준비] 글을 참고한다.
이제 dockerfile을 아래와 같이 빌드한다.
$ docker build -t [dockerhub username]/corin:1.0 .
Sending build context to Docker daemon 6.272MB
Step 1/6 : FROM openjdk:11
11: Pulling from library/openjdk
001c52e26ad5: Extracting [====================================> ] 40.11MB/55MB
d9d4b9b6e964: Download complete
2068746827ec: Download complete
9daef329d350: Download complete
d85151f15b66: Download complete
66223a710990: Download complete
db38d58ec8ab: Downloading [==========================================> ] 173.7MB/202.1MB
Successfully built c1e68115d590
Successfully tagged [dockerhub username]/corin:1.0
이미지가 정상적으로 만들어졌는지 확인 한다.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[dockerhub username]/corin 1.0 c1e68115d590 About a minute ago 654MB
openjdk 11 47a932d998b7 7 months ago 654MB
이제 도커 이미지를 저장소에 올려보자!
$ docker push [dockerhub username]/corin:1.0
The push refers to repository [docker.io/[dockerhub username]/corin]
4aefcae3b0e6: Pushed
38ecac311777: Pushed
7b7f3078e1db: Mounted from library/openjdk
826c3ddbb29c: Mounted from library/openjdk
b626401ef603: Mounted from library/openjdk
9b55156abf26: Mounted from library/openjdk
293d5db30c9f: Mounted from library/openjdk
03127cdb479b: Mounted from library/openjdk
9c742cd6c7a5: Mounted from library/openjdk
1.0: digest: sha256:123 size: 2208
정상적으로 이미지가 저장소에 올라갔는지 확인 하면 정상적으로 올라간것을 볼 수 있고 버전 태그도 잘 적용 되었다.
정상적으로 올렸다면 pull 테스트를 위해 이미지를 제거 하고 pull 받아온다.
이미지 제거시 rmi 를 사용하며 이미지 ID는 일부만 적어도 제거 된다.
$ docker rmi [이미지 ID, 띄어쓰기로 구분하여 여러개 동시 제거 가능]
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
$ docker pull [dockerhub username]/corin:1.0
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[dockerhub username]/corin 1.0 c1e68115d590 14 minutes ago 654MB
도커 컨테이너를 띄운다.
$ docker run -d -p 8080:8080 [image id]
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
45b6fdbea0d8 b0 "java -jar app.jar" 4 seconds ago Up 2 seconds 0.0.0.0:8080->8080/tcp, :::8080->8080/tcp busy_gauss
정상적으로 떴는지 테스트 하면 정상적으로 결과가 나온다.
$ curl http://localhost:8080
hello corin
이제부터 jib 를 이용한 배포 실습을 진행할 예정이다.
jib를 이용하면 docker 설치, 이미지를 빌드, 저장소에 푸시 하는 작업을 gradle로 편리하게 처리 할 수 있다.
이를 이용하기 위해 아래 plugin에 jib 추가, jib 관련 설정을 추가 한다.
build.gradle
plugins{
...
id 'com.google.cloud.tools.jib' version '3.3.1'
}
...
jib {
from {
image = 'openjdk:11' // base image
}
to {
image = '<dockerhub user name>/corin' // image name
tags = ['1.1'] // tag
}
container {
entrypoint = ['java','-jar', 'app.jar'] // entrypoint
jvmFlags = ['-Xms512m', '-Xmx512m'] // java option > 현 메모리에 맞게 옵션 설정후 테스트 진행
ports = ['8080'] // expose
labels = [version:project.version, name:project.name, group:project.group] // label >> docker inspect 로 상세 정보 확인시 볼 수 있다.
creationTime = 'USE_CURRENT_TIMESTAMP'
format = 'Docker'
}
extraDirectories {
paths {
path {
from = file('build/libs')
}
}
}
}
이제 빌드 하고 jib 를 실행한다.
$ gradle clean build jib
이미지 리스트를 확인해보면 EC2 로컬에는 이미지가 생성되지 않은것을 볼 수 있으며
이를 통해 로컬에 설치된 도커를 사용하지 않고 gradle 에서 바로 이미지를 만들어 저장소에 배포하는것을 알 수 있다.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[dockerhub username]/corin 1.0 b040318baec9 31 minutes ago 672MB
이제 원격 저장소를 확인하면 1.1 태그의 이미지가 정상적으로 업로드 된것을 볼 수 있으며
EC2 로컬에 이미지를 받아서 컨테이너 실행한다.
$ docker pull [dockerhub username]/corin:1.1
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
[dockerhub username]/corin 1.1 ae558dafcfc6 11 minutes ago 689MB
[dockerhub username]/corin 1.0 b040318baec9 41 minutes ago 672MB
$ docker run -d -p 8060:8080 [image id]
컨테이너 테스트 해보면 정상인것을 확인 할 수 있다.
$ curl http://localhost:8060
hello corin
끝!
'ETC' 카테고리의 다른 글
[Docker] Docker 빌드를 위한 Jenkins 활용 - Jenkins 설치 (0) | 2023.03.18 |
---|---|
[Lambda] 라이브러리 버전 변경 (0) | 2023.03.16 |
[Docker] Docker 빌드를 위한 Jenkins 활용 - 준비 (0) | 2023.03.13 |
[Docker] Docker Compose 란? (0) | 2022.12.09 |
[Docker] 도커 이미지 경량화 전략 / 디버깅 (0) | 2022.11.27 |