Diferencia entre CMD y ENTRYPOINT en Docker

Isaac Tony 30 enero 2023
  1. el comando CMD en Docker
  2. el comando ENTRYPOINT en Docker
  3. Conclusión
Diferencia entre CMD y ENTRYPOINT en Docker

Los contenedores Docker se han convertido en el estándar a la hora de gestionar software y dependencias en diferentes entornos. Deberá crear un archivo Docker antes de crear la imagen del contenedor de aplicaciones cuando trabaje con aplicaciones reales.

Un archivo docker es simplemente un documento de texto de solo lectura con un conjunto de instrucciones que se llamarán al ensamblar una imagen. Estos comandos incluyen RUN, CMD y ENTRYPOINT.

En este artículo, discutiremos el uso de estos comandos. La mayoría de los desarrolladores que probablemente se encuentran en sus etapas iniciales de aprendizaje de Docker tienden a usar estos comandos indistintamente, lo que podría causarle algunos problemas.

el comando CMD en Docker

Este comando especifica una instrucción que se ejecuta cada vez que se ejecuta el comando docker RUN. Esto, sin embargo, requiere que el comando docker RUN se ejecute sin especificar ningún argumento.

Cuando se especifican argumentos, este comando se anula. Por otro lado, el comando CMD se ejecuta si no se especifican argumentos en la línea de comandos.

El comando CMD no es obligatorio para que su contenedor docker funcione correctamente, ya que el comando ECHO se puede usar en tiempo de ejecución para cumplir el mismo propósito. Sin embargo, el comando CMD puede ser útil cuando se ejecuta un archivo ejecutable cada vez que se inicia el contenedor.

Para demostrar cómo podemos usar el comando CMD para ejecutar un archivo ejecutable en tiempo de ejecución, crearemos un contenedor Docker simple con un programa matraz simple que imprime un mensaje. Tenga en cuenta que esto se puede replicar en cualquier idioma, no necesariamente en Python.

Comenzaremos creando nuestra aplicación principal, que debería ser tan simple como se muestra a continuación.

from flask import Flask

app = Flask(__name__)


def hello():
    print("Hello, this is a simple Flask application")


hello()

Dentro de la misma carpeta, crearemos nuestro Dockerfile mediante el comando touch Dockerfile.

El Dockerfile solo especifica la imagen base, el directorio de trabajo y los paquetes que deben instalarse.

En la última línea, debe notar el comando CMD. En este caso, estamos usando el comando CMD para ejecutar el archivo app.py cuando se inicia el contenedor.

#  base image
FROM python

# Set your working directory
WORKDIR /var/www/

# Copy the necessary files
COPY ./app.py /var/www/app.py
COPY ./requirements.txt /var/www/requirements.txt

# Install the necessary packages
RUN pip install -r /var/www/requirements.txt

# Run the app
CMD python3 app.py

El requirements.txt debería aparecer como se muestra a continuación.

click==8.0.4
Flask==2.0.3
gunicorn==20.1.0
itsdangerous==2.1.0
Jinja2==3.0.3
MarkupSafe==2.1.0
Werkzeug==2.0.3

Ahora que tenemos todo listo, podemos continuar y construir la imagen de la ventana Docker. Antes de eso, debemos asegurarnos de que estamos en la misma carpeta donde está almacenado nuestro programa.

En nuestro caso, vamos a cd en la carpeta my-app antes de construir la imagen, como se muestra a continuación.

~/my-app$ docker build -t isaactonyloi_image .

Producción :

 => [internal] load build context                                                                                                          0.9s
 => => transferring context: 320B                                                                                                          0.1s
 => [2/5] WORKDIR /var/www/                                                                                                                5.1s
 => [3/5] COPY ./app.py /var/www/app.py                                                                                                    3.2s
 => [4/5] COPY ./requirements.txt /var/www/requirements.txt                                                                                3.2s
 => [5/5] RUN pip install -r /var/www/requirements.txt                                                                                    53.9s
 => exporting to image                                                                                                                     6.9s
 => => exporting layers                                                                                                                    5.8s
 => => writing image sha256:5847e4777754d9d576accd929076bfbee633ca71f049ebe1af6e9bae161f3e96                                               0.1s
 => => naming to docker.io/library/isaactonyloi_image                                                                                      0.2s
isaac@DESKTOP-HV44HT6:~/my-app$

Hemos construido con éxito nuestra imagen basada en el archivo docker anterior. Lo podemos comprobar a continuación.

~/my-app$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED         SIZE
isaactonyloi_image   latest    5847e4777754   7 minutes ago   929MB

Finalmente podemos crear nuestro contenedor docker usando el comando docker run basado en esta imagen. Además, tenga en cuenta que haremos esto sin pasar ningún argumento para ejecutar el comando CMD.

~/my-app$ docker run isaactonyloi_image
Hello, this is a simple Flask application

Además de esto, el comando CMD también nos permite crear argumentos que pueden anularse fácilmente en tiempo de ejecución.

Hicimos cambios en el comando CMD en el siguiente ejemplo. Los otros archivos permanecen intactos y hemos reconstruido una nueva imagen.

# base image
FROM python

# Set your working directory
WORKDIR /var/www/

# Copy the necessary filesls
COPY ./app.py /var/www/app.py
COPY ./requirements.txt /var/www/requirements.txt

# Install the necessary packages
RUN pip install -r /var/www/requirements.txt

# Run the app
CMD ["echo", "Hello, Developer"]

Aquí está la nueva imagen que reconstruimos a partir de nuestros cambios en Dockerfile.

~/my-app$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
new_image            latest    73f323be0d2f   25 minutes ago   929MB

Deberíamos recibir el mensaje bajo el comando CMD al crear un nuevo contenedor Docker nuevamente sin pasar ningún argumento.

isaac@DESKTOP-HV44HT6:~/my-app$ docker run new_image
Hello, Developer

Sin embargo, el comando CMD se anulará automáticamente cuando pasemos un argumento en tiempo de ejecución, y el nuevo argumento debería tener prioridad. Por lo tanto, nos brinda la flexibilidad de agregar nuevos argumentos en tiempo de ejecución, como se muestra a continuación.

~/my-app$ docker run new_image hostname
da0a832888cb

El resultado anterior muestra que el comando CMD no se ejecuta ni se reemplaza por el argumento del nuevo nombre de host.

el comando ENTRYPOINT en Docker

El comando docker ENTRYPOINT tiene similitudes con el comando CMD, pero no del todo igual.

Cuando usamos el comando CMD, podemos anularlo fácilmente pasando argumentos en tiempo de ejecución, pero este no es el caso con el comando ENTRYPOINT.

Por lo tanto, ENTRYPOINT se puede usar para no anular la instrucción del punto de entrada en tiempo de ejecución.

Como se muestra a continuación, podemos explorar cómo funciona este comando simplemente reemplazando el comando CMD con el comando ENTRYPOINT en nuestro Dockerfile. Construiremos una nueva imagen basada en nuestros cambios en el archivo docker.

isaac@DESKTOP-HV44HT6:~/my-app$ docker build -t tonyloi_newimage .
[+] Building 42.7s (10/10) FINISHED

Producción :

 => [internal] load build definition from Dockerfile                                                                                                                          2.0s
 => => transferring dockerfile: 365B                                                                                                                                          0.7s
 => [internal] load .dockerignore                                                                                                                                             1.6s
 => => transferring context: 2B                                                                                                                                               0.4s
 => [internal] load metadata for docker.io/library/python:latest                                                                                                             35.4s
 => [1/5] FROM docker.io/library/python@sha256:c90e15c86e2ebe71244a2a51bc7f094554422c159ce309a6faadb6debd5a6df0                                                               0.3s
 => [internal] load build context                                                                                                                                             1.2s
 => => transferring context: 63B                                                                                                                                              0.1s
 => CACHED [2/5] WORKDIR /var/www/                                                                                                                                            0.0s
 => CACHED [3/5] COPY ./app.py /var/www/app.py                                                                                                                                0.0s
 => CACHED [4/5] COPY ./requirements.txt /var/www/requirements.txt                                                                                                            0.0s
 => CACHED [5/5] RUN pip install -r /var/www/requirements.txt                                                                                                                 0.0s
 => exporting to image                                                                                                                                                        2.1s
 => => exporting layers                                                                                                                                                       0.0s
 => => writing image sha256:15fb8e4e3ff58ed529b11342bba75b029fd4323beb24aac70ca36b178d04cb34                                                                                  0.2s
 => => naming to docker.io/library/tonyloi_newimage                                                                                                                           0.1s
isaac@DESKTOP-HV44HT6:~/my-app$

Este resultado es un testimonio de que hemos construido con éxito una nueva imagen. Ahora podemos crear un nuevo contenedor docker basado en esta imagen.

Puede elegir crear el contenedor usando el nombre de la imagen o la identificación de la imagen, a los cuales se puede acceder usando el comando docker images. Esto también mostrará las imágenes que creamos antes.

~/my-app$ docker images
REPOSITORY           TAG       IMAGE ID       CREATED          SIZE
tonyloi_newimage     latest    15fb8e4e3ff5   48 minutes ago   929MB
new_image            latest    73f323be0d2f   48 minutes ago   929MB
isaactonyloi_image   latest    5847e4777754   48 minutes ago   929MB

Si construimos nuestro contenedor docker sin agregar ningún argumento, deberíamos obtener un resultado como el siguiente.

isaac@DESKTOP-HV44HT6:~/my-app$ docker run tonyloi_newimage
Hello, Developer

Si tratamos de pasar argumentos al crear otro contenedor basado en esta imagen, notará que, a diferencia del caso del comando CMD, estos nuevos argumentos no anulan el comando ENTRYPOINT.

Podemos verificar esto a continuación.

isaac@DESKTOP-HV44HT6:~/my-app$ docker run tonyloi_newimage Welcome to ADC
Hello, Developer Welcome to ADC

Conclusión

Podemos afirmar que estos dos comandos son muy similares; sin embargo, su diferencia es que el comando CMD se puede anular en tiempo de ejecución mientras que el comando ENTRYPOINT no.

Además, las situaciones pueden justificar el uso de los dos comandos simultáneamente.

Autor: Isaac Tony
Isaac Tony avatar Isaac Tony avatar

Isaac Tony is a professional software developer and technical writer fascinated by Tech and productivity. He helps large technical organizations communicate their message clearly through writing.

LinkedIn

Artículo relacionado - Docker Command