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.
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