Qual é a diferença entre o CMD e o ENTRYPOINT em um Dockerfile?

Nos Dockerfiles, há dois comandos semelhantes a mim: CMD e ENTRYPOINT . Mas eu acho que há uma diferença (sutil?) Entre eles – caso contrário, não faria sentido ter dois comandos para a mesma coisa.

Os estados da documentação para o CMD

O objective principal de um CMD é fornecer padrões para um contêiner em execução.

e para ENTRYPOINT :

Um ENTRYPOINT ajuda você a configurar um contêiner que pode ser executado como um executável.

Então, qual a diferença entre esses dois comandos?

O Docker possui um entrypoint padrão, que é /bin/sh -c mas não possui um comando padrão.

Quando você executa o docker como este: docker run -i -t ubuntu bash o entrypoint é o padrão /bin/sh -c , a imagem é o ubuntu e o comando é bash .

O comando é executado através do ponto de input. isto é, a coisa real que é executada é /bin/sh -c bash . Isso permitiu que o Docker implementasse o RUN rapidamente, confiando no analisador do shell.

Mais tarde, as pessoas pediram para poder personalizar isso, então ENTRYPOINT e --entrypoint foram introduzidos.

Tudo após o ubuntu no exemplo acima é o comando e é passado para o ponto de input. Ao usar a instrução CMD , é exatamente como se você estivesse fazendo o docker run -i -t ubuntu . será o parâmetro do ponto de input.

Você também obterá o mesmo resultado se, em vez disso, digitar este comando docker run -i -t ubuntu . Você ainda vai iniciar um shell bash no container por causa do ubuntu Dockerfile especificou um padrão CMD: CMD ["bash"]

Como tudo é passado para o ponto de input, você pode ter um comportamento muito bom de suas imagens. @Jiri exemplo é bom, mostra como usar uma imagem como um “binário”. Ao usar ["/bin/cat"] como ponto de input e fazer o docker run img /etc/passwd , você o obtém, /etc/passwd é o comando e é passado para o ponto de input para que a execução do resultado final seja simplesmente /bin/cat /etc/passwd .

Outro exemplo seria ter qualquer cli como ponto de input. Por exemplo, se você tiver uma imagem de redis, em vez de executar o docker run redisimg redis -H something -u toto get key , você pode simplesmente ter ENTRYPOINT ["redis", "-H", "something", "-u", "toto"] e, em seguida, execute assim para o mesmo resultado: docker run redisimg get key .

O ENTRYPOINT especifica um comando que sempre será executado quando o contêiner for iniciado.

O CMD especifica argumentos que serão alimentados no ENTRYPOINT .

Se você quiser criar uma imagem dedicada a um comando específico, você usará ENTRYPOINT ["/path/dedicated_command"]

Caso contrário, se você quiser criar uma imagem para fins gerais, poderá deixar o ENTRYPOINT não especificado e usar o CMD ["/path/dedicated_command"] pois poderá replace a configuração fornecendo argumentos para a docker run .

Por exemplo, se o seu Dockerfile é:

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

Executar a imagem sem qualquer argumento fará o ping do host local:

 $ 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 

Agora, a execução da imagem com um argumento fará o ping do argumento:

 $ 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 

Para comparação, se o seu Dockerfile é:

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

Executar a imagem sem qualquer argumento fará o ping do host local:

 $ 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 

Mas a execução da imagem com um argumento executará o argumento:

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

Veja este artigo de Brian DeHamer para mais detalhes: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/

Sim, essa é uma boa pergunta. Eu não entendi completamente ainda, mas:

Eu entendo que ENTRYPOINT é o binário que está sendo executado. Você pode ultrapassar o ponto de input por –entrypoint = “”.

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

CMD é o argumento padrão para o contêiner. Sem o ponto de input, o argumento padrão é o comando que é executado. Com o ponto de input, o cmd é passado ao ponto de input como argumento. Você pode emular um comando com o ponto de input.

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

Então, a principal vantagem é que com o entrypoint você pode passar argumentos (cmd) para o seu container. Para conseguir isso, você precisa usar os dois:

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

e

 docker build -t=cat . 

então você pode usar:

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

De acordo com documentos docker ,

Ambas as instruções CMD e ENTRYPOINT definem qual comando é executado ao executar um contêiner. Existem poucas regras que descrevem sua cooperação.

  1. O Dockerfile deve especificar pelo menos um dos comandos CMD ou ENTRYPOINT .
  2. ENTRYPOINT deve ser definido ao usar o contêiner como um executável.
  3. CMD deve ser usado como uma maneira de definir argumentos padrão para um comando ENTRYPOINT ou para executar um comando ad-hoc em um contêiner.
  4. CMD será substituído ao executar o contêiner com argumentos alternativos.

As tabelas abaixo mostram qual comando é executado para diferentes combinações 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 exec_cmd p1_cmd ║ ╟────────────────────────────╫───────────────────────────────────────────────────────────╢ ║ CMD [“p1_cmd”, “p2_cmd”] ║ /bin/sh -c exec_entry p1_entry p1_cmd p2_cmd ║ ╟────────────────────────────╫───────────────────────────────────────────────────────────╢ ║ CMD exec_cmd p1_cmd ║ /bin/sh -c exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd ║ ╚════════════════════════════╩═══════════════════════════════════════════════════════════╝ 

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 ║ ╚════════════════════════════╩═════════════════════════════════════════════════╝ 

Em poucas palavras:

  • O CMD define o comando e / ou os parâmetros padrão, que podem ser sobrescritos na linha de comando quando o contêiner do docker é executado.
  • O comando ENTRYPOINT e os parâmetros não serão sobrescritos da linha de comando. Em vez disso, todos os argumentos da linha de comando serão adicionados após os parâmetros ENTRYPOINT.

Se você precisar de mais detalhes ou gostaria de ver a diferença no exemplo, há uma postagem no blog que compara de forma abrangente CMD e ENTRYPOINT com muitos exemplos – http://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/

Diferença entre CMD e ENTRYPOINT por intuição :

  • ENTRYPOINT: comando para executar quando o contêiner é iniciado.
  • CMD: comando para executar quando o contêiner é iniciado ou argumentos para ENTRYPOINT, se especificado.

Sim, está se misturando.

Você pode replace qualquer um deles ao executar a execução do docker.

Diferença entre CMD e ENTRYPOINT pelo exemplo :

 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 

Mais sobre a diferença entre o CMD e o ENTRYPOINT :

O argumento para o docker run , como / bin / bash, substitui qualquer comando CMD que tenhamos escrito no Dockerfile.

ENTRYPOINT não pode ser substituído em tempo de execução com comandos normais, como o docker run [args] . Os args no final da docker run [args] do docker run [args] são fornecidos como argumentos para o ENTRYPOINT. Desta forma, podemos criar um container que é como um binário normal, como ls .

Assim, o CMD pode atuar como parâmetros padrão para ENTRYPOINT e, em seguida, podemos replace os argumentos CMD de [args].

ENTRYPOINT pode ser substituído por --entrypoint .

A resposta aceita é fabulosa na explicação da história. Acho que esta tabela explica muito bem a partir do documento oficial sobre ‘como o CMD e o ENTRYPOINT interagem’ : insira a descrição da imagem aqui

Comentários sobre a function EntryPoint no código

// ENTRYPOINT / usr / sbin / nginx.

// Defina o ponto de input (cujo padrão é sh -c) para / usr / sbin / nginx.

// Aceitará o CMD como argumentos para / usr / sbin / nginx.

Outra referência de documentos

Você pode usar o formulário exec de ENTRYPOINT para definir comandos e argumentos padrão razoavelmente estáveis e, em seguida, usar o CMD para definir padrões adicionais com maior probabilidade de serem alterados.

Exemplo:

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

Construir : docker sudo 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: Na presença de EntryPoint, o CMD manterá argumentos para alimentar o EntryPoint. Na ausência de EntryPoint, o CMD será o comando que será executado.

CMD:

  • CMD ["executable","param1","param2"] : ["executable","param1","param2"] é o primeiro processo.
  • CMD command param1 param2 : /bin/sh -c CMD command param1 param2 é o primeiro processo. CMD command param1 param2 é bifurcado do primeiro processo.
  • CMD ["param1","param2"] : Este formulário é usado para fornecer argumentos padrão para ENTRYPOINT .

ENTRYPOINT (A lista a seguir não considera o caso em que o CMD e o ENTRYPOINT são usados ​​juntos):

  • ENTRYPOINT ["executable", "param1", "param2"] : ["executable", "param1", "param2"] é o primeiro processo.
  • ENTRYPOINT command param1 param2 : /bin/sh -c command param1 param2 é o primeiro processo. command param1 param2 é bifurcado do primeiro processo.

Como creack disse, o CMD foi desenvolvido primeiro. Em seguida, o ENTRYPOINT foi desenvolvido para mais personalização. Como eles não são projetados juntos, há algumas sobreposições de funcionalidade entre o CMD e o ENTRYPOINT, que muitas vezes confundem as pessoas.

Esta é provavelmente a melhor descrição que eu encontrei: Dockerfile: ENTRYPOINT vs CMD

Eu tinha um resumo aqui, mas as pessoas continuavam votando sem dar um motivo, então eu apaguei.