우리네 장

[ Docker ] Dockerfile을 빌드와 실행으로 나눠보자 본문

배포 관리 도구/Docker

[ Docker ] Dockerfile을 빌드와 실행으로 나눠보자

qpmi1zm29 2023. 3. 9. 12:58

실행하고자 하는 실행 파일이 존재하는 경우, 그냥 COPY 명령어를 통해 파일을 컨테이너 내부로 옮겨 실행하면 되지만, 

실제 운영 환경에서 파이프라인을 통해 CI/CD를 구성할 때는 그 과정에서 빌드를 수행해 실행파일을 생성해줘야 한다.

 

이를 위해 Dockerfile 에서는 builder stage와 run stage를 구분지어 설정이 가능하다.

 

[ 예시 파일 - react app ]

FROM node:alpine as builder
WORKDIR "/usr/src/app/"
COPY package.json ./
RUN npm install
COPY ./ ./
CMD [ "node", "run" ,"build" ]

FROM nginx
COPY --from=builder /usr/src/app/build /usr/share/nginx/html                    --nginx가 참조하는 기본 디렉토리 설정, 수정 가능

 

as builder 현재 FROM부터 다음 FROM절까지 builder stage임을 명시해준다. 
--from=builder node build 후 결과물이 /usr/src/app/build 아래 생기는데, 해당 디렉토리에 존재하는 파일이 builder stage의 결과물임을 run stage에게 알려준다. 

 

 

[ 예시 파일 - gradle app ]

FROM eclipse-temurin:17-jdk-alpine as builder
COPY src src
COPY gradlew .
COPY gradle gradle
COPY build.gradle .
COPY settings.gradle .
RUN +x ./gradlew
RUN ./gradlew bootJar

FROM eclipse-temurin:17-jdk-alpine
COPY --from=builder build/libs/*.jar app.jar

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=dev","app.jar"]

빌드 툴에 따른 build stage의 build 명령어나 run stage의 실행 명령어들은 https://spring.io/guides/topicals/spring-boot-docker/ 를 참고한다.

 

 


 

Docker 명령어 - CMD vs ENTRYPOINT

 

docker inspect <container id> 명령어를 수행하면, 해당 컨테이너에 대한 정보들이 key : value 형태로 보여진다.

 

{ ....

  CMD : null,

  ENTRYPOINT : null 

   .....

 }

 

 

빌드 중 터미널 창에서 필요한 작업이 있을 경우 사용하는 RUN과 달리,

CMD와 ENTRYPOINT 는 컨테이너 실행 시에 실행할 명령어를 정의하는 부분으로 Dockerfile 하단에 주로 위치한다.

 

컨테이너의 메인 프로젝트는 주로 실행하는 명령어가 고정되어 있어 ENTRYPOINT의 사용이 권장된다. 

CMD는 다른 실행 명령어로 대체될 수 있다. 

ex. docker run <random image name> ls -al

위 명령어는 해당 이미지에 어떤 CMD가 있던 4번째 인자로 들어있던 ls -al로 대체되어 실행된다.

{ ....

  CMD : {"ls", "-al"},

  ENTRYPOINT : null 

   .....

 }

 

즉, 4번째 인자 부분이 CMD와 관여된 부분인 것을 알 수 있다.

 

 

보통 ENTRYPOINT와 CMD를 같이 사용하게 되는데, 이때 

ENTRYPOINT는 컨테이너 실행 시 실행할 명령어가 되고,

CMD는 ENTRYPOINT와 같이 사용될 때 인자를 담당하게 된다. 

 

Dockerfile에서 

ENTRYPOINT [ "sh", "/test.sh" ]

CMD [ "1" ]

 

로 사용하게 되면 default param은 file에 정의한 "1"이 되어 ENTRYPOINT의 명령어인 test.sh를 실행할 때 넘어갈 인수가 된다. 

{ ....

  CMD : {"1"},

  ENTRYPOINT : {"sh", "/test.sh"}

   .....

 }

 

컨테이너 실행 시에 넘어가는 인수를 다른 값으로 변경하고 싶을 때는,

docker run < random image id > 2 를 실행하면

{ ....

  CMD : {"2"},

  ENTRYPOINT : {"sh", "/test.sh"}

   .....

 }

로 바뀌어 실행되게 된다.