lunes, 8 de febrero de 2021

Primeros pasos con contenedores Docker y gestión gráfica con Portainer

Portainer te permite gestionar, organizar, ver los diferentes contenedores desde el navegador de una forma gráfica y visual muy amigable. Es ideal para empezar. Portainer se trata de una interfaz de usuario web que nos permite administrar fácilmente nuestro host Docker y todos los contenedores que en él habitan. ¿Porqué usar Portainer? para aprender lo mejor es practicar y qué mejor que una herramienta muy visual que mediante ejemplos vayamos entendiendo los conceptos.


Docker es un proyecto de código abierto que automatiza el despliegue de aplicaciones dentro de contenedores de software, proporcionando una capa adicional de abstracción y automatización de virtualización de aplicaciones en múltiples sistemas operativos. Docker utiliza características de aislamiento de recursos del kernel Linux, tales como cgroups y espacios de nombres (namespaces) para permitir que 'contenedores' independientes se ejecuten dentro de una sola instancia de Linux, evitando la sobrecarga de iniciar y mantener máquinas virtuales

Contenedores de software sin virtualizar

Docker es útil a administradores de sistemas, pero también a desarrolladores. Uno de los problemas que se presentan durante el desarrollo y despliegue de aplicaciones es encontrarnos con sistemas heterogéneos, no ya entre los desarrolladores, también entre los sistemas de pruebas, pre-producción y producción. Es decir, que los desarrolladores y los sistemas donde se ejecuta la aplicación tienen librerías y sistemas operativos diferentes. ¿Y por qué es un problema? Pues porque la aplicación puede funcionar bien en una distribución de GNU/Linux pero no bien en otra, o ejecutarse bien con la versión de un lenguaje pero no con otra. Para asegurar la calidad de desarrollo tenemos que asegurar que todo el mundo usa las mismas versiones de todas las aplicaciones y librerías necesarios.

¿Docker es virtualización?

En GNU/Linux Docker no es virtualizado, no hay un hipervisor. Los procesos que corren dentro de un contenedor de docker se ejecutan con el mismo kernel que la máquina anfitrión. Linux lo que hace es aislar esos procesos del resto de procesos del sistema, ya sean los propios de la máquina anfitrión o procesos de otros contenedores. Además, es capaz de controlar los recursos que se le asignan a esos contenedores (cpu, memoria, red, etc.). Internamente, el contenedor no sabe que lo es y a todos los efectos es una distribución GNU/Linux independiente, pero sin la penalización de rendimiento que tienen los sistemas virtualizados.

Imágenes Docker

De forma muy similar a las máquinas virtuales, los contenedores de Docker se basan en imágenes, que son plantillas de solo lectura con todas las instrucciones que necesita el motor de Docker para crear un contenedor. Como copia portátil de un contenedor, una imagen Docker se describe en forma de archivo de texto (Dockerfile). Antes de iniciar un contenedor en un sistema, se carga un paquete con la imagen correspondiente si esta no está ya guardada de forma local. La imagen cargada prepara todos los sistemas de archivos con los parámetros necesarios para la ejecución. Un contenedor puede considerarse como un proceso en ejecución de una imagen.

Docker Hub

El Docker Hub es un registro para repositorios de software basado en la nube, es decir, una especie de biblioteca para las imágenes Docker. Este servicio online está formado por repositorios públicos y privados. En los primeros se ofrece a los usuarios la posibilidad de subir sus propias imágenes y compartirlas con la comunidad. Aquí se dispone de un gran número de imágenes Docker oficiales realizadas por el equipo de desarrolladores de la plataforma así como de proyectos de código abierto consolidados. Por el contrario, en los repositorios privados del registro no todo el mundo tiene acceso a las imágenes que se cargan, aunque estas sí pueden ser compartidas dentro de una misma empresa o en un determinado círculo. Al repositorio de Docker Hub se accede a través de hub.docker.com.


Portainer: administrar contenedores con interfaz web

  • Contenedor Portainer, un gestor de contenedores con interfaz web, muy sencillo y completo.

Portainer  es un poderoso conjunto de herramientas de administración (de código abierto) que te permite construir, administrar y mantener fácilmente entornos Docker.

¿Porqué usar Portainer? para aprender lo mejor es practicar y qué mejor que una herramienta muy visual que mediante ejemplos vayamos entendiendo los conceptos.

Si por fin instalaste Docker, para desarrollar WordPress  en local o para otras aplicaciones, verás que tienes carencias a la hora de ver tus contenedores e imágenes. En Visual Studio Code, aún que va muy bien, te falta visibilidad si tienes muchos contenedores, imágenes, etc. 

Lo mismo te pasa con Dashboard (antes Kitematic) que es la GUI por defecto que viene con la versión de Docker para Windows. Aunque que ahora ha sido mejorada es posible que se te quede algo corta.

Portainer  va un paso más allá a la hora de darnos facilidades para gestionar nuestro Docker a través de una interfaz gráfica muy intuitiva.

Lo que vas a apreciar en Portainer es su sencilla interfaz basada en web desde donde podrás gestionar remota o localmente contenedores, iniciarlos, pararlos, eliminarlos, reiniciarlos, etc. y también agregar contenedores, crear imágenes, levantar redes, monitorizar los contenedores en marcha, etc. 

Además tienes a tu disposición la extensa documentación de Portainer.

Su instalación es muy fácil en su sitio web tienes muy bien explicado como hacerlo.

Instalar Portainer con Docker

La aplicación se encuentra dentro de un contenedor así que podemos desplegarlo igual que cualquier otro Docker.

En el terminal de Visual Studio Code o en Windows PowerShell debes teclear estas dos líneas para instalar «Portainer»

docker volume create portainer_data

docker run -d -p 9000:9000 --name portainer --restart always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer 

No te asustes si dice

Unable to find image 'xxxx' locally 

Si no encuentra la imagen local la descargará de internet. 

O en el puerto local 8000 y el del contenedor 9000 

$HOSTPORT:$CONTAINERPORT.

docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

Ahora la nueva versión de Portainer ya acepta https y se ejecuta por defecto en el puerto 9443

Y lo único que pide ahora al acceder es crear el usuario:

https://localhost:9443




Si lo prefieres también puedes hacerlo con un archivo «docker-compose.yml» con este código:

 version: '2'

services:

  portainer:

    image: portainer/portainer

    command: -H unix:///var/run/docker.sock

    volumes:

      - /var/run/docker.sock:/var/run/docker.sock

      - portainer_data:/data

    ports:

      - 127.0.0.1:9443:9443

volumes:

  portainer_data:

 

version: "3"
services:
  portainer:
    image: portainer/portainer-ce:latest
    ports:
      - 9443:9443
      volumes:
        - data:/data
        - /var/run/docker.sock:/var/run/docker.sock
    restart: unless-stopped
volumes:
  data:


O descarga el archivo docker-compose.

Ya sabes que entonces debes usar el comando:

docker-compose up -d


Con el  comando  comprobamos que está correcto:

docker ps 

Esto lo debes ejecutar en la misma ruta donde tengas el fichero con extensión YML.

 

Y listo en  localhost:9443 tendrás  Portainer  en marcha.

 


Al acceder vía web por primera vez nos pedirá configurar la contraseña del usuario administrador, tal y como se muestra en la imagen

Lo primero es crear un usuario y la contraseña.

Una vez ya nos hemos logeado en el siguiente paso es elegir la gestión de los contenedores:

  • Docker (docker.sock local)
  • Kubernetes
  • Agent
  • Azure


Anteriores versiones:



Y  ya podemos ver la interfaz de Portainer:



La verdad es que este producto da mucho juego. Podemos gestionar prácticamente todas las operaciones: 

  • Descargar imágenes
  • Crear contenedores
  • Gestionar volúmenes
  • Redes
  • Puertos
  • etc



 

Pulsando sobre Primary nos lleva a Dashboard:

  • Stacks
  • Images
  • Networks
  • Containers
  • Volumes 


Otro ejemplo:



El menú de Containers, nos mostrará la lista de todos nuestros contenedores, y podremos ejecutar con click instrucciones como arrancarlos, pararlos o eliminarlos.  También podemos ver detalles del propio contenedor.

  • Start
  • Stop
  • Kill
  • Restart
  • Pause
  • Remove
  • Add

Si hacemos click en el nombre de un contenedor, podemos ver la información del mismo.

  • Nombre
  • Estado
  • Stack
  • Imagen
  • Creada
  • Puertos

 


Desde el propio apartado de «Containers«, justo en la línea con la información del contenedor en cuestión, podemos ver sus estadísticas marcando sobre el símbolo de la gráfica. 

Container

  • Logs
  • Inspect
  • Stats
  • Console
  • Attach

Ejemplo Stats -->



Vista de la sección  Images:

 


 Detalles contenedor:

  • Imagen
  • Puertos
  • CMD
  • Entrypoint
  • ENV
  • Labels
  • Restart Policies
  • Connected Networks

En la pantalla de Networks, tenemos la posibilidad de ver las redes que ya tenemos creadas. También podemos eliminarlas o añadir a través de la interfaz una nueva red.

 



En Volumes veremos los directorios:

 


Para mostrar brevemente su funcionamiento nos podemos descargar una plantilla de contenedor ya predefinida desde «Add Templates«. En el ejemplo vamos a utilizar la plantilla para instalar la popular herramienta de control de versiones GitLab.


AppTemplates:

 


Conceptos básicos sobre Docker

Antes de comenzar a instalar y usar docker es importante tener una serie de conceptos claros2:

Demonio de docker (docker daemon)
Es el proceso principal de docker. Escucha peticiones a la API y maneja los objetos de docker: imágenes, contenedores, redes, volúmenes. También es capaz de comunicarse con otros demonios para controlar servicios docker.
Cliente de docker (docker client)
Es la principal herramienta que usan los administradores de sistema para interaccionar con el sistema Docker.
Registro de docker (docker registry)
Es el lugar donde se almacenan las imágenes de Docker y poder descargarlas para reutilizarlas. Docker Hub es el principal registro público de Docker y contiene ya un montón de imágenes listas para ser usadas de multitud de servicios (mysql, wordpress, etc).

Objetos de docker

Cuando usamos Docker, estamos creando y usando imágenes, contenedores, redes o volúmenes, entre otros. A todo esto se le denominan objetos. Veamos los más importantes:

Imagen (image)
Plantilla de solo lectura que contiene las instrucciones para crear un contenedor Docker. Pueden estar basadas en otras imagenes, lo cual es habitual.
Contenedor (container)
Es una instancia ejecutable de una imagen. Esta instancia puede ser creada, iniciada, detenida, movida o eliminada a través del cliente de Docker o de la API. Las instancias se pueden conectar a una o más redes, sistemas de almacenamiento, o incluso se puede crear una imagen a partir del estado de un contenedor. Se puede controlar cómo de aislado está el contenedor del sistema anfitrión y del resto de contenedores. El contenedor está definido tanto por la imagen de la que procede como de las opciones de configuración que permita. Por ejemplo, la imagen oficial de MariaDb permite configurar a través de opciones la contraseña del administrador, de la primera base de datos que se cree, del usuario que la maneja, etc.
Servicios (services)
Los servicios permiten escalar contenedor a través de múltiples demonios de Docker, los cuales trabajarán conjuntamente como un enjambre (swarm).

Instalación Docker

Debido a que, dependiendo de la distribución, la forma de instalarlo difiere, es mejor consultar la documentación oficial para saber como instalar Docker en tu máquina.

Añadir usuario:

sudo usermod -aG docker usuario


Instalación Docker Compose

Docker Compose permite definir las aplicaciones multicontenedor, conocidas como stacks, y ejecutarlas en un nodo individual o en un clúster. La herramienta recurre para ello a una consola de línea de comandos con el fin de gestionar el ciclo de vida completo de sus aplicaciones.

En el universo Docker los stacks o lotes son grupos de servicios interconectados que comparten las dependencias del software y que se escalan y orquestan de forma conjunta. Un stack de Docker permite definir las diversas funcionalidades de una aplicación en un archivo central, este es, docker-compose.yml, iniciarlo, ejecutarlo conjuntamente en un sistema de tiempo de ejecución y gestionarlo de forma central.

Puedes instalarla con las instrucciones que hay en la página de Instalación de Docker Compose

Seguimos hablando de containers, en este caso, de la herramienta Docker Compose, que nos permitirá definir y ejecutar múltiples aplicaciones utilizando contenedores de software.

Con Compose utilizaremos ficheros en formato YAML, que nos servirán para definir la configuración de la aplicación en cuestión. De esta manera podemos, con un solo comando, crear e iniciar los servicios configurados en estos ficheros.

Su forma de uso es la siguiente:

  1. Definir el entorno de las aplicaciones con Dockerfile (del que hablamos en el artículo anterior), para que así pueda reproducirse en cualquier lugar.
  2. Establecer los servicios que componen las aplicación en un fichero docker-compose.yml, para que se pueda utilizar en un entorno aislado.
  3. Ejecutar la herramienta docker-compose, para así iniciar la aplicación.

Crear un volumen

Como necesitamos crear una base de datos para nuestro blog con WordPress vamos a crear un volumen donde guardar la información:

$ docker volume create wordpress-db
wordpress-db

Listar volúmenes

Con docker volume ls podemos visualizar todos los volumenes disponibles.
$ docker volume ls
DRIVER              VOLUME NAME
local               wordpress-db


Visualizar volúmenes

Los volúmenes se crean en un directorio del sistema y no es recomendable acceder a él, no al menos mientras haya un contenedor usándolo. En cualquier caso, si queremos ver los metadatos de un volumen podemos usar docker volume inspect


$ docker volume inspect wordpress-db 

[

    {

        "CreatedAt": "yyyy-mm-ddThh:ii:ss+Z",

        "Driver": "local",

        "Labels": {},

        "Mountpoint": "/var/lib/docker/volumes/wordpress-db/_data",

        "Name": "wordpress-db",

        "Options": {},

        "Scope": "local"

    }

]

Borrar volúmenes

Como todos los objetos de Docker, los volúmenes también pueden ser borrados, pero solo si no están en uso. Mucha precaución al borrar los volúmenes, porque perderíamos todos los datos que contenga.

Para borrar un contenedor usaremos

 docker volume rm y el nombre del contenedor. 


Detener servicios

Podemos detener servicios con

docker-compose stop

Borrar servicios

Podemos borrar servicios con

docker-compose down

Esto borra los contenedores, pero no los volúmenes. Así que si hemos creado bien la aplicación nuestros datos están a salvo.

Si queremos borrar también los volúmenes:

docker-compose down -v 

Buscar imágenes

Crear una imagen desde cero supone un esfuerzo demasiado grande, así que lo normal es partir o usar una ya creada.

Para ellos buscaremos en los registros, el lugar donde se almacenan. Hay un registro oficial (https://hub.docker.com), pero nada impide a otras organizaciones, o a nosotros mismo, tener un registro propio. Estos registros pueden ser privados o públicos.


Ver imágenes

docker images


Borrar imágenes

docker rmi

Ver contenedores

docker ps 

Ejecutar un comandos en un contenedor:

docker run --name ubuntu_bash --rm -i -t ubuntu bash 

Recuerda que los containers están construidos para un arquitectura de procesador concreta, normalmente x86_64 (amd64, intel64) pero también hay para arm, etc. y entones no funcionarán.

Por ejemplo un comando para probarlo es:

$ docker run --rm -t arm64v8/ubuntu uname -m

Si aparece un error 

standard_init_linux.go:211: exec user process caused "exec format error" 

Es que nuestro host (ordenador) es  x86_64 y el contenedor es arm64v8, arquitectura diferente y fallará.

La respuesta debería haber sido

$ docker run --rm -t i386/ubuntu uname -m

 x86_64

En futuras entradas hablaremos de emuladores para solucionar estos problemas:


Iniciar un contenedor 

docker container start 

Detener un contenedor

docker container stop id_contenedor

Ya hemos indicado que un contenedor está aislado de todo. Hemos visto como podemos conectar el contenedor a un puerto de red para poder acceder a él. Eso incluye al sistema de archivos que contiene. De tal manera que si se elimina el contenedor, se eliminan también sus archivos. 

Si queremos almacenar datos (una web, una base de datos, etc.) dentro de un contenedor necesitamos una manera de almacenarlos sin perderlos.

Docker ofrece tres maneras:

  • A través de volúmenes, que son objetos de Docker como las imágenes y los contenedores.
  • Montando un directorio de la máquina anfitrión dentro del contenedor.
  • Almacenándolo en la memoria del sistema (aunque también se perderían al reiniciar el servidor).

Todo sobre los comandos de  Docker

Imágenes más conocidas por las que podemos usar para no partir desde cero para crear la nuestra.

Limpieza

Para borrar objetos que no están en uso:

docker system prune

Para borrar volúmenes que no están asociados a ningún contenedor:

docker volume rm $(docker volume ls -q -f "dangling=true")

Para borrar contenedores que han terminado su ejecución:

docker rm $(docker ps -q -f "status=exited")

Para borrar imágenes que no están etiquetadas:

docker rmi $(docker images -q -f "dangling=true")

Copias de seguridad

Para hacer una copia de seguridad:

docker run --rm -v /tmp:/backup \

    --volumes-from <container-name> \

    busybox tar -cvf /backup/backup.tar <path-to-data>

Para restaurar:

docker run --rm -v /tmp:/backup \

    --volumes-from <container-name> 

    busybox tar -xvf /backup/backup.tar <path-to-data>

Extraer datos de un contenedor:

docker cp 


Copias de seguridad  de contenedores

Ya estén encendidos o apagados, podemos realizar respaldos de seguridad de los contenedores. Utilizando la opción “export” empaquetará el contenido, generando un fichero con extensión “.tar” de la siguiente manera:

docker export -o fichero-resultante.tar nombre-contenedor

o

docker export nombre-contenedor > fichero-resultante.tar

Restauración de copias de seguridad de contenedores

Hay que tener en cuenta, antes de nada, que no es posible restaurar el contenedor directamente, de forma automática. En cambio, sí podemos crear una imagen, a partir de un respaldo de un contenedor, mediante el parámetro “import” de la siguiente manera:

docker import fichero-backup.tar nombre-nueva-imagen

Copias de seguridad de imágenes

Aunque no tiene mucho sentido por que se bajan muy rápido, también tenemos la posibilidad de realizar copias de seguridad de imágenes. El proceso se realiza al utilizar el parámetro ‘save‘, que empaquetará el contenido y generará un fichero con extensión “tar“, así:

docker save nombre_imagen > imagen.tar

o

docker save -o imagen.tar nombre_imagen

Restaurar copias de seguridad de imágenes

Con el parámetro ‘load’, podemos restaurar copias de seguridad en formato ‘.tar’ y de esta manera recuperar la imagen.

docker load -i fichero.tar

 

Resumen comandos más frecuentes

Crear máquina Docker:

docker-machine create [MACHINE_NAME]

Eliminar todas las imágenes y contenedores docker

#!/bin/bash

# Delete all containers

docker rm $(docker ps -a -q)

# Delete all images

docker rmi $(docker images -q)

Reiniciar máquina docker (a veces se producen fallos red)

docker-machine restart [MACHINE_NAME]

Preparar shell para trabajar por línea de comandos

eval "$(docker-machine env [MACHINE_NAME])"

Crear una imagen a partir de un Dockerfile

docker build -f Dockerfile .

Crear contenedor a partir de una imagen

docker create [IMAGE_ID]

Crear contenedor con nombre mapeando puertos a partir de una imagen

docker run -d --name=[CONTAINER_NAME] -p 8081:8081 [IMAGE_ID]

Consultar containers activos

docker ps

Consultar containers (funcionando o no)

docker ps -a

Iniciar un container

docker start [CONTAINER_ID]

Cambiar nombre a un contenedor

docker rename [CONTAINER_ID ] [CONTAINER_NAME]

Ejecutar comando en un contenedor

docker exec [CONTAINER_NAME] [COMMAND]

Hacer login en un contenedor en ejecución

docker exec -i -t [CONTAINER_NAME] /bin/bash

Fuentes: 

https://labarta.es/administra-docker-con-portainer/

https://colaboratorio.net/davidochobits/sysadmin/2018/gestion-grafica-docker-portainer/

https://aulasoftwarelibre.github.io/taller-de-docker/tips/

No hay comentarios:

Publicar un comentario