Dockerfile에서 CMD와 ENTRYPOINT의 차이점은 무엇입니까?


1698

Dockerfiles 년이 나에게 유사 두 명령은 다음과 같습니다 CMDENTRYPOINT. 그러나 나는 그들 사이에 (미묘한) 차이가 있다고 생각합니다. 그렇지 않으면 동일한 것에 대해 두 개의 명령을 갖는 것이 의미가 없습니다.

설명서에 대한 내용 CMD

CMD의 주요 목적은 실행 컨테이너에 대한 기본값을 제공하는 것입니다.

그리고 ENTRYPOINT:

ENTRYPOINT를 사용하면 실행 파일로 실행할 수있는 컨테이너를 구성 할 수 있습니다.

그렇다면 두 명령의 차이점은 무엇입니까?


12
이 블로그 게시물에는 차이점과 그 차이점을 함께 사용할 수있는 방법에 대한 설명이 있습니다 ( crosbymichael.com/dockerfile-best-practices.html) .
slm

2
^^ 감사합니다 @ slm. 좀 더 최신의 다른 유사한 참조가 있습니다 : docs.docker.com/reference/builder/#entrypoint
Adam Monsen


1
이 링크는 RUN, CMD 및 ENTRYPOINT의 차이점을 제공합니다. goinbigdata.com/docker-run-vs-cmd-vs-entrypoint
prafi

것을 그냥 참고 CMD하고 ENTRYPOINT모두가 다른 형태를 가지고는, 기록 될 간부 형태. 따라서 자신에게 유리한 태도를 취하고 사용되는 형태에 따라 행동의 미묘한 차이점을 이해하십시오. 그런 다음 docs.docker.com/engine/reference/builder/…를 읽으 십시오 .
Jaime Hablutzel

답변:


1736

Docker에는 기본 진입 점이 /bin/sh -c있지만 기본 명령은 없습니다.

docker를 다음과 같이 실행 docker run -i -t ubuntu bash 하면 진입 점이 기본값 /bin/sh -c이고 이미지는 ubuntu이며 명령은 bash입니다.

명령은 진입 점을 통해 실행됩니다. 즉, 실제로 실행되는 것은 /bin/sh -c bash입니다. 이를 통해 Docker RUN는 셸 파서에 의존하여 신속하게 구현할 수있었습니다 .

나중에, 사람들은이를 사용자 정의 할 수 있도록 요청, 그래서 ENTRYPOINT--entrypoint소개되었다.

ubuntu위의 예제에서 모든 것은 명령이며 진입 점으로 전달됩니다. CMD지시 사항을 사용할 때 , 마치 지시 사항과 똑같습니다 docker run -i -t ubuntu <cmd>. <cmd>진입 점의 매개 변수가됩니다.

대신이 명령을 입력하면 동일한 결과를 얻을 수 있습니다 docker run -i -t ubuntu. 우분투 Dockerfile 이 기본 CMD를 지정 했기 때문에 컨테이너에서 bash 쉘을 계속 시작할 것입니다 .CMD ["bash"]

모든 것이 진입 점으로 전달되면 이미지에서 매우 훌륭한 동작을 할 수 있습니다. @Jiri 예제가 좋으며 이미지를 "이진"으로 사용하는 방법을 보여줍니다. 사용하는 경우 ["/bin/cat"]엔트리 포인트로하고 일을 docker run img /etc/passwd, 당신은 얻을 /etc/passwd명령이며, 최종 결과 실행이 단순히 때문에 엔트리 포인트에 전달됩니다 /bin/cat /etc/passwd.

다른 예는 cli를 진입 점으로 사용하는 것입니다. 예를 들어 redis 이미지가있는 경우 running 대신을 실행 한 다음 같은 결과를 얻기 위해 docker run redisimg redis -H something -u toto get key간단히 ENTRYPOINT ["redis", "-H", "something", "-u", "toto"]다음과 같이 실행할 수 있습니다 docker run redisimg get key.


3
전혀. ENTRYPOINT는 런타임에 (그러나 재정의 될 수있는) 메타 데이터를 설정합니다. 따라서 컨테이너를 시작한 후 아무것도 변경하지 않으면 결과는 동일하지만 빌드 시간과 실행 시간에 관계없이 RUN이 예상됩니다. 런타임에 여기에 있습니다.
creack

8
기본적으로는 없습니다 ENTRYPOINT; 쉘 사용 여부는 사용 된 CMD명령 형식 ( docs.docker.com/engine/reference/builder/#cmd ) 에 따라 다릅니다 .
Blaisorblade

19
덕분에 역사적 맥락은 재정의 된 내용과 추가 된 내용에 대한 겉보기에 이상한 규칙을 기억하는 데 어려움을 겪고 있었으므로 많은 도움이됩니다. 사실과 시나리오를 열거하지 마십시오 :-)
ashirley

84
이것은 멋진 답변입니다. Docker 설명서에 이것을 CMDvs 라는 섹션 아래에 추가해야한다고 생각합니다 ENTRYPOINT.
Tarik

5
@Webman 아니오. 두 가지 지침이 있습니다. 둘 다 존재하는 경우 CMD는 ENTRYPOINT의 매개 변수로 처리됩니다.
빛 G.

627

ENTRYPOINT지정 컨테이너가 시작될 때 항상 실행됩니다 명령.

CMD전달 될 인수를 지정합니다 ENTRYPOINT.

특정 명령 전용 이미지를 만들려면 ENTRYPOINT ["/path/dedicated_command"]

그렇지 않으면 일반적인 용도로 이미지를 만들려면에 ENTRYPOINT지정하지 않고 CMD ["/path/dedicated_command"]인수를 제공하여 설정을 무시할 수 있으므로 사용할 수 없습니다 docker run.

예를 들어 Dockerfile이 다음과 같은 경우

FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]

인수없이 이미지를 실행하면 localhost가 ping됩니다.

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.096 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.088 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.088 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.088/0.091/0.096/0.000 ms

이제 인수로 이미지를 실행하면 인수를 핑합니다.

$ docker run -it test google.com
PING google.com (173.194.45.70): 48 data bytes
56 bytes from 173.194.45.70: icmp_seq=0 ttl=55 time=32.583 ms
56 bytes from 173.194.45.70: icmp_seq=2 ttl=55 time=30.327 ms
56 bytes from 173.194.45.70: icmp_seq=4 ttl=55 time=46.379 ms
^C--- google.com ping statistics ---
5 packets transmitted, 3 packets received, 40% packet loss
round-trip min/avg/max/stddev = 30.327/36.430/46.379/7.095 ms

Dockerfile이 다음과 같은 경우 비교하십시오.

FROM debian:wheezy
CMD ["/bin/ping", "localhost"]

인수없이 이미지를 실행하면 localhost가 ping됩니다.

$ docker run -it test
PING localhost (127.0.0.1): 48 data bytes
56 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.076 ms
56 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.087 ms
56 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
^C--- localhost ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.076/0.084/0.090/0.000 ms

그러나 인수로 이미지를 실행하면 인수가 실행됩니다.

docker run -it test bash
root@e8bb7249b843:/#

자세한 내용은 Brian DeHamer 의이 기사를 참조하십시오 : https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/


219
The ENTRYPOINT specifies a command that will always be executed when the container starts. The CMD specifies arguments that will be fed to the ENTRYPOINT.좋은 요약입니다.
Jingguo Yao

1
--entrypoint 플래그를 사용하여 ENTRYPOINT를 재정의 할 수도 있습니다. 예를 들어 docker run -it --entrypoint bash test
seenimurugan

2
나는 당신의 예를 좋아합니다, 정말 도움이됩니다!
Chau Giang

2
@Jingguo Yao : CMD에-CMD [ "nginx", "-g", "daemon", "off"]와 같은 명령이 포함되어 있으면 어떻게됩니까? 연결 될까요?
KMC

@KMC CMD는 ENTRYPOINT의 기본 인수이므로 이미지를 실행할 때 새 인수를 전달하여 재정의합니다.
MGP

237

도커 문서 에 따르면 ,

CMD 및 ENTRYPOINT 명령어는 컨테이너를 실행할 때 어떤 명령이 실행 될지 정의합니다. 그들의 협력을 설명하는 규칙은 거의 없습니다.

  1. Dockerfile은 최소한 하나 CMD이상의 ENTRYPOINT명령을 지정해야 합니다.
  2. ENTRYPOINT 컨테이너를 실행 파일로 사용할 때 정의해야합니다.
  3. CMDENTRYPOINT명령에 대한 기본 인수를 정의 하거나 컨테이너에서 임시 명령을 실행하는 방법으로 사용해야합니다 .
  4. CMD 대체 인수로 컨테이너를 실행할 때 재정의됩니다.

아래 표 는 다른 ENTRYPOINT/ CMD조합에 대해 실행되는 명령을 보여줍니다 .

- No ENTRYPOINT

╔════════════════════════════╦═════════════════════════════╗
║ No CMD                     ║ error, not allowed          ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════╝

- ENTRYPOINT exec_entry p1_entry

╔════════════════════════════╦══════════════════════════════════╗
║ No CMD                     ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ /bin/sh -c exec_entry p1_entry   ║
╟────────────────────────────╫──────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ /bin/sh -c exec_entry p1_entry   ║
╚════════════════════════════╩══════════════════════════════════╝

- ENTRYPOINT [“exec_entry”, “p1_entry”]

╔════════════════════════════╦═════════════════════════════════════════════════╗
║ No CMD                     ║ exec_entry p1_entry                             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“exec_cmd”, “p1_cmd”] ║ exec_entry p1_entry exec_cmd p1_cmd             ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD [“p1_cmd”, “p2_cmd”]   ║ exec_entry p1_entry p1_cmd p2_cmd               ║
╟────────────────────────────╫─────────────────────────────────────────────────╢
║ CMD exec_cmd p1_cmd        ║ exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝

px_cmd와 exec_entry는 무엇입니까? 그들이 같은 실행 라인에있을 때 무엇을 의미합니까? 그들은 서로에게 논쟁으로 전달됩니까? 때에도 /bin/sh -c참여?
Danielo515

1
@ Danielo515 'px_cmd'와 'exec_entry'는 모두 더미 문자열입니다. /bin/sh -cCMD가 실행 구문 (목록 구문이 아닌)으로 작성된 동안 접두사로 CMD에 추가되는 것을 알 수 있습니다 .
빛 G.

1
@royki 사용자가 docker run에 인수를 지정하면 CMD에 지정된 기본값을 무시합니다.
donrondadon

2
ENTRYPOINT exec_entry p1_ent잘못 설명되었습니다. - 쉘 형태가 사용되는 모든 CMD 또는 실행 명령 줄 인수를 방지 docs.docker.com/engine/reference/builder/#entrypoint
MARIUSZ Miesiak에게

1
@MariuszMiesiak 이제 업데이트되었습니다. 의견을 보내 주셔서 감사합니다.
Rafaf Tahsin 5

170

네, 좋은 질문입니다. 아직 완전히 이해하지 못했지만 :

나는 그것이 ENTRYPOINT실행중인 바이너리라는 것을 이해합니다 . --entrypoint = ""로 진입 점을 무시할 수 있습니다.

docker run -t -i --entrypoint="/bin/bash" ubuntu

CMD는 컨테이너의 기본 인수입니다. 진입 점이 없으면 기본 인수는 실행되는 명령입니다. 진입 점을 사용하면 cmd가 진입 점에 인수로 전달됩니다. 진입 점으로 명령을 에뮬레이션 할 수 있습니다.

# no entrypoint
docker run ubuntu /bin/cat /etc/passwd

# with entry point, emulating cat command
docker run --entrypoint="/bin/cat" ubuntu /etc/passwd

따라서 주요 이점은 진입 점을 사용하여 컨테이너에 인수 (cmd)를 전달할 수 있다는 것입니다. 이를 위해서는 두 가지를 모두 사용해야합니다.

# Dockerfile
FROM ubuntu
ENTRYPOINT ["/bin/cat"]

docker build -t=cat .

다음을 사용할 수 있습니다.

docker run cat /etc/passwd
#              ^^^^^^^^^^^
#                   CMD
#          ^^^      
#          image (tag)- using the default ENTRYPOINT

@Blauhirn 귀하의 경우 목록 구문으로 CMD에 인수를 추가하고, 구분 한 진입 점이 CMD에서 인수를 구문 분석 할 수 있는지 확인해야합니다. 일반적으로 시작점에 '-h'인수를 추가합니다. 그런 다음 docker run image_name -h이 이미지의 도움말 정보를 보여주기 위해 실행할 수 있습니다 .
빛 G.

1
이것은 가장 간단하고 명확한 답변입니다.
Eric Wang

44

직감에 의한 CMD와 ENTRYPOINT의 차이점 :

  • ENTRYPOINT : 컨테이너가 시작될 때 실행할 명령입니다.
  • CMD : 컨테이너가 시작될 때 실행할 명령 또는 지정된 경우 ENTRYPOINT에 대한 인수

그렇습니다.

docker run을 실행할 때 그중 하나를 무시할 수 있습니다.

CMD 및 엔트리 포인트의 차이 예에 의하여 :

docker run -it --rm yourcontainer /bin/bash            <-- /bin/bash overrides CMD
                                                       <-- /bin/bash does not override ENTRYPOINT
docker run -it --rm --entrypoint ls yourcontainer      <-- overrides ENTRYPOINT with ls
docker run -it --rm --entrypoint ls yourcontainer  -la  <-- overrides ENTRYPOINT with ls and overrides CMD with -la

차이에 대한 자세한 CMDENTRYPOINT:

docker run/ bin / bash와 같은 인수 는 Dockerfile에 작성한 CMD 명령보다 우선합니다.

ENTRYPOINT는와 같은 일반 명령으로 런타임에 재정의 할 수 없습니다 docker run [args]. 는 args말의 docker run [args]엔트리 포인트에 인수로 제공됩니다. 이런 식으로 우리 container는와 같은 일반 이진과 같은 것을 만들 수 있습니다 ls.

따라서 CMD는 ENTRYPOINT에 대한 기본 매개 변수로 작동 한 다음 [args]에서 CMD 인수를 재정의 할 수 있습니다.

ENTRYPOINT는로 대체 할 수 있습니다 --entrypoint.


38

간단히 말해서 :

  • CMD는 기본 명령 및 / 또는 매개 변수를 설정하며, Docker 컨테이너가 실행될 때 명령 줄에서 덮어 쓸 수 있습니다.
  • ENTRYPOINT 명령 및 매개 변수는 명령 행에서 겹쳐 쓰지 않습니다. 대신, 모든 명령 행 인수는 ENTRYPOINT 매개 변수 뒤에 추가됩니다.

좀 더 자세한 내용이 필요하거나 예에 차이를보고 싶은 경우, 종합적으로 예를 많이 CMD 및 엔트리 포인트를 비교하는 블로그 게시물이 - http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/


21

차이점을 더 잘 이해하는 데 도움이 되는 예제 1 로 답변을 추가하겠습니다 .

시작할 때 항상 절전 명령을 실행 하는 이미지를 만들고 싶다고 가정 해 봅시다 . 우리는 우리 자신의 이미지를 만들고 새로운 명령을 지정합니다 :

FROM ubuntu
CMD sleep 10

이제 이미지를 만듭니다.

docker build -t custom_sleep .
docker run custom_sleep
# sleeps for 10 seconds and exits

초 수를 변경하려면 어떻게해야합니까? Dockerfile값이 하드 코딩 될 때 값 을 변경 하거나 다른 값을 제공하여 명령을 재정의해야합니다.

docker run custom_sleep sleep 20

우리가 중복 "절전"명령을 가지고이 작품 있지만, 그것은 (컨테이너의 목적이다 좋은 솔루션이 아니다 수면 그래서 명시 적으로 지정할 필요, sleep명령을 좋은 방법이 아닙니다).

이제 ENTRYPOINT명령어를 사용해 봅시다 :

FROM ubuntu
ENTRYPOINT sleep

이 명령어 는 컨테이너가 시작될 때 실행될 프로그램을 지정합니다 .

이제 다음을 실행할 수 있습니다.

docker run custom_sleep 20

기본값은 어떻습니까? 글쎄, 당신은 그것을 올바르게 추측했다 :

FROM ubuntu
ENTRYPOINT ["sleep"]
CMD ["10"]

ENTRYPOINT실행됩니다 프로그램이며, 컨테이너에 전달 된 값은 추가됩니다.

플래그 ENTRYPOINT를 지정하고 --entrypoint사용하려는 새 진입 점을 지정하여를 재정 의 할 수 있습니다 .

내 것이 아니라이 예제를 제공하는 자습서를 한 번 보았습니다.


1
여기에 튜토리얼에 대한 링크는 다음과 같습니다 youtu.be/OYbEWUbmk90 . 미래의 사용자에게 유용 할 수 있습니다.
ChiPlusPlus


7

코드의 EntryPoint 함수에 대한 주석

// ENTRYPOINT / usr / sbin / nginx.

// 진입 점 (기본값은 sh -c)을 / usr / sbin / nginx로 설정합니다.

// CMD를 / usr / sbin / nginx의 인수로 받아들입니다.

문서에서 다른 참조

ENTRYPOINT의 exec 형식을 사용하여 상당히 안정적인 기본 명령 및 인수 를 설정 한 다음 CMD를 사용하여 변경 될 가능성이있는 추가 기본값을 설정할 수 있습니다.

예:

FROM ubuntu:14.04.3
ENTRYPOINT ["/bin/ping"]
CMD ["localhost", "-c", "2"]

빌드 : sudo docker build -t ent_cmd.

CMD arguments are easy to override.

NO argument (sudo docker -it ent_cmd)                :  ping localhost 
argument    (sudo docker run -it ent_cmd google.com) :  ping google.com

.

To override EntryPoint argument, you need to supply entrypoint
sudo docker run -it --entrypoint="/bin/bash" ent_cmdd

ps : EntryPoint가있는 경우 CMD는 EntryPoint에 제공 할 인수를 보유합니다. EntryPoint가 없으면 CMD가 실행될 명령이됩니다.


3

CMDDockerfile파일 내부에 언급 된 docker run명령 ENTRYPOINT은 명령을 통해 무시할 수 있지만 명령을 통해 재정의 할 수는 없습니다.


4
docker run --help명령은 그렇지 않으면 말합니다 :--entrypoint string Overwrite the default ENTRYPOINT of the image
iomv

3

나는 모든 답변을 읽었으며 다음과 같이 언뜻보기에 더 나은 이해를 위해 요약하고 싶습니다.

먼저 컨테이너에서 실행되는 전체 명령에는 명령인수 두 부분이 포함됩니다.

  • ENTRYPOINT 는 컨테이너가 시작될 때 호출되는 실행 파일을 정의합니다 (명령 용).

  • CMD 는 ENTRYPOINT로 전달되는 인수를 지정합니다 (인수).

으로 는 Kubernetes에서 동작 책 그것에 대해 중요한 점을 지적한다. (7 장)

CMD 명령을 사용하여 이미지가 실행될 때 실행할 명령을 지정할 수 있지만 올바른 방법은 ENTRYPOINT 명령을 통해 수행 하고 기본 인수를 정의하려는 경우 에만 CMD를 지정하는 것 입니다.

간단한 방법 으로이 기사를 읽으면 훌륭한 설명을 얻을 수 있습니다


2

CMD :

  • CMD ["executable","param1","param2"]: ["executable","param1","param2"]첫 번째 프로세스입니다.
  • CMD command param1 param2: /bin/sh -c CMD command param1 param2첫 번째 프로세스입니다. CMD command param1 param2첫 번째 프로세스에서 분기됩니다.
  • CMD ["param1","param2"]:이 양식은에 대한 기본 인수를 제공하는 데 사용됩니다 ENTRYPOINT.

ENTRYPOINT (다음 목록은 CMD와 ENTRYPOINT가 함께 사용되는 경우를 고려하지 않습니다) :

  • ENTRYPOINT ["executable", "param1", "param2"]: ["executable", "param1", "param2"]첫 번째 프로세스입니다.
  • ENTRYPOINT command param1 param2: /bin/sh -c command param1 param2첫 번째 프로세스입니다. command param1 param2첫 번째 프로세스에서 분기됩니다.

마찬가지로 creack은 상기 CMD 먼저 개발되었다. 그런 다음 ENTRYPOINT는 더 많은 사용자 정의를 위해 개발되었습니다. 그것들은 함께 설계되지 않았기 때문에 CMD와 ENTRYPOINT 사이에 일부 기능이 중복되어 종종 사람들을 혼란스럽게합니다.


2

대부분의 사람들이 여기에 완벽하게 설명하므로 모든 답변을 반복하지는 않습니다. 그러나 좋은 느낌을 얻으려면 컨테이너의 프로세스를보고 직접 테스트하는 것이 좋습니다.

다음과 같은 작은 Dockerfile을 작성하십시오.

FROM ubuntu:latest
CMD /bin/bash

그것을 빌드 하고 컨테이너 와 함께 docker run -it theimage실행 ps -eo ppid,pid,args하십시오. 이 출력을 다음을 사용할 때 ps에서 수신 한 출력과 비교하십시오.

  • docker run -it theimage bash
  • 이미지를 다시 작성하지만 ENTRYPOINT /bin/bash두 가지 방법으로 이미지 를 모두 실행
  • 사용 CMD ["/bin/bash"]
  • ...

이렇게하면 가능한 모든 방법의 차이점을 쉽게 확인할 수 있습니다.


0

Dockerfile 모범 사례에 대한 공식 문서는 차이점을 잘 설명해줍니다. Dockerfile 모범 사례

CMD :

CMD 명령어는 인수와 함께 이미지에 포함 된 소프트웨어를 실행하는 데 사용해야합니다. CMD는 거의 항상 형식으로 사용해야합니다 CMD ["executable", "param1", "param2"…]. 따라서 이미지가 Apache 및 Rails와 같은 서비스 용인 경우 다음과 같이 실행 CMD ["apache2","-DFOREGROUND"]됩니다. 실제로이 형식의 명령어는 모든 서비스 기반 이미지에 권장됩니다.

진입 지점:

ENTRYPOINT의 가장 좋은 용도는 이미지의 기본 명령을 설정하여 해당 명령처럼 이미지를 실행 한 다음 CMD를 기본 플래그로 사용하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.