Como ya sabrás, Docker es una herramienta increíble para el trabajo de programación colaborativo, permitiéndonos trabajar en un entorno virtualmente idéntico, sin importar el sistema operativo en el que estemos.

En un artículo anterior aprendimos a crear nuestras propias imágenes de Docker para probar y distribuir nuestras aplicaciones sin preocuparnos de sus dependencias.

Ahora vamos a ver una forma sencilla de ejecutar contenedores Docker.

Docker run para ejecutar contenedores Docker: descubre cómo hacerlo de una manera sencilla

Después de crear nuestra imagen de ejemplo en el artículo anterior, finalizamos ejecutando el comando:

docker run --name pandora_community --rm \
-p 8085:80 \
-p 41121:41121 \
-p 162:162 \
-e DBHOST=mysqlhost.local \
-e DBNAME=pandora \
-e DBUSER=pandora \
-e DBPASS=pandora \
-e DBPORT=3306 \
-e SLEEP=5 \
-e RETRIES=3 \
-e INSTANCE_NAME=pandora_community \
-ti rameijeiras/pandorafms-community:740

Con este comando inicializamos nuestro contenedor Docker usando la imagen previamente creada. Pero, ¿qué es exactamente lo que hemos ejecutado? ¿Qué significan todos estos parámetros? Para saber la respuesta, hoy veremos cómo se ejecuta el comando docker run y sus parámetros más utilizados.

Vamos a comenzar desde lo más básico; podemos ejecutar el comando docker run sin ningún parámetro, por ejemplo utilizando el comando:

docker run hello-world

El cual devolverá una salida como esta:

docker run 1

En este caso levantará un contenedor con la imagen hello-world; si no la tenemos descargada, conectará con el repositorio de DockerHub, la descargará y la ejecutará.

Como podéis ver, simplemente ejecuta el entrypoint o CMD por defecto (según sea el caso) y al terminar la ejecución el contenedor se saldrá, quedando almacenado en nuestro ordenador.

Si te interesa Docker, te interesará conocer el estado de tus sistemas, ¿verdad?

Si es así, tenemos algo que contarte. Un programa de monitorización gratuito para que pruebes necesites donde necesites: casa, despacho, oficina, empresa… Este software lo monitoriza todo:

El comando docker ps

Si ejecutamos el comando:

docker ps -a

Podremos ver todos los contenedores que hemos ejecutado en nuestro sistema. El parámetro -a indica que los muestre todos, los que están corriendo y los que no. Por defecto, sin este parámetro solo mostrará los contenedores que están corriendo; si lo ejecuto en mi sistema veremos la salida:

docker run 2

Vamos a analizar esta salida para comprender los campos que nos está mostrando. Lo primero que podemos ver es que tenemos 3 contenedores (3 líneas) en este sistema. La primera línea es la referente a nuestra ejecución de hello-world; los otros dos contenedores ya estaban corriendo en mi sistema y los he dejado para contrastar la información que nos devuelve.

Como podemos ver, el comando docker ps nos devuelve información relacionada con nuestros contenedores. Veamos qué información nos está mostrando:

  1. Container id: Es el identificador único o ID de cada contenedor. Este id es asignado automáticamente por Docker.
  2. Image: En esta columna nos indica la imagen que utilizamos para levantar el contenedor; si miramos la última línea podemos ver que hemos usado la imagen hello-world en nuestra primera ejecución docker run.
  3. Command: Es el comando de inicio de los contenedores; se define en el dockerfile con la sentencia CMD y es lo que se ejecuta por defecto al iniciar el contenedor. Este comando se puede modificar cuando ejecutamos un contenedor, lo veremos más adelante.
  4. Created: Nos indica hace cuánto tiempo se ejecutó nuestro contenedor.
  5. Status: Nos indica el estado actual de nuestro contenedor. Como podéis ver nuestro hello-world se ejecutó y murió, por lo que nos muestra el estado exit y entre paréntesis el código de error de esta salida, en este caso 0. Esto será muy útil para debugear nuestra aplicación en caso de que algo fallara y el contenedor terminara de forma inesperada.
  6. Ports: Este apartado es muy importante, ya que nos indica qué puertos están expuestos de nuestro contenedor. En el caso de nuestro hello-world no hay ningún puerto expuesto. Como sabéis, un contenedor está aislado del sistema, por lo que para tener acceso a la aplicación que esté corriendo debemos exponer el puerto correspondiente. No solo podemos exponer los puertos, también los podemos reenviar indicando que el puerto X en nuestro sistema host está redireccionado al puerto Y dentro del contenedor. De esta forma podemos dar acceso externo a nuestras aplicaciones en la red. Hay otras formas de dar estos accesos, pero son más avanzadas. Por lo general usamos el redireccionamiento de puertos, el cual aprenderemos a hacer en este artículo.
  7. Name: Es el nombre asignado a nuestro contenedor; por defecto Docker asigna un nombre a nuestros contenedores automáticamente, pero es posible indicar el nombre que deseemos en la ejecución del docker run.

Ejecutando docker run

Ahora que sabemos cómo obtener el estado y características de nuestros contenedores, veamos qué podemos hacer con el comando docker run. Vamos a repasar los parámetros que considero más útiles. Para una información más profunda del comando docker run podéis buscar en la documentación oficial de Docker: https://docs.docker.com/engine/reference/run/

Primero veamos la estructura del comando docker run:

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

Como podemos ver, los parámetros u opciones irán justo antes del nombre de la imagen que queramos utilizar. Seguidamente podemos indicar un comando con sus propios argumentos que sobrescribiría el CMD por defecto de la imagen. Hagamos un ejemplo ejecutando:

docker run alpine

Con esta sentencia estamos indicando a Docker que ejecute un contenedor con la imagen llamada alpine con las opciones por defecto. Alpine es una distribución de Linux muy pequeña y utilizada en el mundo de los contenedores. Si no definimos ningún tag a la imagen, utilizará por defecto latest.

El resultado de este comando será similar a:

docker run 3

En el que se descargará la imagen:tag en caso de no tenerla, y ejecutará un contenedor con esta imagen. Como por defecto el comando de esta imagen es sh, se ejecuta, no da ninguna salida y se cierra, como podemos ver si ejecutamos un docker ps -a

docker run 4

Hay modificadores para mantener el contenedor corriendo con el comando sh pero eso lo veremos más adelante. Por ejemplo, vamos a sobreescribir el comando por defecto usando ifconfig para obtener la dirección ip interna del contenedor. Así que ejecutaremos:

docker run alpine ifconfig

Que nos devolverá la salida del comando ifconfig dentro del contenedor alpine:

docker run 5

Ahora ejecutaremos el mismo docker run, pero pasando un parámetro con el nombre de la interfaz al comando ifconfig para que solo nos devuelva la información de la interfaz eth0, y obtendremos:

docker run 6

Como veis, podemos pasar cualquier parámetro al comando que definamos a nuestro contenedor.

Echemos un vistazo a nuestra lista de contenedores con un docker ps -a

docker run 7

Están todas nuestras ejecuciones allí con los comandos que hemos definido. Hay una opción para indicar a Docker que elimine el contenedor una vez que se ejecute; lo veremos más adelante.

Parámetros docker run

Ya hemos aprendido a ejecutar un contenedor y a sobrescribir el comando que tiene por defecto; ahora veremos las opciones o parámetros que nos permiten modificar o añadir funcionalidades a nuestros contenedores.

Deatached (-d)

Es un operador que nos permite indicar a Docker que corra el contenedor en segundo plano, dejando el prompt libre mientras el contenedor sigue activo. Por ejemplo, podemos ejecutar:

docker run -d hello-world

No veremos la ejecución del contenedor, ya que se ejecutará en segundo plano. Es útil para servicios o tareas largas que no queremos que mantengan ocupado el prompt.

Foreground/interactive (-it)

Si por el contrario lo que queremos es mantener el contenedor en ejecución e incluso interactuar con él, podemos usar el parámetro -it. Como sabemos que el comando por defecto de alpine es sh (un shell más ligero que bash) podemos usar el parámetro -it para interactuar con él y lanzar diferentes comandos dentro del contenedor.

docker run -it alpine

Como podemos ver, esto nos permitirá interactuar con alpine directamente desde la shell.

docker run 8

Name (–name)

Este parámetro nos permitirá asignar un nombre a nuestro contenedor. Como comentaba anteriormente, Docker asignará un nombre aleatorio a nuestros contenedores, pero podemos asignarlo directamente desde la ejecución del docker run.

Ojo con esta opción, ya que el nombre es único y solo un contenedor puede tener ese nombre, por lo que si tenemos un contenedor (corriendo o parado) con un nombre que queramos usar en el comando docker run, Docker no nos lo permitirá, tendremos que elegir otro nombre o eliminar el contenedor antiguo con el nombre asignado.

Para asignar el nombre “test” a un contenedor de la imagen alpine podemos ejecutar:

docker run --name test alpine

docker run 9

Clean up (–rm)

Con el parámetro –rm indicamos a Docker que elimine el contenedor al terminar la ejecución; de esta forma no tendremos almacenadas todas las ejecuciones de nuestros contenedores. Para usar el parámetro –rm en un contenedor alpine que muestre el mensaje “hola mundo” y luego se autoelimine podemos usar :

docker run --rm alpine echo “hola mundo”

docker run 10

EXPOSE (incoming ports)

Podemos exponer puertos de nuestro ordenador que se redirijan a otro puerto en nuestro contenedor.

Por ejemplo, si queremos ejecutar un contenedor con un servidor web y queremos que se pueda acceder desde fuera al contenedor, tenemos que exponer un puerto.

Para exponer un puerto utilizamos el formato: [ip]:host_port:container_port

El campo [ip] se utiliza para filtrar los orígenes; si no se define quiere decir todos (0.0.0.0).
Para redireccionar por ejemplo el puerto 8080 de mi ordenador, desde cualquier origen, al puerto 80 de un contenedor que utilice la imagen nginx:alpine solo debo ejecutar:

docker run -d -p 8080:80 nginx:alpine

He utilizado el parámetro -d para que el contenedor esté corriendo en segundo plano, ya que Nginx es un servidor web que se seguirá ejecutando hasta que lo paremos, y si no usamos -d mantendrá ocupado el prompt.

docker run 11

Como podemos ver el contenedor se mantiene en segundo plano en estado running. Si hago un curl a mi propia máquina en el puerto 8080, me redirige al servidor Nginx corriendo en el Docker, que tiene expuesto el puerto 80.

Si hacemos un docker ps, en la columna PORTS podemos ver la redirección del puerto 8080 al 80 desde todos los orígenes.

Es posible usar el parámetro -P (mayúscula), que redireccionará todos los puertos expuestos de un contenedor. Perdemos el control de elegir en qué puerto queremos redireccionar, pero para hacer pruebas rápidas puede ser útil.

Por ejemplo, si ejecutamos la imagen base que creamos en el artículo anterior que exponía diversos puertos, podemos ver como Docker los redireccionará todos asignando puertos aleatorios.

docker run -P -d rameijeiras/pandorafms-base sleep 100

En este caso he utilizado el comando sleep 100 para mantener vivo el contenedor por 100 segundos. Además, he usado el parámetro -d para que se mantenga en segundo plano y he usado el parámetro -P para redireccionar todos los puertos expuestos en la imagen.

docker run 12

ENV environment variables (-e)

Con el parámetro -e podemos definir variables de entorno para el contenedor que iniciemos; esto es especialmente útil cuando nuestro contenedor está configurado para usar estas variables de entorno y modificar su comportamiento. Como vimos en el artículo anterior, nuestro contenedor de Pandora FMS utilizaba las variables de entorno para definir la base de datos a la que se conectaría y sus credenciales de conexión. Para definir variables de entorno podemos ejecutar:

docker run -e "APP=PandoraFMS" -e "VER=740" alpine echo "$APP $VER"

docker run 13

Como podemos ver, dentro del contenedor se asignaron las variables de entorno que hemos definido en la ejecución del comando docker run.

VOLUME shared filesystems (-v)

El parámetro -v sirve para gestionar volúmenes en Docker. Como sabemos, los datos que modifiquemos dentro de Docker son volátiles, pero usando -v podemos configurar persistencia de datos. Esto es especialmente útil para levantar un contenedor de bases de datos o servidores web, por ejemplo.

Con el parámetro -v podemos hacer 2 cosas diferentes; si lo ejecutamos seguido de un nombre de volumen crearemos un volumen persistente que manejara Docker, por ejemplo:

docker run --rm -v myvolume:/app alpine sh -c "echo persistent > /app/file"
docker run --rm myvolume:/app alpine cat /app/file

docker run 15

Como podéis ver, hemos ejecutado dos contenedores que se autodestruyen, apuntando al volumen myvolume, pero aunque el primer contenedor se destruyó al crear el fichero, el segundo es capaz de acceder a los datos, ya que el directorio app está vinculado a un volumen persistente en nuestra máquina host.

Podéis ver los volúmenes creados en vuestra máquina ejecutando el comando docker volume ls. El tema de volúmenes en contenedores Docker lo veremos en otra entrada de este blog.

El segundo método es el método bind, que lo que hace es “pasar” un directorio de nuestra máquina host al contenedor. Esto nos permitirá configurar y modificar ficheros en nuestra máquina local y que estos afecten directamente al contenedor. Si por ejemplo quiero mostrar mi web, que he puesto en mi directorio local /tmp/web/index.html, en un contenedor Nginx, tendría que ejecutar el comando docker run referenciando el directorio fuente y destino con este formato: -v host_path:container_path:[rw/ro], en el que opcionalmente podemos definir los permisos de lectura y escritura de este directorio; lo dejaremos por defecto. El comando sería:

docker run -d -p 8080:80 -v /tmp/web/:/usr/share/nginx/html nginx:alpine

docker run 15

Como podéis ver, si hago un bind a mi contenedor y luego edito localmente los ficheros, los cambios son inmediatos en mi servidor Nginx.

Docker y Pandora

Ya conocemos todos las opciones básicas de docker run, por lo que en este punto ya somos unos shinobis de Docker y vamos a poner a prueba nuestras habilidades usando todo lo aprendido para levantar un stack completo de Pandora FMS.

Utilizaremos dos contenedores, uno para la aplicación y otro para la base de datos. No solo eso, al servidor de base de datos le daremos persistencia para que en caso de fallos no se pierda la información almacenada.

Solo necesitaremos 2 comandos docker run; sí, así de fácil.

En el primero iniciaremos un contenedor para la base de datos. Utilizaremos una imagen modificada de Percona Sql. Puedes ver el dockerfile en mí repo de GitHub (a estas alturas serás un maestro leyendo dockerfiles).

docker run --name Pandora_DB \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=pandora \
-e MYSQL_DATABASE=pandora \
-e MYSQL_USER=pandora \
-e MYSQL_PASSWORD=pandora \
-v mysqlvol:/var/lib/mysql \
-d rameijeiras/pandorafms-percona-base

Esperamos un par de segundos y ya tenemos nuestra base de datos corriendo.

docker run 16

Ahora ejecutamos el contenedor de Pandora FMS que apunte al contenedor de base de datos. Podemos apuntar tanto a la IP interna como a la externa. Como hemos hecho la redirección de puertos para el puerto 3306, usaremos la IP externa que, en este caso, será la IP de mi host.

docker run --name Pandora_new --rm \
-p 8081:80 \
-p 41121:41121 \
-e DBHOST=192.168.85.128 \
-e DBNAME=pandora \
-e DBUSER=pandora \
-e DBPASS=pandora \
-e DBPORT=3306 \
-e SLEEP=5 \
-e RETRIES=3 \
-e INSTANCE_NAME=pandora \
-ti rameijeiras/pandorafms-community:740

docker run 17

Y ya tendríamos nuestra instancia de Pandora FMS Community en su versión 740 con solo dos comandos. Impresionante.

Comprobemos que todo está en orden; desde el navegador vamos a la dirección http://<host_ip>:8081/pandora_console.

docker run 18

Ahora simplemente hacemos login con las credenciales admin:pandora y tendremos acceso a la consola web de Pandora FMS.

docker run 19

En siguientes entradas, aprenderemos a usar el orquestador docker-compose para gestionar nuestros contenedores Docker de forma aún más rápida, sencilla y eficaz. Así que quédate atento a los posts que vienen, para aprender a sacar el mayor partido de tus aplicaciones en contenedores Docker.

Además, si quieres saber cómo crear contenedores Docker para desplegar aplicaciones puedes echar un vistazo a este vídeo:

Para finalizar, recuerda que puedes conocer mucho más acerca de Pandora FMS entrando en nuestra página de inicio.

O si tienes que monitorizar más de 100 dispositivos también puedes disfrutar de una DEMO GRATUITA de 30 días de Pandora FMS Enterprise. Consíguela aquí.

Shares