티스토리 뷰

반응형

스프링 부트를 도커 이미지로 만드는 작업(dockerize)을 github, travis-ci, dockerhub를 이용하여 자동화 해보았다. 각 서비스에는 가입을 하였고, travis-ci와 github을 연결해두었다.

참고 링크

1. 프로젝트 만들기

intellij를 이용하여 프로젝트를 만들었다. gradle을 사용하여 라이브러리 의존성 관리를 했다. gradle은 따로 설치하지 않고 gradle wrapper(./gradlew)를 사용했다. 그리고 java나 kotlin이 아닌 groovy 언어를 사용했다. 그 이유는 함수형 사고라는 책을 보고 groovy라는 언어가 개인적으로 참으로 편리하다고 생각했기 때문이다.

그루비로 간단하게 컨트롤러를 작성한다.

package vw.demo.helloworld

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/hello")
class HelloworldController {

    @GetMapping
    String hello(String name) {
        return "Hello, ${name? name: 'world'}!"ㅁ
    }
}

참고!

코드를 간결하게 하기 위해서 String hello(String name = "world") 이렇게 파라미터에 default value를 줄 수 있다. 그런데 @GetMapping 같이 RequestMapping 어노테이션이 붙은 메서드의 파라미터에 default value를 주면 java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'helloworldController' method 이런 에러가 난다. 왜냐하면 defalut value가 컴파일 되면 아래처럼 두개의 메서드로 나눠지기 때문이다. 조심하시길.

@GetMapping
String hello(String name = "world") {
    return "Hello, ${name}!"
}
@GetMapping
public String hello(String name) {
    CallSite[] var2 = $getCallSiteArray();
    return (String)ShortTypeHandling.castToString(new GStringImpl(new Object[]{name}, new String[]{"Hello, ", "!"}));
}

@GetMapping
public String hello() {
    CallSite[] var1 = $getCallSiteArray();
    return !__$stMC && !BytecodeInterface8.disabledStandardMetaClass() ? this.hello((String)"world") : this.hello((String)"world");
}

Dockerfile 만들기

기존에 처음 스프링 부트로 도커이미지를 만들었을 때는 빌드시에 코드를 모두 도커 이미지로 옮기고 도커이미지 내에서 빌드하고 실행했다. jar나 war를 만들지도 않고 그냥 스프링부트의 메이븐 플러그인을 사용해서 mvn spring-boot:run을 실행했다. 그랬더니 단점이 매번 도커파일이 빌드될 때 라이브러리를 다운로드하고 용량도 매우 커졌다.

그랬는데 이번 spring boot with docker 공식문서를 보니 jar로 빌드한 다음에 해당 jar만 도커 이미지에 넣고 빌드하는 것이었다. 그렇게 되면 용량도 가볍고 빌드 서버에 있는 ~/.m2 디렉토리에 라이브러리들이 캐싱될테니 속도도 빨라지는 것이다. 그래서 나도 이렇게 하기로 했다.

FROM openjdk:8-jdk-alpine
VOLUME /tmp
RUN echo ${JAR_FILE}
ARG JAR_FILE
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]

이 도커파일은 도커를 빌드할때 --build-arg JAR_FILE=jarfile_path/app.jar 이처럼 옵션을 작성해야한다. 옵션 없이도 빌드가 성공한다. 그러나 옵션이 없을 경우에는 도커를 실행할 때 에러가 난다. 조심해야한다.

(-Djava.security.egd 옵션에 대한 설명은 http://lng1982.tistory.com/261 이 링크를 참고)

travis 설정

travis를 github과 연동을 하고 repository를 추가하면 그냥 설정은 끝이다. 뭐가 더 있겠지만은 딱히 필요가 없어서 건드리지 않았다.

이제 부터 해야할 일은 아래 두가지 이다.

1. .travis.yml 코드 작성

travis는 소스가 푸시가 되면 .travis.yml 코드를 가지고 빌드를 진행한다.

language: java
jdk: oraclejdk8

sudo: required

cache:
  directories:
  - .autoconf
  - $HOME/.m2

services:
  - docker

script:
  # BUILD
  - ./gradlew build

  # GET NAME
  - PRJ_GROUP=$(gradle properties -q | grep "group:" | awk '{print $2}')
  - PRJ_NAME=$(gradle properties -q | grep "name:" | awk '{print $2}')
  - PRJ_VERSION=$(gradle properties -q | grep "version:" | awk '{print $2}')

  - echo "## PROJECT_GROUP - ${PRJ_GROUP}"
  - echo "## PROJECT_NAME - ${PRJ_NAME}"
  - echo "## PROJECT_VERSION - ${PRJ_VERSION}"

  - PRJ_JAR=${PRJ_NAME}-${PRJ_VERSION}.jar

  # DOCKER BUILD
  - docker build -t ${PRJ_GROUP}.${PRJ_NAME}:latest --build-arg JAR_FILE=build/libs/${PRJ_JAR} ./

  # PUSH TO DOCKER HUB
  - docker login -u ${DOCKER_USER} -p ${DOCKER_PASS}
  - docker tag vw.demo.helloworld:latest voyagerwoo/vw.demo.helloworld:latest
  - docker tag vw.demo.helloworld:latest voyagerwoo/vw.demo.helloworld:${TRAVIS_JOB_NUMBER}

  - docker push voyagerwoo/vw.demo.helloworld:latest
  - docker push voyagerwoo/vw.demo.helloworld:${TRAVIS_JOB_NUMBER}

2. 환경변수 설정

우선 오른쪽 상단에 햄버거 버튼을 누르고 그다음 settings 버튼을 누른다. 그 다음 여기에서 필요한 환경변수를 넣어준다. 여기에 기입하고 Add 버튼을 누르게 되면 자동으로 암호화 되서 저장이 된다. 나 같은 경우는 docker hub에 로그인 하기 위한 환경변수들을 추가했다.

정리

이렇게 github, travis, dockerhub를 이용하여 스프링 부트 도커 이미지 만들기 자동화를 했다.

세 도구 모두 퍼블릭으로 사용할 경우 무료이다.

반응형
댓글
댓글쓰기 폼