컨테이너 용어 사전
빌드exec form · shell form

ENTRYPOINT와 CMD

무엇인가(ENTRYPOINT) + 기본 인자(CMD). exec form이 아니면 PID 1이 sh가 되어 시그널이 안 간다.

ENTRYPOINT ["java", "-jar", "/app.jar"]        # 항상 실행되는 것
CMD        ["--spring.profiles.active=prod"]   # 기본 인자 (덮어쓸 수 있다)
docker run myapp                  → java -jar /app.jar --spring...=prod
docker run myapp --debug          → java -jar /app.jar --debug   (CMD 만 교체)
docker run --entrypoint sh myapp  → sh   (ENTRYPOINT 를 바꾼다)
  • ENTRYPOINT — 이 컨테이너가 '무엇인가' 를 정한다

  • CMD — 기본 인자. 사용자가 덮어쓸 것을 전제로 한다

  • CMD 만 쓰면 — docker run myapp bash 로 통째로 교체된다 (디버깅엔 편하다)

  • ENTRYPOINT 만 — 인자를 덧붙이는 형태가 된다

exec form 과 shell form — 시그널이 갈린다

CMD java -jar app.jar             # shell form → /bin/sh -c "java -jar app.jar"
CMD ["java", "-jar", "app.jar"]   # exec form  → 직접 실행

shell form 이면 PID 1 이 sh 가 된다

  • 컨테이너 정지 시 SIGTERM 을 sh 가 받는다
  • sh 는 그것을 자식에게 전달하지 않는다
  • 애플리케이션이 graceful shutdown 을 못 한다 → 강제 종료

배포마다 요청이 잘리는 원인 1순위다 반드시 exec form(대괄호 표기)을 쓴다

변수 치환이 필요할 때

# exec form 은 셸을 안 거치므로 $VAR 가 치환되지 않는다
CMD ["java", "-Xmx$MEM", "-jar", "app.jar"]   # ✗ 문자열 그대로 넘어간다

# 방법 ① 셸을 명시하되 exec 로 교체해 PID 1 을 넘긴다
CMD ["sh", "-c", "exec java -Xmx$MEM -jar app.jar"]

# 방법 ② 엔트리포인트 스크립트에서 exec
#   entrypoint.sh 마지막 줄:  exec "$@"

핵심은 exec 다 — 셸이 자기를 애플리케이션으로 '대체' 하므로 PID 1 이 애플리케이션이 된다 → 시그널이 직접 간다

엔트리포인트 스크립트를 쓴다면 마지막이 exec "$@" 인지 반드시 확인한다

컨테이너를 실행 파일처럼 만든다

ENTRYPOINT ["/usr/local/bin/mytool"]
CMD ["--help"]
  • docker run mytool — → --help 가 나온다

  • docker run mytool scan /src — → 도구처럼 인자를 받는다

  • CLI 도구를 배포할 때의 관용적 형태다

엔트리포인트 스크립트 패턴

#!/bin/sh
set -e

# 실행 전 준비 — 설정 렌더링 · 마이그레이션 대기 등
envsubst < /app/config.tmpl > /app/config.yml

exec "$@"        # ← 반드시 exec. 이것이 PID 1 을 넘긴다
ENTRYPOINT ["/entrypoint.sh"]
CMD ["java", "-jar", "/app.jar"]

스크립트가 준비를 끝내고 자기를 애플리케이션으로 '대체' 한다 exec 를 빠뜨리면 스크립트가 PID 1 로 남아 시그널이 애플리케이션에 안 간다

기존 이미지의 엔트리포인트 스크립트를 볼 때 마지막 줄이 exec 인지 확인하는 것이 습관이 돼야 한다

실행 권한을 잊지 않는다

  • COPY entrypoint.sh /entrypoint.sh

  • 실행 비트가 없으면 종료 코드 126 (permission denied)

    • COPY --chmod=755 entrypoint.sh /entrypoint.sh
    • 또는 RUN chmod +x /entrypoint.sh

윈도우에서 만든 스크립트는 줄바꿈(CRLF)도 문제가 된다

  • "exec /entrypoint.sh: no such file or directory"
  • 셔뱅 뒤의 \r 때문이다. .gitattributes 로 LF 를 강제한다

면접 함정

  • "CMD와 ENTRYPOINT는 골라 쓰면 된다" → 함께 쓰는 것이 기본형이다.
  • "shell form이 읽기 편하니 괜찮다" → PID 1이 sh가 되어 무중단 배포가 깨진다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — Dockerfile — 명령어와 그 함정