Compartir comentarios
Las respuestas se generan en base a la documentación.

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 [::]:8080

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