multiple - ¿Cuál es la diferencia entre CMD y ENTRYPOINT en un Dockerfile?




commands (9)

En Dockerfiles hay dos comandos que me parecen similares: CMD y ENTRYPOINT . Pero supongo que hay una diferencia (¿sutil?) Entre ellos; de lo contrario, no tendría ningún sentido tener dos comandos para la misma cosa.

Los estados de documentación para CMD

El propósito principal de un CMD es proporcionar valores predeterminados para un contenedor en ejecución.

y para ENTRYPOINT :

Un ENTRYPOINT le ayuda a configurar un contenedor que puede ejecutar como un ejecutable.

Entonces, ¿cuál es la diferencia entre esos dos comandos?


Answers

La respuesta aceptada es fabulosa al explicar la historia. Encuentro que esta tabla lo explica muy bien en el documento oficial sobre 'cómo interactúan CMD y ENTRYPOINT' :


Diferencia entre CMD y ENTRYPOINT por intuición :

  • ENTRYPOINT: comando que se ejecuta cuando se inicia el contenedor.
  • CMD: comando que se ejecuta cuando se inicia el contenedor o argumentos para ENTRYPOINT si se especifica.

Sí, se está mezclando.

Puede anular cualquiera de ellos al ejecutar la ventana acoplable.

Diferencia entre CMD y ENTRYPOINT por ejemplo :

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

Más sobre la diferencia entre CMD y ENTRYPOINT :

Los argumentos para docker run , como / bin / bash, anulan cualquier comando CMD que escribimos en Dockerfile.

ENTRYPOINT no se puede anular en tiempo de ejecución con comandos normales, como la docker run [args] . Los argumentos al final de la ejecución de la ventana docker run [args] argumentos docker run [args] se proporcionan como argumentos para ENTRYPOINT. De esta manera podemos crear un container que es como un binario normal como ls .

Por lo tanto, CMD puede actuar como parámetros predeterminados para ENTRYPOINT y luego podemos anular los argumentos de CMD de [args].

ENTRYPOINT se puede anular con --entrypoint .


Sí, esa es una buena pregunta. No lo entiendo completamente todavía, pero:

Entiendo que ENTRYPOINT es el binario que se está ejecutando. Puede sobrescribir el punto de entrada por --entrypoint = "".

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

CMD es el argumento predeterminado para el contenedor. Sin punto de entrada, el argumento predeterminado es un comando que se ejecuta. Con entrypoint, cmd se pasa a entrypoint como argumento. Puedes emular un comando con un punto de entrada.

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

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

Entonces, la principal ventaja es que con un punto de entrada puede pasar argumentos (cmd) a su contenedor. Para lograr esto, necesitas usar ambos:

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

y

docker build -t=cat .

entonces puedes usar:

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

Según documentos de la docker ,

Las instrucciones CMD y ENTRYPOINT definen qué comando se ejecuta cuando se ejecuta un contenedor. Hay pocas reglas que describen su cooperación.

  1. Dockerfile debe especificar al menos uno de los comandos CMD o ENTRYPOINT .
  2. ENTRYPOINT debe definir cuando se usa el contenedor como un ejecutable.
  3. CMD debe utilizar como una forma de definir argumentos predeterminados para un comando ENTRYPOINT o para ejecutar un comando ad-hoc en un contenedor.
  4. CMD se anulará al ejecutar el contenedor con argumentos alternativos.

Las tablas a continuación muestran qué comando se ejecuta para diferentes combinaciones 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  ║
╚════════════════════════════╩═════════════════════════════════════════════════╝

CMD:

  • CMD ["executable","param1","param2"] : ["executable","param1","param2"] es el primer proceso.
  • CMD command param1 param2 primer proceso es el CMD command param1 param2 : /bin/sh -c CMD command param1 param2 . CMD command param1 param2 se bifurca desde el primer proceso.
  • CMD ["param1","param2"] : este formulario se utiliza para proporcionar argumentos predeterminados para ENTRYPOINT .

ENTRYPOINT (La siguiente lista no considera el caso en el que CMD y ENTRYPOINT se usan juntos):

  • ENTRYPOINT ["executable", "param1", "param2"] : ["executable", "param1", "param2"] es el primer proceso.
  • ENTRYPOINT command param1 param2 primer proceso es el ENTRYPOINT command param1 param2 : /bin/sh -c command param1 param2 . command param1 param2 se bifurca desde el primer proceso.

Como dijo , CMD fue desarrollado primero. Luego ENTRYPOINT fue desarrollado para una mayor personalización. Como no están diseñados juntos, hay algunas funciones que se superponen entre CMD y ENTRYPOINT, que a menudo confunden a las personas.


Comentarios sobre la función EntryPoint en el code

// ENTRYPOINT / usr / sbin / nginx.

// Establezca el punto de entrada (cuyo valor predeterminado es sh -c) en / usr / sbin / nginx.

// Aceptará el CMD como los argumentos de / usr / sbin / nginx.

Otra referencia de los documentos.

Puede usar la forma ejecutiva de ENTRYPOINT para establecer comandos y argumentos predeterminados bastante estables y luego usar CMD para establecer valores predeterminados adicionales que es más probable que se cambien.

Ejemplo:

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

Build : 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: En presencia de EntryPoint, CMD mantendrá los argumentos que se enviarán a EntryPoint. En ausencia de EntryPoint, CMD será el comando que se ejecutará.


En una palabra:

  • CMD establece los comandos y / o parámetros predeterminados, que pueden sobrescribirse desde la línea de comandos cuando se ejecuta el contenedor de la ventana acoplable.
  • El comando y los parámetros de ENTRYPOINT no se sobrescribirán desde la línea de comandos. En su lugar, todos los argumentos de la línea de comandos se agregarán después de los parámetros ENTRYPOINT.

Si necesita más detalles o le gustaría ver la diferencia en el ejemplo, hay una publicación de blog que compara exhaustivamente CMD y ENTRYPOINT con muchos ejemplos: goinbigdata.com/docker-run-vs-cmd-vs-entrypoint


Docker tiene un punto de entrada predeterminado que es /bin/sh -c pero no tiene un comando predeterminado.

Cuando ejecuta la ventana acoplable de esta manera: la ventana docker run -i -t ubuntu bash el punto de entrada es el valor predeterminado /bin/sh -c , la imagen es ubuntu y el comando bash .

El comando se ejecuta a través del punto de entrada. es decir, lo que realmente se ejecuta es /bin/sh -c bash . Esto permitió a Docker implementar RUN rápidamente confiando en el analizador del shell.

Más adelante, las personas solicitaron poder personalizar esto, por --entrypoint se introdujeron ENTRYPOINT y --entrypoint .

Todo después de ubuntu en el ejemplo anterior es el comando y se pasa al punto de entrada. Cuando se usa la instrucción CMD , es exactamente como si estuvieras haciendo la docker run -i -t ubuntu <cmd> . <cmd> será el parámetro del punto de entrada.

También obtendrá el mismo resultado si en su lugar escribe este comando docker run -i -t ubuntu . Aún iniciará un shell bash en el contenedor debido a que el ubock Dockerfile especificó un CMD predeterminado: CMD ["bash"]

Como todo se pasa al punto de entrada, puede tener un comportamiento muy agradable de sus imágenes. El ejemplo de @Jiri es bueno, muestra cómo usar una imagen como un "binario". Cuando usa ["/bin/cat"] como punto de entrada y luego docker run img /etc/passwd ventana docker run img /etc/passwd , lo obtiene, /etc/passwd es el comando y se pasa al punto de entrada por lo que la ejecución del resultado final es simplemente /bin/cat /etc/passwd .

Otro ejemplo sería tener cualquier cli como punto de entrada. Por ejemplo, si tiene una imagen de redis, en lugar de docker run redisimg redis -H something -u toto get key , simplemente puede tener ENTRYPOINT ["redis", "-H", "something", "-u", "toto"] y, a continuación, ejecute así para obtener el mismo resultado: la función docker run redisimg get key .


Una instancia de una imagen se llama contenedor. Tiene una imagen, que es un conjunto de capas como usted describe. Si inicia esta imagen, tiene un contenedor en ejecución de esta imagen. Puedes tener muchos contenedores corriendo de la misma imagen.

Puede ver todas sus imágenes con imágenes de la docker images mientras que puede ver sus contenedores en ejecución con la docker ps (y puede ver todos los contenedores con la docker ps -a ).

Así que una instancia en ejecución de una imagen es un contenedor.







docker