Comienza construyendo una imagen Docker bien papita de implementar en un contenedor, conoce elementos básicos para seguir el camino hacia la dockerización. Por esta vez, no es necesario que cuentes con código de aplicación para publicar 😎. Lo que buscas para entender mejor la construcción de imágenes y contenedores de Docker desde cero, aquí lo puedes encontrar. ¡De veras!
La Imagen, materia prima del contenedor
El contenedor Docker al final es la instancia de una imagen Docker; cuando la imagen pasa de sólo ocupar espacio de almacenamiento, y comienza a consumir memoria RAM, procesamiento, red, o sea cuando la pones a chambear papá.
Comentamos en un post, que existe un repositorio público de imágenes base Docker. Las imágenes base tienen archivos que tus aplicaciones pueden necesitar para su ejecución, pero principalmente traen los archivos mínimos del sistema operativo para que el contenedor viva. Y hay de dos sopas, o tus imágenes ejecutarán Linux o Windows, y depende del sistema operativo de la máquina Host; dicha máquina es aquella que trae el motor de Docker.
Entonces, comienzas desde una imagen base a la que posteriormente vas a agregar los archivos que necesites para lograr ejecutar algo.
Vamos al Ejemplo
Espero que ya tengas tu laboratorio listo para tirar comandos, si aún no lo tienes y trabajas con Windows 10, puedes darte una vuelta por nuestro post.
¿Qué haremos?
- Utilizar Nginx y crear un contenedor y usarlo desde el navegador
Comencemos
Como vamos a utilizar a Nginx, vamos a requerir de los archivos para ejecutarlo en Docker, y de hecho ya existe una imagen Docker con Nginx que podemos utilizar.
Verificamos qué imágenes tenemos actualmente, en nuestro caso no hay imágenes:
C:\Users\mix_i>docker images REPOSITORY TAG IMAGE ID CREATED SIZE C:\Users\mix_i>
Ahora, vamos a usar el siguiente comando
docker run -it --rm -d -p 8080:80 --name web nginx
El comando run hace que Docker genere un contenedor, lo demás son opciones para ajustar el comportamiento:
- -it: este es un método para utilizar dos operadores de forma conjunta, y normalmente siempre se usan así cuando se quiere un modo interactivo con el contenedor
- – – rm: se usa para que el contenedor se elimine cuando el proceso que se haya ejecutado en el contenedor termine. Útil para procesos o aplicaciones que se requiere realicen tareas de corta duración y que al finalizar su ejecución se liberen los recursos de forma automática
- -d: inicia el contenedor en segundo plano (proceso separado)
- -p: aquí mapeamos los puertos de nuestro Host con los puertos dentro del contenedor, el protocolo por default es TCP. En este ejemplo, estamos indicando que el puerto 8080 de la máquina Host queremos mapearlo con el puerto 80 del contenedor🧐, así que cuando enviemos peticiones a nuestra máquina Host por el puerto 8080, éstas llegarán al puerto 80 del contenedor
- – – name: es para asignarle un nombre a nuestro contenedor, y este ejemplo quisimos ponerle de nombre “web”
- nginx: este no es un comando u opción, lo que pasa es que al final del comando run, se debe especificar el nombre de la imagen a utilizar, y la imagen que deseamos es del web server nginx
El resultado de ejecutar el comando run es el siguiente:
docker run -it --rm -d -p 8080:80 --name web nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx a330b6cecb98: Already exists e0ad2c0621bc: Pull complete 9e56c3e0e6b7: Pull complete 09f31c94adc6: Pull complete 32b26e9cdb83: Pull complete 20ab512bbb07: Pull complete Digest: sha256:853b221d3341add7aaadf5f81dd088ea943ab9c918766e295321294b035f3f3e Status: Downloaded newer image for nginx:latest 68dcf0f3ba7d2dd9fa4367c0fe660c579b0fd2e680c6f619d7933faea6019b05
Debido a que necesitamos contar con una imagen en nuestra máquina Host para crear el contenedor, se observa que al no encontrar una imagen con nombre “nginx” de forma local, automáticamente intentará descargar una del repositorio Docker Hub. Después de la descarga, se crea el contenedor a partir de la imagen.
Podemos revisar las imágenes que tenemos, y comprobar que ahora sí obtenemos información, a diferencia de cuando ejecutamos el comando anteriormente
C:\Users\mix_i>docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx latest ad4c705f24d3 2 days ago 133MB
Por otro lado, podemos listar los contenedores activos, lo que esperamos es ver 1 contenedor activo, para ello, utilizamos el comando “ps”
C:\Users\mix_i>docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 68dcf0f3ba7d nginx "/docker-entrypoint.…" 8 minutes ago Up 8 minutes 0.0.0.0:8080->80/tcp, :::8080->80/tcp web
Como se observa, la salida default del comando es a modo de tabla, donde vemos la imagen que utiliza el contenedor, cuánto tiempo tiene que se creó la instancia, el estatus actual, y el mapeo de los puertos. Finalmente, en la columna Name, vemos el nombre que asignamos al contenedor. Un dato importante a tener en cuenta es el ID del contenedor, lo usaremos cuando ejecutemos un comando Docker que lo requiera; dicho dato siempre es distinto entre contenedores, y cambia si el contenedor se elimina y se vuelve a crear, en realidad es una cadena más larga de lo que se ve.
Para probar el contenedor, en una ventana de navegador vamos a la URL: http://localhost:8080
Lo que ocurre es que las peticiones llegan a la máquina Host por el puerto 8080, y son enviadas dentro del contenedor a su puerto 80. Esto es por el mapeo que realizamos en el comando “run”, ¿Porqué el contenedor usa el puerto 80? pues por ser el default en el que Nginx escucha peticiones, aunque esto se puede cambiar; si has utilizado Internet Information Services, siglas IIS (el aya yay), te parecerá familiar.
Aunque también, las peticiones llegan al contenedor porque la máquina Host tiene varias redes (networks) configuradas por default, una de ellas, llamada “bridge” es la red a la que por default un contenedor se conecta cuando lo creas, a no ser que indiques otra cosa. Para que veas este hecho, y siguiendo nuestro ejemplo, ejecuta lo siguiente:
docker network disconnect bridge web
Y ahora vuelve a ejecutar la URL http://localhost:8080 (puede que sea necesario que borres caché de tu navegador), entonces deberás de ver un error de que no puedes acceder a la URL. Para volver a conectar el contenedor a la red, ejecuta lo siguiente:
docker network connect bridge web
Vuelve a probar para corroborar que funciona como al principio 😰
Por último, ¿Recuerdas la opción – – rm que usamos al crear el contenedor?, pues para probar que nuestro contenedor se elimina de forma automática, lo que haremos es detener el contenedor con este comando
docker stop 68dcf0
¿68dcf0? Recuerda que en líneas anteriores, el ID de nuestro contenedor fue “68dcf0f3ba7d”, usamos el dato para referirnos a un contenedor en particular dentro de un comando de Docker, y puedes escribir el ID completo, o algunos primeros caracteres, que no coincidan con los primeros caracteres de otro contenedor al que no quieres afectar.
Revisamos los contenedores activos y no activos con el comando “ps” y opción “-a” (para mostrar contenedores sin importar su estatus) de la siguiente manera
docker ps -a
Cómo puedes ver, no hay resultados, eso quiere decir que después de detenerse el contenedor, éste se eliminó 😦
Puedes volver a ejecutar el comando “run” con las mismas opciones, pero quitando la opcion “- – rm” para volver a crear el contenedor, pero esta vez si detenemos el contenedor no se eliminará
docker run -it -d -p 8080:80 --name web nginx cc72ef6a3a3ce306080c56853f2a782b92c7cb3522b7ab3968141498f2f6297a
Debido a que ya contábamos con la imagen “nginx”, no fue necesario descargarla, entonces la salida del comando muestra el ID del contenedor que se generó, observa que ya no es el mismo de antes 🤨.
Revisamos nuevamente los contenedores activos:
docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc72ef6a3a3c nginx "/docker-entrypoint.…" 11 seconds ago Up 10 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp web
Ahora detenemos el contenedor
docker stop cc72ef
Después ejecutamos el comando “ps” con la opción “-a” para ver todos los contenedores independiente de su estatus:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cc72ef6a3a3c nginx "/docker-entrypoint.…" 7 minutes ago Exited (0) 6 seconds ago web
Como puedes ver, ahora el contenedor no se eliminó, y si intentas probar la URL, verás que no funcionará ya que el contenedor está detenido. Para eliminar manualmente el contenedor, ejecutamos el comando “rm” así
docker rm cc72ef cc72ef
La salida del comando “rm” es el id del contenedor que se eliminó, si todo fue bien.
Hasta aquí hemos utilizado comandos de uso general para imagen y contenedor, utilizamos una imagen Nginx que podamos echar a andar muy fácilmente para ejemplificar.
Aunque llegues a sentir cierto gusto por tirar comandos a diestra y siniestra para crear tus contenedores, llegará el día donde necesites agilizar esos procesos, para ello conocerás Dockerfile en un siguiente post… y tu vida cambiará 😎 ¡De veras!
Ingeniero en Comunicaciones y Electrónica, dedicado al desarrollo de software y apoyo a la comunidad en temas de tecnología, especialmente en temas de IA. En lo personal disfruto practicar guitarra, viendo algún buen anime.
Pingback: Crear Imagen y Contenedor Docker Nivel Chūnin – CodecX
Pingback: Crear Imagen y Contenedor Docker Nivel Jōnin – CodecX