Ejecuta tu imagen de Go como un contenedor
Requisitos previos
Completa los pasos para contenedorizar una aplicación de Go en Construye tu imagen de Go.
Resumen
En el módulo anterior creaste un Dockerfile para tu aplicación de ejemplo y luego creaste tu imagen de Docker usando el comando docker build. Ahora que tienes la imagen, puedes ejecutarla y ver si tu aplicación funciona correctamente.
Un contenedor es un proceso normal del sistema operativo, excepto que este proceso está aislado y tiene su propio sistema de archivos, su propia red y su propio árbol de procesos aislado separado del host.
Para ejecutar una imagen dentro de un contenedor, utilizas el comando docker run. Requiere un parámetro y ese es el nombre de la imagen. Inicia tu imagen y asegúrate de que se ejecute correctamente. Ejecuta el siguiente comando en tu terminal.
$ docker run docker-gs-ping
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.10.2
Framework web de Go de alto rendimiento y minimalista
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:8080Al ejecutar este comando, notarás que no regresaste a la línea de comandos de la terminal. Esto se debe a que tu aplicación es un servidor REST y se ejecutará en un bucle esperando solicitudes entrantes sin devolver el control al sistema operativo hasta que detengas el contenedor.
Realiza una solicitud GET al servidor utilizando el comando curl.
$ curl http://localhost:8080/
curl: (7) Failed to connect to localhost port 8080: Connection refused
Tu comando curl falló porque se rechazó la conexión a tu servidor. Esto significa que no pudiste conectarte a localhost en el puerto 8080. Esto es lo esperado porque tu contenedor se está ejecutando de forma aislada, lo que incluye la red. Detén el contenedor y reinícialo con el puerto 8080 publicado en tu red local.
Para detener el contenedor, presiona ctrl-c. Esto te devolverá al prompt de la terminal.
Para publicar un puerto para tu contenedor, usarás la bandera --publish (o -p para abreviar) en el comando docker run. El formato del comando --publish es [puerto_host]:[puerto_contenedor]. De modo que si deseas exponer el puerto 8080 dentro del contenedor al puerto 3000 fuera del contenedor, pasarías 3000:8080 a la bandera --publish.
Inicia el contenedor y expón el puerto 8080 al puerto 8080 en el host.
$ docker run --publish 8080:8080 docker-gs-ping
Ahora, vuelve a ejecutar el comando curl.
$ curl http://localhost:8080/
Hello, Docker! <3
¡Éxito! Pudiste conectarte a la aplicación que se ejecuta dentro de tu contenedor en el puerto 8080. Regresa a la terminal donde se está ejecutando tu contenedor y deberías ver la solicitud GET registrada en la consola.
Press ctrl-c to stop the container.
Presiona ctrl-c para detener el contenedor.
Ejecución en modo desacoplado (detached mode)
Esto es genial hasta ahora, pero tu aplicación de ejemplo es un servidor web y no deberías tener que mantener tu terminal conectada al contenedor. Docker puede ejecutar tu contenedor en modo desacoplado (detached) en segundo plano. Para hacer esto, puedes usar la bandera --detach o -d para abreviar. Docker iniciará tu contenedor de la misma manera que antes, pero esta vez se desacoplará del contenedor y te devolverá al prompt de la terminal.
$ docker run -d -p 8080:8080 docker-gs-ping
d75e61fcad1e0c0eca69a3f767be6ba28a66625ce4dc42201a8a323e8313c14e
Docker inició tu contenedor en segundo plano e imprimió el ID del contenedor en la terminal.
Nuevamente, asegúrate de que tu contenedor se esté ejecutando. Ejecuta el mismo comando curl:
$ curl http://localhost:8080/
Hello, Docker! <3
Listar contenedores
Dado que ejecutaste tu contenedor en segundo plano, ¿cómo sabes si tu contenedor se está ejecutando o qué otros contenedores se están ejecutando en tu máquina? Bueno, para ver una lista de contenedores que se ejecutan en tu máquina, ejecuta docker ps. Esto es similar a cómo se usa el comando ps para ver una lista de procesos en una máquina Linux.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 41 seconds ago Up 40 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
El comando ps te dice un montón de cosas sobre tus contenedores en ejecución. Puedes ver el ID del contenedor, la imagen que se ejecuta dentro del contenedor, el comando que se usó para iniciar el contenedor, cuándo se creó, el estado, los puertos que están expuestos y los nombres del contenedor.
Probablemente te estés preguntando de dónde proviene el nombre de tu contenedor. Como no proporcionaste un nombre para el contenedor cuando lo iniciaste, Docker generó un nombre aleatorio. Corregiremos esto en un minuto, pero primero debes detener el contenedor. Para detener el contenedor, ejecuta el comando docker stop, pasando el nombre o el ID del contenedor.
$ docker stop inspiring_ishizaka
inspiring_ishizaka
Ahora vuelve a ejecutar el comando docker ps para ver una lista de contenedores en ejecución.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Detener, iniciar y nombrar contenedores
Los contenedores de Docker se pueden iniciar, detener y reiniciar. Cuando detienes un contenedor, no se elimina, sino que el estado cambia a detenido y el proceso dentro del contenedor se detiene. Cuando ejecutaste el comando docker ps, la salida predeterminada es mostrar únicamente contenedores en ejecución. Si pasas --all o -a para abreviar, verás todos los contenedores en tu sistema, incluidos los contenedores detenidos y los contenedores en ejecución.
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" About a minute ago Exited (2) 23 seconds ago inspiring_ishizaka
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 2 minutes ago wizardly_joliot
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 3 minutes ago Exited (2) 3 minutes ago magical_carson
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 9 minutes ago Exited (2) 3 minutes ago gifted_mestorf
Si has estado siguiendo los pasos, deberías ver varios contenedores en la lista. Estos son contenedores que iniciaste y detuviste pero que aún no has eliminado.
Reinicia el contenedor que acabas de detener. Localiza el nombre del contenedor y reemplaza el nombre del contenedor en el siguiente comando restart:
$ docker restart inspiring_ishizaka
Ahora, vuelve a listar todos los contenedores usando el comando ps:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d75e61fcad1e docker-gs-ping "/docker-gs-ping" 2 minutes ago Up 5 seconds 0.0.0.0:8080->8080/tcp inspiring_ishizaka
f65dbbb9a548 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 2 minutes ago wizardly_joliot
aade1bf3d330 docker-gs-ping "/docker-gs-ping" 4 minutes ago Exited (2) 4 minutes ago magical_carson
52d5ce3c15f0 docker-gs-ping "/docker-gs-ping" 10 minutes ago Exited (2) 4 minutes ago gifted_mestorf
Observa que el contenedor que acabas de reiniciar se ha iniciado en modo desacoplado y tiene expuesto el puerto 8080. Además, ten en cuenta que el estado del contenedor es Up X seconds (Activo por X segundos). Cuando reinicias un contenedor, se iniciará con las mismas banderas o comandos con los que se inició originalmente.
Detén y elimina todos tus contenedores y echemos un vistazo a cómo solucionar el problema de los nombres aleatorios.
Detén el contenedor que acabas de iniciar. Busca el nombre de tu contenedor en ejecución y reemplaza el nombre en el siguiente comando con el nombre del contenedor en tu sistema:
$ docker stop inspiring_ishizaka
inspiring_ishizaka
Ahora que todos tus contenedores están detenidos, elimínalos. Cuando se elimina un contenedor, ya no se ejecuta ni se encuentra en estado detenido. En su lugar, el proceso dentro del contenedor se termina y se eliminan los metadatos del contenedor.
Para eliminar un contenedor, ejecuta el comando docker rm pasando el nombre del contenedor. Puedes pasar múltiples nombres de contenedor al comando en una sola línea de comandos.
De nuevo, asegúrate de reemplazar los nombres de los contenedores en el siguiente comando con los nombres de los contenedores de tu sistema:
$ docker rm inspiring_ishizaka wizardly_joliot magical_carson gifted_mestorf
inspiring_ishizaka
wizardly_joliot
magical_carson
gifted_mestorf
Ejecuta de nuevo el comando docker ps --all para verificar que todos los contenedores hayan desaparecido.
Ahora, abordemos el molesto problema de los nombres aleatorios. La práctica estándar es nombrar tus contenedores por la sencilla razón de que es más fácil identificar qué se está ejecutando en el contenedor y con qué aplicación o servicio está asociado. Al igual que las buenas convenciones de nomenclatura para las variables en tu código facilitan su lectura, lo mismo ocurre con la nomenclatura de tus contenedores.
Para nombrar un contenedor, debes pasar la bandera --name al comando run:
$ docker run -d -p 8080:8080 --name rest-server docker-gs-ping
3bbc6a3102ea368c8b966e1878a5ea9b1fc61187afaac1276c41db22e4b7f48f
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3bbc6a3102ea docker-gs-ping "/docker-gs-ping" 25 seconds ago Up 24 seconds 0.0.0.0:8080->8080/tcp rest-server
Ahora, puedes identificar fácilmente tu contenedor basándote en el nombre.
Siguientes pasos
En este módulo, aprendiste a ejecutar contenedores y publicar puertos. También aprendiste a administrar el ciclo de vida de los contenedores. Luego, aprendiste la importancia de nombrar tus contenedores para que sean más fácilmente identificables. En el próximo módulo, aprenderás a ejecutar una base de datos en un contenedor y conectarla a tu aplicación.