Diferencia entre RUN y CMD en un Dockerfile

Respuestas:

425

EJECUTAR es un paso de creación de imagen, el estado del contenedor después de un RUNcomando se confirmará en la imagen del contenedor. Un Dockerfile puede tener muchos RUNpasos que se superponen para construir la imagen.

CMD es el comando que el contenedor ejecuta de forma predeterminada cuando inicia la imagen construida. Un Dockerfile solo usará el final CMDdefinido. Se CMDpuede anular al iniciar un contenedor con docker run $image $other_command.

ENTRYPOINT también está estrechamente relacionado CMDy puede modificar la forma en que un contenedor inicia una imagen.

Mate
fuente
15
haces todo lo RUNnecesario para configurar tu entorno, y tu (solo) CMD inicia el proceso que se ejecuta en tu contenedor, por ejemplo, para nginx, extrae de github.com/nginxinc/docker-nginx/blob/… ves la líneaCMD ["nginx", "-g", "daemon off;"]
user2915097
"Un Dockerfile solo puede tener un CMD", lo que no es técnicamente cierto, pero efectivamente todos menos uno serán ignorados. Ver la respuesta de GingerBeer.
Colm Bhandal
¿"Un Dockerfile solo usará el CMD final definido"? en realidad, la CMD final definida se usará para lanzar la imagen como contenedor, ¿verdad?
Paul Cheung
1
Sí @paulcheung, el comando final en el dockerfile se escribe en la imagen y es el comando que el contenedor ejecuta de manera predeterminada cuando inicia la imagen construida.
Matt
126

RUN - El comando se dispara mientras construimos la imagen del acoplador.

CMD - el comando se dispara mientras lanzamos la imagen de docker creada.

Nisal Edu
fuente
67

Este artículo me pareció muy útil para comprender la diferencia entre ellos:

CORRER : la instrucción EJECUTAR le permite instalar su aplicación y los paquetes necesarios para ello. Ejecuta cualquier comando sobre la imagen actual y crea una nueva capa al confirmar los resultados. A menudo encontrará múltiples instrucciones de EJECUTAR en un Dockerfile.

CMD : la instrucción CMD le permite establecer un comando predeterminado, que se ejecutará solo cuando ejecute el contenedor sin especificar un comando. Si el contenedor Docker se ejecuta con un comando, se ignorará el comando predeterminado. Si Dockerfile tiene más de una instrucción CMD,
se ignorarán todas las últimas instrucciones CMD.

meter
fuente
13

EJECUTAR - Instale Python, su contenedor ahora tiene python quemado en su imagen
CMD - python hello.py, ejecute su script favorito

Rohit Salecha
fuente
CMD : instale Python, ¿mi contenedor ahora no tiene Python quemado en su imagen?
Carlos Fontes
RUN creará una capa de imagen de python, CMD simplemente ejecutará el comando, no creará la imagen
Rohit Salecha
8

Comando EJECUTAR: El comando EJECUTAR básicamente ejecutará el comando predeterminado cuando construimos la imagen. También confirmará los cambios de imagen para el siguiente paso.

Puede haber más de 1 comando RUN, para ayudar en el proceso de construcción de una nueva imagen.

Comando CMD: los comandos CMD solo establecerán el comando predeterminado para el nuevo contenedor. Esto no se ejecutará en el momento de la compilación.

Si un archivo acoplable tiene más de 1 comandos CMD, se ignoran todos, excepto el último. Como este comando no ejecutará nada, solo configure el comando predeterminado.

Cerveza de jengibre
fuente
6

Nota: No confunda RUN con CMD. RUN realmente ejecuta un comando y confirma el resultado; CMD no ejecuta nada en el momento de la compilación, pero especifica el comando previsto para la imagen.

de la referencia del archivo acoplable

https://docs.docker.com/engine/reference/builder/#cmd

Elsayed
fuente
4

EJECUTAR : puede ser muchos y se usa en la compilación proceso de , por ejemplo, instalar varias bibliotecas

CMD : solo puede tener 1, que es su punto de inicio de ejecución (por ejemplo ["npm", "start"], ["node", "app.js"])

Xin
fuente
2

Las respuestas existentes cubren la mayor parte de lo que cualquiera que esté viendo esta pregunta necesitaría. Así que solo cubriré algunas áreas de nicho para CMD y RUN.

CMD: se permiten duplicados pero es un desperdicio

GingerBeer hace un punto importante: no obtendrá ningún error si coloca más de un CMD, pero es un desperdicio hacerlo. Me gustaría elaborar con un ejemplo:

FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"

Si construye esto en una imagen y ejecuta un contenedor en esta imagen, como dice GingerBeer, solo se tendrá en cuenta la última CMD. Entonces la salida de ese contenedor será:

Ejecutando CMD 2

La forma en que lo pienso es que "CMD" está configurando una única variable global para toda la imagen que se está creando, por lo que las sucesivas declaraciones "CMD" simplemente sobrescriben cualquier escritura anterior en esa variable global, y en la imagen final que se construye el último en escribir gana. Dado que un Dockerfile se ejecuta en orden de arriba a abajo, sabemos que el CMD más inferior es el que obtiene esta "escritura" final (hablando metafóricamente).

EJECUTAR: los comandos pueden no ejecutarse si las imágenes se almacenan en caché

Un punto sutil a tener en cuenta sobre RUN es que se trata como una función pura, incluso si hay efectos secundarios, y por lo tanto se almacena en caché. Lo que esto significa es que si RUN tuvo algunos efectos secundarios que no cambian la imagen resultante, y esa imagen ya ha sido almacenada en caché, el RUN no se ejecutará nuevamente y, por lo tanto, los efectos secundarios no sucederán en las construcciones posteriores. Por ejemplo, tome este Dockerfile:

FROM busybox
RUN echo "Just echo while you work"

La primera vez que lo ejecute, obtendrá un resultado como este, con diferentes ID alfanuméricos:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest

Observe que la declaración de eco se ejecutó en lo anterior. La segunda vez que lo ejecuta, usa el caché y no verá ningún eco en la salida de la compilación:

docker build -t example/run-echo .
Sending build context to Docker daemon  9.216kB
Step 1/2 : FROM busybox
 ---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
 ---> Using cache
 ---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest
Colm Bhandal
fuente
1

Ha habido suficientes respuestas sobre RUN y CMD . Solo quiero agregar algunas palabras en ENTRYPOINT . Los argumentos de CMD se pueden sobrescribir con argumentos de línea de comandos, mientras que los argumentos ENTRYPOINT siempre se usan.

Este artículo es una buena fuente de información.

Milo Lu
fuente