Docker – Guía Rápida
Mini guía:
primeros pasos
Bienvenido/a este pequeño tutorial enfocado al manejo de contenedores y todo lo relacionado a la virtualización. Antes de arrancar e instalar lo que necesitamos, es fundamental entender algunas cuestiones básicas.
Un resumen rápido:
• ¿Qué es y para qué sirve Docker? “Docker es una herramienta que permite empaquetar una aplicación y sus dependencias en un contenedor muy ligero. Es como si tomaras una app completa con absolutamente todo lo que necesita para funcionar, de modo que se pueda transportar sin problema a cualquier otro servidor con Docker instalado, ya sea para seguir desarrollándola o para hacer deploy. Esto significa que podremos trabajar en un entorno Windows, Linux o Mac, con tener previamente configurada dicha tecnología. Docker, a diferencia de las máquinas virtuales, trabaja con contenedores para que nuestros proyectos puedan ejecutarse de manera abstracta compartiendo el kernel del Sistema Operativo. Es decir, cada contenedor opera como un proceso aislado dentro del entorno del usuario y a su vez ocupan una cantidad reducida de espacio. En base a esto último, es clave saber que Docker no es una máquina virtual (VM). Recordar que las máquinas virtuales, a diferencia de los contenedores, toman recursos del S.O para poder arrancar y virtualizar el funcionamiento de la parte del hardware. Conllevando a que en algunos casos, podría ocurrir que el tiempo de carga al iniciar la o las VMS sea significativamente superior. En definitiva, Docker se desacopla de algunas capas, y corre las apps con los ficheros que ellas necesitan.”
Docker – Guía Rápida25-05-2021Con el siguiente gráfico se deja más claro lo que se mencionó antes. Las aplicaciones interaccionan de forma directa con Docker, y éste al mismo tiempo con el S.O.
Por último, dos cosas. La primera es que hay que tener en cuenta que Docker no es necesario para todos nuestros trabajos; por un lado, va a añadirle una capa más de complejidad que previamente debe ser considerada según el proyecto que vayamos a encarar. Por el otro, es una herramienta que debería utilizarse para solucionar un problema que existe o es probable que llegue a encontrarse. La segunda cuestión, es que hay dos versiones: la versión Docker EE (Enterprise Edition), de pago y con funciones adicionales para sacarle el máximo provecho. Y su contraparte, Docker CE (Community Edition), de código abierto. Aclaro que con esta última vamos a trabajar, señalando que es una genialidad. Ahora si, ¡vamos con todo!
Instalación en Linux:
Perdón a todas aquellas personas amantes de Windows y Mac, pero me voy a enfocar en distribuciones Linux basadas en Ubuntu, ya que actualmente estoy trabajando con Mint. Si necesitan información de cómo instalar Docker en dichos sistemas, al final de este documento encontrarán enlaces relacionados.(1)
Bien. Asumiendo que tenés conocimientos básicos del manejo de la consola, los siguientes comandos te permitirán instalarlo en tu equipo. Si no sabés iniciar la terminal, podes hacerlo tecleando Ctrl+Alt+T o dirigiéndote hacia el ícono que se encuentra en el panel. Comandos para distribuciones basadas en Ubuntu:(2)
•sudo apt-get update
•sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common
•curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
•sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(. /etc/os-release; echo "$UBUNTU_CODENAME") stable"
•sudo apt-get update
•sudo apt-get -y install docker-ce
•sudo docker –version
(1) Puede llegar a fallar o andar mal si un contenedor Linux corre en un servidor Windows. Loaconsejable es que opere en un mismo server.
(2) Si no tenés instalado curl, basta con hacer un sudo apt update & sudo aptupgrade, seguido de sudo apt install curl y por último curl –version
Una vez ya instalado, vamos a dirigirnos hacia el directorio Documentos/Documents y creamos un directorio para nuestro proyecto. El mismo, lo vamos a hacer con NodeJS+Express. Algo sencillo... ¡a no preocuparse! Seguí los siguientes pasos:
• Abrir la consola y ejecutar ls (para listar).
•Ingresamos a Documentos con el comando cdDocumentos.
•Una vez estando ahí, ponemos mkdir proyecto_node. Este comando va a crear un directorio el cual se va a llamar “proyecto_node”. Posteriormente, ingresamos a él con cd.
•Ahora es momento de hacer nuestro pequeño programa para luego dockerizarlo. Podes utilizar tu editor de código favorito, en mi caso voy a usar VIM. Para empezar a codear, simplemente poné <editor> server.js. Por ejemplo: atom server.js o si preferís y usas VSC, tan solo pones code . y creas un fichero ahí mismo con ese nombre.
Genial. Ahora que ya estamos listos para editar. Vamos a plasmar lo básico y necesario.
Explicación nivel Speedy Gonzalez:
• Importamos el módulo de Express, el cual posteriormente instalaremos. Configuramos el Router y la forma con la que queremos trabajar, en este caso con el método json() para reconocer el objeto de la solicitud entrante como un objeto JSON. Valga la redundancia. Luego creamos una ruta tipo GET para obtener un simple mensaje. Paso siguiente, con app.use le indicamos al router cómo deben definirse las rutas. En este caso le especifiqué /docker. Adicional, si la URL ingresada no corresponde, mostrará elmensaje por default de error. Por último, creamos una constante “puerto” con una variable de entorno asignada (esto por si se despliega en un server que automáticamente le asigna un puerto para iniciar). En este caso, va a correr en el 3000. Luego se encapsuló dicha variable (configuración dinámica) para finalmente indicarle a la constante “server” dónde tiene que lanzarse. Por consola podrás visualizar los siguientes mensajes: si todo está ok o si todo no está ok. ;)
•Guardamos los cambios y volvemos a la consola. Ejecutamos el siguiente comando: npm init –y (3)
•Ejecutamos ls y vemos que se nos generó un package.json. Lo editamos y le añadimos dos cosas nada más: type y engines. Guardamos los cambios.
(3) si no tenés instalado Node ni el gestor NPM, basta con que lo descargues con los siguientes comandos: curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -, luego sudo apt-get install -y nodejs
•Perfecto. Ya casi terminando con esta parte, instalamos Express con npm i express. Quedando en la interfaz lo siguiente:
•¡LISTO! Ponemos npm start ó node server.js y podemos ir a nuestro Browser (Chrome/Firefox/etc) ó API Client para ver en acción nuestra mini app.
Terminada la primer parte, ya podemos ir avanzando con eltema principal de este documento.Como bien mencioné al principio, Docker trabaja concontenedores. Para hacerlo, corre un contenedor a partir deuna imagen la cual generalmente está compuesta por unSistema Operativo (puede ser alguna Distro), Software (comoPHP, paquetes Apache, librerías, extensiones, etc) y el códigode la aplicación. Para generar una imagen se utiliza un fichero llamadoDockerfile. Éste archivo tiene una serie de instrucciones queindican cómo va a estar compuesta esa imagen. Una vez quehayamos creado el Dockerfile, lo único que tenemos que haceres ejecutar dos comandos más:
docker build y docker run
– Guía Las ventajas de trabajar con esta tecnología, es que alguien puede crear una imagen y nosotros descargarla para añadirle nuestro código. Al mismo tiempo, terceros puede hacer exactamente lo mismo. Sin más que añadir por el momento, haremos nuestro primer Dockerfile para el proyecto que levantamos antes.
•Volvemos a la consola donde está corriendo Node y cancelamos su ejecución con Ctrl+c (usá el comando clear para limpiar la interfaz).
•Y con el editor, en la raíz del proyecto (donde estamos ubicados) creamos el fichero: Dockerfile.
•Una vez que estemos dentro del fichero, vamos a escribir y analizar la siguiente estructura:
FROM: Siempre al crear una imagen se empieza con un FROM el cual va a indicar la tecnología que vamos a utilizar para nuestro proyecto y su correspondiente versión (tag). Una buena práctica es la de indicar la versión que vamos a utilizar, porque cuando, ya sea que bajemos el trabajo de alguien más u otras personas bajen el nuestro, Docker desde su plataforma10/23
principal va a descargarnos por default la versión más reciente.Acá indiqué Node en la versión 14.17.0-alpine(4).
WORKDIR: En resumidas palabras, estamos señalando que se debe crear un directorio dentro de nuestro proyecto llamado app donde se podrán ejecutar comandos.
COPY . .: Bien. Este tema puede ser para rato, pero acá se decidió copiar todos los directorios y ficheros de la raíz del proyecto, dentro de app.
RUN: Específicamente con el comando yarn install –production indica que se deben instalar las dependencias Javascript necesarias para que nuestra applicación pueda ejecutarse.
CMD: Cuando ejecutamos nuestro server, recordarás que señalé que podes hacer npm start o node server.js. Bueno, con CMD se indica cómo debe iniciar la aplicación.
•Guardamos los cambios y a continuación ponemos losiguiente: sudo docker build -t proyecto_node .Debería quedar así (ignorá lo que está con color rojo):
(4) Alpine es una de las distros Linux más ligeras que existen. No tiene sentido instalar unadistribución, por ej Debian para un proyecto tan pequeño como este.11/23
•Por último, para ver en funcionamiento todo, alcanza con ejecutar el siguiente cmd y abrir el navegador: sudo docker run -p 3000:3000 proyecto_node
¡Muy bien! Tu primera app corriendo con Docker 😀
Hay que aclarar algo: se puede ejecutar de múltiples maneras. Lo anterior significa que el contenedor va a correr en el puerto3000 que apunta al puerto 3000 del proyecto Node. Si vos necesitas que se ejecute en el puerto 4000, solo tendrías que especificar: 4000:3000. También se puede especificar una variable de entorno, pero eso es para otro momento.
Habrás notado que la consola quedó bloqueada. Para evitar esto haremos:
•Cancelar con Ctrl+c, escribimos el mismo comando que utilizamos pero cambiamos el argumento -p por -dp (-d =detach). El resultado sería...
Y... ¿ahora? Bueno, básicamente podes entrar de nuevo al navegador y observar que el mensaje JSON sigue apareciendo. Pero para ver los procesos que están siendo ejecutados ya no son visibles como antes.
•Ponemos lo siguiente: sudo docker ps
•Si queremos detener ese contenedor tenemos que escribir el cmd especificando el ID: sudo docker stop 8f08fa715c50
•En el caso de que necesitemos ver las imágenes que hemos creado o tenemos en nuestro ordenador, ponemos: sudo docker images
Acá tenemos cinco títulos bien descriptivos. El primero detalla el nombre del repositorio, el segundo la versión actual del proyecto (último porque no especificamos nada aún), el ID de la imagen, el tiempo que lleva creado y por último el tamaño de dicha imagen.
Último antes de adentrarnos a otras cosas:
•si por alguna razón querés borrar la imagen que creaste/descargaste, pones: sudo docker rmi -f proyecto_node y se terminó todo!
•Al hacer docker images notarás que ya no figura más 😉
Repaso:
(1) Descargamos Docker.
(2) Descargamos y desarrollamos un nuevo proyecto NodeJS+Express.
(3) Creamos un Dockerfile con sus correspondientes instrucciones.
(4) Hicimos building para posteriormente correr la app en los puertos que le indicamos.
(5) Vimos cómo hacer que el proceso no sea bloqueante con detach.
(6) Analizamos los procesos en el background.
(7) Listamos las imágenes que tenemos creadas hasta el momento.
(8) Borramos la imagen.
Espero que no estés así aún para hacer todo de nuevo...
pd: Para la persistencia de datos, trabajar de forma bidireccional y hacer push, o sea, enviar nuestros proyectos a la nube para que alguien más lo descargue, lo dejo pendiente para un próximo tutorial
Docker Hub:
Como para darle un cierre al tema y te pongas a jugar con los comandos, vamos a ver de manera superficial la plataforma oficial de Docker, la cual permite subir y descargar imágenes a lo loco. Te recomiendo de antemano que vayas haciendo una cuenta ahí mismo para seguir indagando más al respecto.
Link: https://hub.docker.com/search?q=&type=image
Ya estando allí, como podrás observar, hay imágenes del software que se te ocurra. Podes encontrar distribuciones Linux, Bases de Datos, entornos de desarrollo configurados para usarse a la primera, herramientas de trabajo, frameworks, librerías, y un sin fin de cosas más. Vamos a ver cómo descargar una DB e interactuar con ella.
•Ponemos en el buscador postgres o simplemente scrolleamos y ahí mismo aparece. •Accedemos haciendo clic y veremos lo siguiente:
•Para descargar la imagen, simplemente copiamos el comando que nos figura allí en nuestra consola y esperamos un poquito: sudo docker pull postgres
•Comprobamos la imagen que hemos descargado:
•Observación: si intentas hacer docker run te saldrá un mensaje de error. ¡No te preocupes!
•Basta con leer y darse cuenta cuál es el error. ;) Más allá de la broma de mal gusto, ponemos: sudo docker run -e POSTGRES_PASSWORD=password postgres
Recordar: para evitar la consola bloqueada, usar -d.
•Podemos observar con el comando docker ps que nuestra base ya está disponible para ser utilizada.
Y... ¿cómo se supone que voy a interactuar con la base, si estáen background y no sale más nada? Sencillo:
•Utilizamos docker exec para para ejecutar comandos dentro de un contenedor activo. Debemos especificar el container id: sudo docker exec -it 80fd40d3663b sh
Los argumentos utilizados significan:
-i: Interactivo.
-t: Emular la terminal
sh: Shell.
Otro ejemplo, podría ser con MariaDB!
•Ejecutamos sudo docker pull mariadb
•Para correr el contenedor: sudo docker run --name mariadbtest -e MYSQL_ROOT_PASSWORD=password -d mariadb
•Recordá hacer sudo docker ps para comprobar que esté todo bien y obtener el ID del container! Ahora vamos a ingresar con docker exec: sudo docker exec -it 1c21d39c0f86 bash
•Bien. Tenemos que saber cuál es la IP que Docker le asignaal contenedor. Para ello ponemos docker inspect 1c21d39c0f86 | grep IPAddress
•Con esa información, ejecutamos mysql -u root -p -h 172.17.0.2
Casi terminando, algunos detalles más:
1.Cuando hacemos docker run de una imagen que no está en nuestro equipo, Docker lo que hará es descargar una imagen de la nube, instalarla y luego ejecutarla. Esa es una diferencia sutil entre hacer docker pull (descargar) y docker run (descargar y ejecutar) en este caso específico.
2.Se puede utilizar el comando docker start <container_id> para también arrancar un container y docker stop para detenerlo.
3.Un comando muy útil, cuando tenemos en nuestro ordenador muchísimas imágenes y tenemos que filtrar. Ya sea por nombre o tags: sudo docker images | grep alpine
4.Para cambiar la versión de nuestro proyecto, mientras hacemos docker build indicamos el tag correspondiente. Por ej: sudo docker build proyecto_node:v1.0.
5.Para ver información de los contenedores, se puede utilizar el comando docker logs <contenedor_id>. Si necesito que sea en tiempo real uso -f. Por ejemplo, con postgres:
Ahora si, ya hemos concluido con este primer encuentro con Docker. Espero honestamente que te sea de utilidad y que puedas seguir investigando más al respecto, para sacarle todo el provecho a esta fantástica herramienta.
A continuación repasamos lo visto hace unos instantes y ya queda en vos el resto!
Repaso:
(1) Ingresamos a Docker Hub para ver imágenes disponibles.
(2) Descargamos Postgres y lo configuramos.
(3) Echamos un vistazo al disparar un comando.
(4) Vimos su proceso en background.
(5) Averiguamos información sobre el contenedor mientras se ejecutaba.
(6) Descargamos MariaDB e hicimos las configuraciones necesarias.
(7) Ingresamos a la base de datos.
Comandos + adicionales:
sudo docker create crea un contenedor pero no lo comienza.
sudo docker rename permite renombrar al contenedor.
sudo docker run crea y comienza un contenedor en una operación.sudo docker rm borra un contenedor.
sudo docker update actualiza los recursos limitados de un contenedor.
sudo docker start comienza un contenedor si se cayó o salió.
sudo docker stop detiene un contenedor.
sudo docker restart detiene y comienza un contenedor.
sudo docker pause pausa un contenedor corriendo, "lo congela".
sudo docker unpause quita la pausa de un contenedor corriendo.
sudo docker wait bloquea hasta que un contenedor corriendo se detiene.
sudo docker kill envía una SIGKILL a un contenedor corriendo.
sudo docker attach se conecta a un contenedor corriendo.
sudo docker history muestra el historial de una imagen.
sudo docker tag taggea una imagen a un nombre asignado.
sudo docker images muestra todas las imágenes.
sudo docker import crea una imagen de un tarball.
sudo docker build crea imagen de un Dockerfile.
sudo docker commit crea imagen de un contenedor, pausándolo temporalmente si esta corriendo.
sudo docker rmi remueve una imagen.
sudo docker load carga una imagen de un archivo tar como STDIN, incluyendo imagenes y tags.
sudo docker save salva una imagen a un archivo tar a STDOUT con todas las capas padre, tags y versiones.
sudo docker ps muestra los contenedores corriendo.
sudo docker logs obtiene logs de un container.
sudo docker inspect observa toda la info en un contenedor.
sudo docker events obtiene eventos de un contenedor.
sudo docker port muestra el puerto publico de un contenedor.
sudo docker top muestra los procesos corriendo en un contenedor.
sudo docker stats muestra las estadísticas de recursos usados por contenedor.
sudo docker diff muestra los archivos cambiados en el FS del contenedor.
sudo docker ps -a muestra todos los contenedores corriendo y detenidos.
sudo docker stats --all muestra una lista de los contenedores corriendo.
Links:
https://hub.docker.com/https://www.docker.com/
https://docs.docker.com/engine/install/debian/
https://www.ibm.com/cloud/learn/docker
https://cloudacademy.com/blog/docker-vs-virtual-machines-differences-you-should-know/
https://www.cyberciti.biz/faq/how-to-install-curl-command-on-a-ubuntu-linux/
https://github.com/nodesource/distributions/blob/master/README.md
https://linuxhint.com/arch-linux-docker-tutorial/
https://docs.docker.com/docker-for-windows/install/
https://docs.docker.com/docker-for-mac/install/
https://es.wikipedia.org/wiki/Docker_(software)