Entrypoints, argumentos y variables de entorno
Ya hemos visto como se consumen imágenes de contenedor, como se construyen imágenes propias y como se gestionan los contenedores pero seguiríamos sin ser capaces de consumir imágenes de dockerhub si no sabemos cómo configurarlas y adaptarlas a nuestras necesidades.
Dentro vídeo: https://youtu.be/bd8EoJbKmwQ
Además, veremos como hacer nuestros contenedores más flexibles y dinámicos, es decir que se puedan adaptar a diferentes situaciones y entornos. Para ello, vamos a ver cómo utilizar las instrucciones ENTRYPOINT
, CMD
, argumentos y variables de entorno en nuestros Dockerfiles.
En este episodio complementaremos las instrucciones de Dockerfile pendientes y esenciales en nuestro día a día. Estas abarcarán la instrucción ENTRYPOINT
, CMD
, la posibilidad de pasar argumentos a nuestro proceso de construcción y la definición de variables de entorno. Por último, veremos cómo pasar variables de entorno a nuestros contenedores en ejecución.
ENTRYPOINT y CMD
En Dockerfile, las instrucciones ENTRYPOINT
y CMD
son las que definen qué comando se ejecutará cuando se inicie un contenedor. Tienen una funcionalidad similar, pero con una diferencia importante.
La instrucción ENTRYPOINT
define el comando que se ejecutará cuando se inicie un contenedor. Si se especifica un ENTRYPOINT
, este comando se ejecutará siempre que se inicie el contenedor, y cualquier comando que se pase al contenedor se ejecutará como argumentos del ENTRYPOINT
.
Por otro lado, la instrucción CMD
también define el comando que se ejecutará cuando se inicie un contenedor, pero si se especifica un CMD
, será sobre escrito por cualquier comando que se pase al contenedor.
Es decir, si se especifica un ENTRYPOINT
, este comando se ejecutará siempre que se inicie el contenedor, y cualquier comando que se pase al contenedor se ejecutará como argumentos del ENTRYPOINT
. Si se especifica un CMD
, este comando se ejecutará solo si no se especifica un comando al iniciar el contenedor.
Por ejemplo, si tenemos un Dockerfile con las siguientes instrucciones:
FROM alpine
ENTRYPOINT ["echo", "Hola"]
CMD ["Mundo"]
Y construimos la imagen con el comando docker build -t saludador .
, al iniciar un contenedor con el comando docker run saludador
, se ejecutará el comando echo Hola Mundo
.
Si queremos sobreescribir el comando CMD
, podemos hacerlo con el comando docker run saludador dockermaniatico
, y se ejecutará el comando echo Hola dockermaniatico
. Es decir, todas las instrucciones que se pasen al comando docker run después del nombre de la imagen se ejecutarán como argumentos del ENTRYPOINT
.
Esto nos da la flexibilidad de modificar el comportamiento de un contenedor sin tener que modificar el Dockerfile y dar más flexibilidad a los usuarios que consumen nuestra imagen.
Argumentos en Dockerfile y Docker build
Además de ENTRYPOINT
y CMD
, podemos pasar argumentos a nuestro proceso de construcción y definir variables de entorno en nuestro Dockerfile.
Para pasar argumentos a nuestro proceso de construcción, podemos utilizar la instrucción ARG
. Por ejemplo, si queremos pasar un argumento a nuestro Dockerfile, podemos hacerlo de la siguiente manera:
FROM alpine
# Declarar un argumento con un valor predeterminado
ARG NOMBRE="Mundo"
# Crear un archivo que contenga el mensaje personalizado
RUN echo "Hola $NOMBRE" > /message
# Comando predeterminado para mostrar el contenido del archivo
CMD ["cat", "/message"]
En este caso, estamos definiendo un argumento NOMBRE
con el valor por defecto Mundo
. Si construimos la imagen con el comando docker build -t saludador .
, al iniciar un contenedor con el comando docker run saludador
, se ejecutará el comando echo Hola Mundo
.
También podemos sobreescribir el argumento NOMBRE
, durante el proceso de construcción, con el comando docker build --build-arg NOMBRE=dockermaniatico -t saludador .
, y al iniciar un contenedor con el comando docker run saludador
, se ejecutará el comando echo Hola dockermaniatico
. Podríamos especificar el parámetro --build-arg
tantas veces como argumentos tengamos en nuestro Dockerfile.
Esto nos permite adaptar nuestro proceso de construcción a diferentes situaciones y entornos, sin tener que modificar el Dockerfile, o simplemente, variabilizar el proceso de construcción para reutilizar variables en diferentes partes del Dockerfile.
Por ejemplo, un dockerfile en el que usemos una variable múltiples veces:
FROM alpine
ARG service=web
RUN echo "Instalando $service"
COPY $service /$service/app
Variables de entorno en Docker run
Por último, vamos a ver cómo pasar variables de entorno a nuestros contenedores en el momento de ejecutarlos. Para ello, podemos utilizar el comando docker run
con la opción -e
o --env
.
Esto nos permite preparar nuestra aplicación para diferentes entornos o casuísticas, sin tener que modificar el Dockerfile ni reconstruir la imagen. Por ejemplo, si tenemos una aplicación que necesita una variable de entorno DEBUG
para activar o desactivar el modo de depuración, podemos hacerlo de la siguiente manera:
docker run -e DEBUG=1 mi_aplicacion
También podríamos preparar el código de nuestra aplicación para leer estas variables y actuar en consecuencia. Por ejemplo, si tenemos una aplicación en Python que necesita la variable de entorno DEBUG
, podríamos hacerlo de la siguiente manera:
import os
if os.getenv("DEBUG"):
print("Modo de depuración activado")
else:
print("Modo de depuración desactivado")
De esta manera, podemos hacer que nuestra aplicación sea más flexible y dinámica, y se pueda adaptar a diferentes situaciones y entornos.
Ser lo más agnóstico posible
La filosofía de los contenedores es ser lo más agnóstico posible, es decir, que no dependan de un entorno concreto y se puedan ejecutar en cualquier entornos, cliente y caso de uso. Por eso, es importante configurar nuestras imágenes para que no dependan de variables estáticas y que se puedan adaptar a diferentes situaciones.
Por ejemplo, una base de datos, funciona igual para todas las personas que desplegarían un contenedor con una base de datos de mariadb, pero cada uno necesitaría una configuración diferente, como el nombre de la base de datos, el usuario, la contraseña, etc. Por eso, es importante que nuestra imagen sea lo más flexible posible y se pueda adaptar a diferentes situaciones y entornos.
Con esta entrada y la anterior, ya tendríamos todas las instrucciones de Dockerfile esenciales para construir imágenes de contenedor y gestionar contenedores en Docker. En los próximos episodios, veremos cómo gestionar imágenes y cómo trabajar con volúmenes y redes.
- Lista de vídeos en Youtube: Curso de Docker