commands - ¿Cuál es la diferencia entre CMD y ENTRYPOINT en un Dockerfile?
dockerfile cmd multiple commands (9)
CMD:
-
CMD ["executable","param1","param2"]
:["executable","param1","param2"]
es el primer proceso. -
CMD command param1 param2
primer proceso es elCMD 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 paraENTRYPOINT
.
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 elENTRYPOINT 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.
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?
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á.
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
.
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
.
El ENTRYPOINT
especifica un comando que siempre se ejecutará cuando se inicie el contenedor.
El CMD
especifica los argumentos que se ENTRYPOINT
al ENTRYPOINT
.
Si desea hacer una imagen dedicada a un comando específico, utilizará ENTRYPOINT ["/path/dedicated_command"]
De lo contrario, si desea hacer una imagen para fines generales, puede dejar ENTRYPOINT
especificar y usar CMD ["/path/dedicated_command"]
ya que podrá anular la configuración al proporcionar argumentos a la docker run
.
Por ejemplo, si su Dockerfile es:
FROM debian:wheezy
ENTRYPOINT ["/bin/ping"]
CMD ["localhost"]
Ejecutar la imagen sin ningún argumento hará ping al localhost:
$ 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
Ahora, ejecutar la imagen con un argumento hará ping al 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 comparación, si su Dockerfile es:
FROM debian:wheezy
CMD ["/bin/ping", "localhost"]
Ejecutar la imagen sin ningún argumento hará ping al localhost:
$ 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
Pero ejecutar la imagen con un argumento ejecutará el argumento:
docker run -it test bash
root@e8bb7249b843:/#
Vea este artículo de Brian DeHamer para obtener aún más detalles: https://www.ctl.io/developers/blog/post/dockerfile-entrypoint-vs-cmd/
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
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'' :
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.
- Dockerfile debe especificar al menos uno de los comandos
CMD
oENTRYPOINT
.ENTRYPOINT
debe definir cuando se usa el contenedor como un ejecutable.CMD
debe utilizar como una forma de definir argumentos predeterminados para un comandoENTRYPOINT
o para ejecutar un comando ad-hoc en un contenedor.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 ║
╚════════════════════════════╩═════════════════════════════════════════════════╝