Dockerfile에서 RUN, CMD, ENTRYPOINT는 Shell 형식과 Exec 형식 두 가지로 작성할 수 있다.
Shell 형식은 우리가 터미널에서 명령어를 입력하듯 작성하는 방식이며, 내부적으로 /bin/sh -c를 통해 실행된다.
반면 Exec 형식은 JSON 배열로 작성하며 쉘을 거치지 않고 프로그램을 직접 실행한다.
이 차이로 인해 가장 크게 달라지는 부분이 바로 “셸 프로세싱”, 특히 환경 변수 치환이다.
Shell 형식은 자동으로 환경 변수 치환이 되지만, Exec 형식은 그렇지 않다. 필요하다면 sh -c를 명시적으로 사용해야 한다.
1. Shell 형식: 터미널처럼 작성하는 방식
RUN npm ci && npm run build
특징:
- 터미널 명령어처럼 그대로 작성
- 내부적으로 /bin/sh -c를 거쳐 실행
- &&, |, $PORT 같은 셸 문법 사용 가능
- 환경 변수 치환 자동 동작
실제 내부 동작은 이렇게 됩니다:
/bin/sh(통영사 경로) -c(실행옵션) "npm ci && npm run build"(해석되는 명령어)
비유하면,
통역사(sh)에게 문장을 던져주고 해석해서 실행시키는 구조
2. Exec 형식: JSON 배열 방식
ENTRYPOINT ["npm", "run", "start"]
- 쉘을 거치지 않음
- 각 요소가 명확히 분리됨
- 큰따옴표만 사용 (JSON 규칙)
- 환경 변수 치환 자동으로 안 됨
실행 구조는:
npm run start
즉,
통역사 없이 직접 프로그램에게 말하는 구조
3. 가장 중요한 차이: 셸 프로세싱
셸 프로세싱이란:
셸이 명령어를 해석하면서 처리하는 과정
대표적인 예가 환경 변수 치환입니다.
export PORT=3000
echo $PORT
→ 3000 출력
Shell 형식은 이 과정이 자동으로 동작합니다.
4. Exec 형식에서 환경 변수 치환이 안 되는 이유
예를 들어:
FROM ubuntu
ENV MY_NAME=codeit
ENTRYPOINT ["echo", "My name is ${MY_NAME}"]
출력 결과:
My name is ${MY_NAME}
왜냐하면:
- 쉘이 없기 때문
- ${MY_NAME}를 해석할 주체가 없음
Exec 형식은 단순히 문자열을 전달할 뿐입니다.
5. Exec 형식에서 셸 프로세싱을 쓰는 방법
ENTRYPOINT ["sh", "-c", "echo \"My name is ${MY_NAME}\""]
이 구조는:
즉,
- Exec 형식 유지
- 내부에서 명시적으로 쉘 실행
- 환경 변수 치환 가능
필요하다면 직접 쉘을 호출하면 됩니다.
6. 왜 일반적으로 ENTRYPOINT는 Exec 형식을 사용할까?
이유는 명확합니다.
- 신호 전달이 정확함 (PID 1 문제 해결)
- 예측 가능한 동작
- 불필요한 쉘 개입 제거
다만, 환경 변수 치환이 필요할 경우 sh -c를 활용합니다.
7. 정리
- Shell 형식 → /bin/sh -c를 통해 실행됨
- Exec 형식 → 쉘 없이 직접 실행
- 환경 변수 치환은 Shell 형식에서 자동 동작
- Exec 형식에서 필요하면 sh -c를 명시적으로 사용
Shell 형식은 셸이 해석해 실행하고, Exec 형식은 셸 없이 직접 실행되며 환경 변수 치환 여부가 가장 큰 차이입니다.
'컨테이너·워크플로우 자동화 > DocKer 기본 및 활용' 카테고리의 다른 글
| Dockerfile ENV vs ARG: 변수의 실행 시점과 생명주기 차이 (0) | 2026.02.18 |
|---|---|
| Dockerfile RUN vs CMD vs ENTRYPOINT: 실행 시점과 역할의 차이 (0) | 2026.02.18 |
| Docker Compose depends_on의 동작 원리와 한계 (0) | 2026.02.18 |
| Docker Compose 구성 이해하기 (0) | 2026.02.18 |
| COPY(명령어)에서 / 유무에 따른 디렉토리 복사 차이 (0) | 2026.02.17 |