[LG CNS AM Inspire Camp 1기] Docker (4) - Dockerfile 명령어 간단 정리

정성엽·2025년 2월 14일
0

LG CNS AM Inspire 1기

목록 보기
50/53

INTRO

이전 포스팅에서는 Dockerfile을 작성할 때 이미지 크기를 최적화하는 방법에 대해 알아보았다.

이번에는 Dockerfile에서 자주 사용되는 RUN , CMD , ENTRYPOINT 등의 지시어들의 차이점과 각각의 사용 방법에 대해 자세히 알아보도록 하자 👀


1. RUN

RUN 은 이미지를 빌드할 때 실행하는 명령어이다.

지금까지 Dockerfile을 생성하면서 많이 봤겠지만, 주로 패키지 설치나 파일 생성 등 이미지를 구성하는데 필요한 커맨드를 실행할 때 사용한다.

이전 포스팅에서도 정리했지만, 도커를 효율적으로 사용하기 위해서는 RUN 명령어를 여러개 사용하여 이미지를 구성하게 되면 레이어가 쌓이게되어 불필요하게 이미지 사이즈가 증가할 수 있다.

따라서, / 으로 개행을 사용하여 개발자가 읽기 쉽도록 구성하고, && 를 사용하여 여러 명령어를 한번에 사용하도록 하자!

(이전에 정리했으니 간단하게 정리하고 넘어가겠다!)


2. CMD vs ENTRYPOINT

CMDENTRYPOINT 는 컨테이너가 시작될 때 실행되는 명령어를 지정하는데 사용된다.

하지만, 여기에는 중요한 차이점이 있다.

우선 간단하게 CMD 명령어를 사용하여 컨테이너를 띄워보자

Sample Code

FROM ubuntu
CMD ["echo", "hello"]

Result View

hello가 정상적으로 나오는 모습을 볼 수 있다.

💡 CMD 사용

그렇다면 컨테이너 실행 시점에 특정 명령어를 추가하면 어떻게 될까?

우선 Dockerfile은 기존과 동일하게 사용하고, 커맨드만 변경해보자

◉ 커맨드 - 추가 명령어 실행
docker run cmd_test echo world


Result View

결과를 살펴보면 Dockerfile을 생성하는 시점에 정의해둔 "hello"는 사라지고 world만 출력된다.

즉, CMD 명령어를 사용하면 새로운 명령어가 들어올 경우, 기존 명령어를 덮어씌우는 특징이 있다.

💡 ENTRYPOINT 사용

다음으로 ENTRYPOINT 명령어를 사용하여 Dockerfile을 구성해보자

Sample Code

FROM ubuntu
ENTRYPOINT ["echo", "hello"]

Result View

보다시피 hello echo world가 출력되는 모습을 볼 수 있다.

그 이유는 ENTRYPOINT 의 경우, 추가되는 내용을 argument로 인식한다.

즉, echo world 라는 명령어를 컨테이너 실행 시점에 추가했다면 ENTRYPOINT ["echo", "hello", "echo", "world"] 로 이해하기 때문에 "hello echo world"가 출력되는 것이다.

따라서, ENTRYPOINT 는 Dockerfile로 지정한 명령어가 사라지지 않고 뒤에 추가로 들어온다고 생각하면 된다.

💡 CMD vs ENTRYPOINT

그렇다면 CMDENTRYPOINT 는 각각 언제 사용하는게 맞을까?

CMDENTRYPOINT 는 각각 다른 상황에서 사용하는 것이 좋다!

CMD 는 컨테이너 실행 시 명령어를 유연하게 변경해야 하는 경우에 사용한다.

예를 들어 개발 환경과 운영 환경에서 다른 명령어를 실행해야 할 때 유용할 것이다.

반면, ENTRYPOINT 는 컨테이너가 항상 동일한 명령어로 시작되어야 할 때 사용하는 것이 적합합다. (명령어가 불변하기 때문)

웹 서버나 데이터베이스 서버처럼 실행 명령어가 고정적인 경우에 적합할 것이다.

💡 exec form vs shell form

여러 포스팅에서 필자가 작성한 Dockerfile을 살펴보면 명령어를 2가지 방식으로 사용하는 모습을 볼 수 있다.

Sample Code - exec form

CMD ["go", "run", "/goapp/main.go"]

Sample Code - shell form

CMD go run /goapp/main.go

이처럼 Dockerfile에서 명령어를 작성하는 방법이 두가지가 있다.

이 두가지 방식 중에서는 exec form을 사용하는 것이 권장된다.

그 이유는 shell form의 경우 컨테이너의 쉘을 사용하게 되는데, 베이스 이미지에 따라 명령어의 동작이 달라질 수 있기 때문이다.

반면, exec form은 쉘을 거치지 않고 직접 실행되기 때문에 베이스 이미지와 상관없이 일관된 동작을 보장한다.

다만 한 가지 단점이 있다면 쉘의 기능을 사용할 수 없다는 점이다.
예를 들어 CMD ["echo", "$HOME"] 처럼 환경 변수를 사용하는 명령은 exec form에서 직접 사용할 수 없다는 것이다.

물론, 이런 경우에는 CMD ["/bin/bash", "-c", "echo $HOME"] 처럼 명시적으로 쉘을 실행하는 방식으로 우회할 수 있긴 하다.


3. COPY vs ADD

다음으로 COPYADD 명령어에 대해서 살펴보려고 한다.

두 지시어 모두 호스트의 파일을 컨테이너로 복사할 때 사용하지만, 세부적인 차이가 존재한다.

💡 COPY

COPY는 호스트의 로컬 파일만 이미지에 추가할 수 있다.

단순하고 직관적인 파일 복사 기능만 제공한다고 이해하면 된다.

지금까지 많이 사용했기 때문에 간단하게 예제 코드만 살펴보고 넘어가자

Sample Code

...
COPY hello.html /var/www/html/
COPY ./app .
...

💡 ADD

ADDCOPY 보다 더 많은 기능을 제공하는데, 호스트의 로컬 파일을 넘어서 외부 URL을 사용하여 파일을 다운로드할 수 있다.

또한, tar 파일을 자동으로 압축 해제하면서 복사를 수행할 수 있다.

예시 코드를 살펴보자

Sample Code

ADD https://example.com/file.tar.gz /app/  
ADD app.tar.gz /app/                       

하지만 실제로 대부분의 경우 COPY 를 사용하는 것이 권장된다.

왜냐하면, 동작이 예측 가능하고 명확하기 떄문이다.

또한, ADD 의 자동 압축 해제 기능이 때로는 의도치 않은 결과를 초래할 수 있다는 불확실성이 존재한다.

실제로 URL 다운로드는 RUN curl 또는 wget으로 직접 처리하는 것이 더 명시적이기 때문이다.

따라서, tar 압축 해제나 URL 다운로드가 필요한 특수한 경우에만 ADD 를 사용하는 것을 권장한다.


4. ENV

컨테이너 환경에서 환경변수는 매우 중요한 역할을 한다.

예를 들어 스프링부트 서버를 컨테이너로 올릴 때 DB 서버의 IP 주소나 포트와 같은 정보를 환경변수로 관리하면 유연하게 설정을 변경할 수 있기 때문이다.

이때, Dockerfile에서 ENV 명령어를 사용하면 환경 변수를 세팅할 수 있는데 우선 코드를 살펴보자

Sample Code

FROM ubuntu
ENV WORKSPACE=/myapp
RUN mkdir ${WORKSPACE}
WORKDIR ${WORKSPACE}
RUN touch ${WORKSPACE}/mytouchfile

Result View

컨테이너에서 WORKSPACE 환경변수를 확인해보면 /myapp으로 세팅된 모습을 볼 수 있다.

💡 환경변수 오버라이드

물론, 컨테이너 실행 시점에 환경변수를 변경할 수도 있다.

◉ 커맨드 - 환경 변수 오버라이드
docker container run -it -e WORKSPACE=/newapp env_test


-e : 환경 변수를 세팅할 때 사용하는 옵션이다.


Result View

여기서 주의깊게 봐야할 부분은 환경변수는 /newapp 이지만 가상 터미널로 접속한 WORKSPACE는 /myapp 임을 확인할 수 있다.

즉, 이런 차이가 발생하는 이유는 디렉토리 구조는 이미지를 빌드하는 시점에 생성되지만, 환경변수는 컨테이너 실행 시점에 적용되기 때문이다.

따라서, 만약 컨테이너를 생성한 이후 어떠한 작업을 수행한다면 현재 세팅된 환경변수인 /newapp 에서 작업이 수행된다.

이러한 특징을 이해하고 사용하는 것이 중요할 것이다!


OUTRO

이번 포스팅에서는 Dockerfile의 주요 지시어들인 CMDENTRYPOINT 의 차이, exec form과 shell form의 특징, 그리고 COPY / ADDENV 의 활용법에 대해 자세히 알아보았다.

특히 각 지시어들이 언제 사용되어야 하는지, 그리고 왜 그렇게 사용해야 하는지에 대해 정리해봤다.

실제로 exec form을 사용하는 것이 권장되는 이유나, 환경변수가 실제로 적용되는 시점의 차이 등은 이해하는 것은 실제 개발환경에서 중요한 부분이 될 것 같으니 공부해두자 👊

profile
코린이

0개의 댓글

관련 채용 정보