스프링 부트의 공식 사이트 가이드에서 스프링 부트와 Docker 를 연동하기 위해 다음과 같은 Dockerfile 포맷을 올려놓았습니다.
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
https://spring.io/guides/gs/spring-boot-docker/
위의 Dockerfile을 스프링 부트의 기본 디렉토리에 저장한 후 Maven 의 경우
docker build -t springio/gs-spring-boot-docker
명령어를 입력하고, Gradle의 경우
$ docker build --build-args JAR_FILE=build/libs/*.jar -t springio/gs-spring-boot-docker .
명령어를 입력하여 도커 이미지를 빌드합니다.
이번 글로 위의 Dockerfile 에서 사용되는 명령어들과 docker build 명령어를 알아보려고 합니다.
우선 Dockerfile 이 무엇인지 알아보겠습니다.
Dockerfile은 나만의 도커 이미지를 만들기 위해 사용되는 파일입니다.
우리가 만든 스프링 부트와 같은 웹 어플리케이션은 이미 도커 이미지들이 저장되어 있는 DockerHub에 등록되어 있지 않아서 Docker pull
명령어로 이미지를 받아올 수 없습니다.
그래서 이미지를 직접 만들어줘야하는데, 이미지를 어떻게 만들건지 정의해놓은 파일이 바로 Dockerfile 입니다.
Dockerfile 의 내부는 이미지를 만들기 위해 사용되는 명령어들로 구성되어 있고, 순서대로 실행되어 이미지를 만들게 됩니다. 따라서 이 Dockerfile 명령어 들을 알게되면 이미지가 어떻게 만들어 졌는지 이해할 수 있는 장점이 있습니다.
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
이제 스프링부트 가이드에 있는 Dockerfile 을 명령어 단위로 분석하려고 합니다.
Dockerfile 로 어떤 이미지를 만드려면 기반이 되는 이미지 레이어가 필요로 합니다.
FROM <이미지 이름>:<태그>
형식으로 작성하여 기반으로 하는 이미지를 설정할 수 있습니다. 예를 들어 FROM ubuntu:14.04
우리는 자바 기반의 스프링 부트 어플리케이션을 실행해야 하기 때문에 자바 이미지를 기반으로 이미지를 만들어야 합니다. 따라서 FROM openjdk:8-jdk-alpine
명렁어는 '이 이미지는 알파인 리눅스에 사용되는 OpenJDK 8버전을 기반으로 만듭니다'라고 설정합니다.
Docker 에서 컨테이너를 삭제할 때 컨테이너 내부의 데이터가 삭제되는데, VOLUME 명령어를 사용할 경우 컨테이너 외부와 컨테이너 내부를 연결시켜 저장된 데이터의 수명과 데이터를 생성한 컨테이너의 수명을 분리할 수 있습니다.
디렉토리 하나를 사용할 경우 VOLUME <컨테이너 디렉토리>
, 여러 디렉토리를 설정할 경우 VOLUME ["컨테이너 디렉토리1", "컨테이너 디렉토리2"]
와 같이 사용할 수 있습니다.
VOLUME /tmp
로 설정할 경우 컨테이너 내부의 /tmp
디렉토리가 호스트의 /var/lib/docker/volumes/${volume_name}/_data
에 마운트 됩니다. (볼륨 이름은 임의의 해쉬값으로 생성)
mac이나 윈도우의 경우
/var/lib/docker/volumes
디렉토리가 없는데, 이는 mac과 윈도우의 경우 docker 를 바로 실행할 수 없어서 xhyve라는 가상머신을 하나 띄운 후 도커를 실행하기 때문에,/var/lib/docker/volumes
디렉토리가 가상머신 내에 감춰져 있기 때문입니다.
참고 : https://joont92.github.io/docker/volume-container-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0/
ARG 명령어는 build 시에 사용되는 변수입니다.
ARG 명령어는 ARG <변수명>
또는 ARG <변수 명=값>
형태로 설정해줄 수 있고, docker build 명령어로 사용할 경우 --build-arg 옵션으로 오버라이딩 할 수 있습니다.
ARG JAR_FILE=target/*.jar
명령어는 'target/*.jar 이라는 값을 가진 JAR_FILE 변수를 사용하겠다'라는 것을 나타냅니다.
target/*.jar 는 Maven 빌드 환경에서 빌드된 JAR 파일이 저장되는 디렉토리 입니다.
COPY 명령어를 사용하면 파일이나 디렉토리를 복사하여 컨테이너 디렉토리에 추가해줍니다.
COPY <복사할 경로> <이미지에 추가할 경로>
형식으로 사용됩니다.
COPY ${JAR_FILE} app.jar
명령어는 'JAR_FILE 변수에 저장된 JAR 파일을 컨테이너의 app.jar 경로에 추가한다' 라는 의미입니다.
ENTRYPOINT 는 해당 컨테이너가 시작되었을 때 수행할 실행 명령을 정의하는 명령어입니다. Dockerfile 파일 내에서 1번만 정의가 가능합니다.
ENTRYPOINT <실행할 명령어>
혹은 ENTRYPOINT ["실행 파일", "매개 변수 1", "매개 변수 2", ...]
형식으로 사용할 수 있습니다.
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
명령어를 실행하면 '컨테이너가 시작되면 java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
쉘 명령어를 실행' 합니다.
자바에서 DB 연결 시에 JDBC Driver 에서 암호화 작업을 하는데, 이 과정에서 난수 발생이 일어납니다.
자바는 기본적으로 /dev/random 을 사용하는데, /dev/random 을 사용할 경우 랜덤 값을 만들어 낼 때 엔트로피가 충분해질때까지 Blocking 이 있기 때문에 간헐적으로 지연되어서 에러가 발생할 수 있습니다. 이 과정에서 /dev/random 대신 /dev/urandom 을 사용하면 현재 존재하는 엔트로피로만 사용하기 때문에 Blocking 을 하지 않아 지연 현상이 발생하지 않습니다.
따라서 Djava.security.egd=file:/dev/./urandom 을 매개 변수로 입력해줍니다.
참고 : http://blog.naver.com/PostView.nhn?blogId=hanccii&logNo=220725686080
https://waspro.tistory.com/254
$ docker build --build-args JAR_FILE=build/libs/*.jar -t springio/gs-spring-boot-docker .
도커 이미지를 빌드하는 명령어는 다음과 같습니다.
docker build [OPTION] <Dockerfile 이 있는 PATH>
현재 도커 이미지 빌드 명령어를 실행하는 디렉토리에 Dockerfile 이 있는 경우 경로로 "." 를 입력하면 됩니다.
이전 Dockerfile 파일의 ARG 명령어로 JAR_FILE 선언했습니다.
Dockerfile 내의 JAR_FILE 경로가 Maven 빌드 환경의 경로이므로 Gradle 빌드 환경에서 JAR 파일 경로를 입력해줘야합니다.
build/libs/*.jar
을 입력하여 Dockerfile 내에서 JAR_FILE 변수의 값을 오버라이딩해주는 역할을 합니다.
생성될 도커 이미지의 이름을 지정해주는 옵션입니다.
빌드를 하면 springio/gs-spring-boot-docker
라는 이름의 이미지를 생성해줍니다.
참고
도커 명령어
http://longbe00.blogspot.com/2015/03/dockerfile.html
https://khj93.tistory.com/entry/Docker-Docker-File-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0-%EB%AA%85%EB%A0%B9%EC%96%B4
https://blog.naver.com/PostView.nhn?blogId=alice_k106&logNo=220646382977&parentCategoryNo=7&categoryNo=&viewDate=&isShowPopularPosts=true&from=search