Docker, manual en español

docker-00-300En una entrada de hace un par de años ya hablé de LXC, los contenedores Linux.

LXC (linux containers) linux dentro de linux.

Hoy hablaremos de Docker.

Docker, como LXC, utiliza el kernel de Linux para conseguir contenedores encapsulados, es lo que se llama virtualización a nivel del sistema operativo, hasta ahí son básicamente lo mismo, pero la “filosofía” de Docker es diferente.

Mientras LXC crea un contenedor Linux que es una sistema operativo completo, que puede correr múltiples servicios y que acumula los cambios que le hagamos, los contenedores Docker son versiones mínimas de una imagen Linux creada para una tarea específica, y que (aunque pueden hacerlo) se pretende que solo corran un único servicio. De ahí que el concepto de arquitectura de microservicios tenga mucho que ver con Docker.

Mientras un contenedor LXC es lo mismo que un servidor físico, o que una máquina virtual (VMware o VirtualBox) pero es virtualización a nivel de OS, Docker crea minicontenedores “apilables” para aplicaciones o servicios individuales. Simplificando la tarea de copiar, clonar, escalar y portar servicios. Es por eso ideal para la nube.

Para comprenderlo, hay que entender dos conceptos básicos en Docker:

Es muy importante distinguir las imágenes de los contenedores.

Las imágenes.

Una imagen de Docker, es una estructura de directorios y paquetes mínima, creada para una función básica. Se trata de que sea una plantilla, que se puede modificar, pero que ha sido pensada para una uso básico y específico. Por ejemplo, una imagen Debian con un Apache. De esta forma, para tener múltiples servidores web apache, cada uno encapsulado y aislado de los demás, sólo tendremos que crear contenedores desde ella, y cada uno será un servidor web distinto, con su propia IP, al que se puede configurar de manera independiente y que a su vez de puede clonar o mover donde se quiera.

Los contenedores.

Un contenedor, es una instancia generada desde una imagen, que ya es en sí un pequeño OS funcionando, y que podemos usarlo para una función concreta (como por ejemplo correr un Apache).

Por eso en Docker se trabaja primero con imágenes (las plantillas) y luego con contenedores (los minisistemas operativos funcionando). Veamos.
Instalamos Docker:

sudo apt install lxc-docker

sudo pacman -S docker

sudo emerge -a docker

(yo he instalado Docker en Gentoo y hay que tener en cuenta que en Gentoo hay que recompilar el núcleo con la configuración adecuada para que funcione Docker, véase https://wiki.gentoo.org/wiki/Docker)

Docker tiene dos partes, un demonio que debe arrancarse de fondo, y el cliente Docker que usamos para trabajar con él en consola.

Por lo tanto arrancamos el demonio (casi seguro que será con Systemd)

sudo systemctl start docker

si no usas Systemd:

/etc/init.d/docker start

y el demonio de Docker ya estará funcionado de fondo.

Si no queremos tener que estar siempre poniendo sudo, podemos meter a nuestro usuario en el grupo “docker”:

sudo gpasswd -a tu-usuario docker

newgrp docker

Y ya podremos usar Docker sin sudo.

Puedo ver información de Docker mediante:

docker version

y

docker info

Y ahora podemos buscar en remoto una imagen así:

docker search debian

o docker searh arch, docker search ubuntu, docker searh busybox, docker search apache, docker search wordpress, etc, etc.

(aquí podemos ver en la web las imágenes disponibles: https://hub.docker.com/explore/ )

Vemos que nos muestra un listado de imágenes listas para usar, diferentes distros, versiones, servidores web como Apache o Nginx, bases de datos, WordPress, etc, etc.

Bajemos una imagen de Busybox (un pequeño Linux para probar)

docker pull busybox

tras esto, si todo ha ido bien, ya tenemos una imagen de Busybox en local.

Podemos ver nuestras imágenes así:

docker images

y ahora ha llegado el momento de correr nuestro primer contenedor Docker, vamos allá:

docker run -it busybox sh

vemos que aparece el prompt y estamos dentro de nuestro contenedor.

podemos hacer

ls

o

ifconfig

y trabajar dentro como en cualquier distro Linux.

Dejamos esa terminal con Busybox y abrimos una nueva terminal.

Podemos ver en esta segunda terminal que el contenedor está funcionando:

docker ps -a

Si abrimos una segunda instancia desde la imagen Busybox, tendremos otro contenedor, idéntico pero distinto, veamos, otra vez:

docker run -it busybox sh

ya estamos en el segundo contenedor, abrimos una tercera terminal y lo vemos:

docker ps -a

docker-01
los dos contenedores busybox funcionando

vemos que ahora hay dos contenedores funcionando, cada uno tiene su propia ID, los dos están creados desde la imagen “busybox”, y al final vemos que Docker le asigna a cada uno un simpático nombre automáticamente.

Puedo hacer un “ifconfig” en ambos y hacer un ping de uno a otro, con lo que comprobaré que se comunican perfectamente como si fuesen dos máquinas reales y distintas en dos puntos cualquiera del planeta. 🙂
O podría conectar de uno a otro mediante SSH. ¿Alucinante no?

Puedes bajar las imágenes que quieras y crear desde ellas múltiples contenedores.

docker pull debian

docker pull ubuntu

docker pull archlinux

y luego:

docker run -it debian sh

docker run -it ubuntu bash

docker run -it archlinux /bin/bash

(en sucesivas terminales)
(obsérvese que en algunos casos arranco en contenedor con el comando al final “sh” un shell genérico, aunque normalmente, como estará instalado Bash, utilizo su propio comando con o sin ruta “bash” o “/bin/bash”

con lo cual ya tendríamos funcionando dos instancias de Busybox, un Debian, un Ubuntu y un Arch. Todo un cluster propio.

Cada instancia tiene su propia ID, su propio nombre, su propia interfaz de red y funciona de forma autónoma.

Por supuesto en Debian y en Ubuntu puedo usar APT, y en Arch Pacman, para instalar software.

Y aquí encontramos una gran diferencia entre Docker y LXC. Si en un contenedor LXC, supongamos que un Debian, hago apt-get update & atp-get upgrade, el contenedor guarda los cambios, es un contenedor persistente. Si embargo, los contenedores Docker no lo son. Esto quiere decir que si lo cerramos, no guardará los cambios, pues son contenedores no persistentes. Han sido pensado así, para la persistencia tenemos las imágenes.

Pero, lo que sí puedo hacer es crear un contenedor desde una imagen original, luego hacerle los cambios que yo quiera, y generar desde él una nueva imagen, esta ya sí, con nuestros cambios. Veamos un ejemplo.

Ya tenemos una imagen Debian que hemos bajado antes, pues primero la corremos si no lo habíamos hecho, si ya la tenemos corriendo simplemente nos vamos a la terminal que la controla:

docker run -it debian bash

Ya estamos dentro.

Hacemos:

apt-get update & apt-get upgrade

para actualizar el sistema.

Instalamos tres paquetes básicos:

apt-get install nano htop screenfetch

El editor nano, el visor de procesos de sistema htop y screenfetch para embellecer nuestra terminal.

editamos con nano el archivo de configuración de bash:

nano /root/.bashrc

y le añadimos la línea:

screenfetch

ctl+o y ctl+x para guardar y salir de nano.

Resumo, hemos actualizado nuestro contenedor Debian mediante APT y hemos instalado 3 paquetes y configurado nuestra terminal. Pero si ahora saliésemos y cerrásemos el contenedor perdería los cambios, por lo que voy a guardar una imagen nueva desde él para poder usarla como nueva plantilla (imagen) de mi Debian. Esto se hace así:

Abro otra terminal:

docker ps -a

miro la ID del contenedor que he modificado y hago:

docker commit -m "Debian actualizado y con nano, htop y screenfetch" -a essau 831e2760f30b deb

Lo explico, “docker commit” es el comando que se encarga de crear una nueva imagen desde un contenedor, “-m” es comentario para saber qué he hecho, “-a” es el autor de la modificación, y luego va la ID del contenedor y finalmente el nombre que le doy a esta nueva imagen modificada por mí, en ente caso la he llamado “deb”.

Si ahora miro qué imágenes tengo:

docker images

puedo ver que además de la Debian original, tengo una nueva que se llama “deb”. Si creo contenedores desde la original estarán “vírgenes”, pero si creo uno desde la nueva:

docker run -it deb bash

docker-02
Un contenedor Debian, actualizado y personalizado por mí, funcionado.

Vemos que al arrancar un contenedor desde ella, aparece la terminal con screenfetch, tal y como habíamos modificado 🙂
Ya para terminar una lista de los comandos de Docker más importantes:
ayuda:

docker

buscar imágenes:

docker search debian

bajar una imagen:

docker pull debian

ver qué imágenes tengo:

docker images

historial de una imagen:

docker history ID o nombre de la imagen

eliminar una imagen:

docker rmi “ID de la imagen”

arrancar un contenedor desde una imagen:

docker run -it debian bash
mirar qué contenedores tengo, su estado e información:

docker ps -a

arrancar un contenedor:

docker start ID (o nombre)

entrar en un contenedor:

docker attach ID (o nombre)

(no sé aún porqué, docker start y docker attach dan a veces problemas, en caso de duda lo que siempre funciona es docker run -it nombre-imagen bash)

detener un contenedor:

docker stop ID (o nombre)

eliminar un contenedor:

docker rm ID (o nombre)

guardar una imagen nueva desde un contenedor modificado:

docker commit -m “comentario” -a autor ID nuevo-nombre

docker-arch
Varias imágenes y un contenedor docker corriendo en mi host Gentoo.

 


Apéndice:

Lo fascinante de Docker es que no sólo puedo crear contenedores en mi máquina para jugar, sino que puedo crear contenedores de la nube para tener mis propios servidores que corran mis microservicios.
Para ello, lo más fácil es usar AWS (Amazon Web Services) que te da un año gratis para trastear y aprender:

http://aws.amazon.com/es/docker/

o también en Google, que da gratis hasta cinco nodos:

https://cloud.google.com/container-engine/


Ampliar información, en inglés 😦 :

https://www.docker.com/

http://prakhar.me/docker-curriculum/

docker-04

LXC (linux containers) linux dentro de linux

MatrioskaTodo el mundo conoce las máquinas virtuales (VirtualBox, QEMU o VMware), es software que permite emular un entorno de hardware para instalar sistemas operativos en máquinas virtuales. Son muy útiles, pues dentro de una máquina de hardware, puedo tener decenas de máquinas virtuales donde instalar, por ejemplo servidores, de manera que cada uno quede encapsulado con todas las ventajas de administración y seguridad que eso conlleva.

LXC es algo parecido pero no es una máquina virtual, es más bien un entorno virtual que provee su propio entorno de procesos y redes. A diferencia de las máquinas virtuales, que necesitan un anfitrión de hardware con mucha memoria RAM, pues es el recurso principal que consumen, los contenedores linux (LXC) no consumen apenas recursos del anfitrión.

LXC funciona aprovechando una funcionalidad del núcleo Linux llamada cgroups, que está presente en el kernel desde la versión 2.6.29 (y por lo tanto en todas las versiones modernas 3.x). LXC es por lo tanto virtualización a nivel del sistema operativo.

LXC me permite tener una distro Linux dentro de otra distro Linux, que utilizará el kernel del anfitrión y la tarjeta de red, pero trabajará de manera encapsulada a todos los efectos, con su propia IP de red, su propia interfaz de red (encapsulada) y sus propios procesos (también enjaulados). Como se puede imaginar, esto es una maravilla de cara a tener dentro de un servidor Linux, decenas o centenares de contenedores linux, cada uno con su configuración, distro, versión, etc, etc, y cada uno perfectamente encapsulado. Puedo administrar todos ellos, por ejemplo, mediante SSH en remoto fácilmente.

Su interés a nivel empresarial es evidente, por la reducción de costes que supone frente a las máquinas virtuales y la facilidad de implementación así como de administración. Además de su gran utilidad para hacer test de seguridad en redes de todo tipo.

Desde el punto de vista didáctico, también resulta fascinante, pues es la mejor manera de tener una distro Linux dentro de la tuya para poder jugar, trastear y aprender, sin el más mínimo riesgo de estropear nada.

Por ejemplo, puedes probar Archlinux o Gentoo dentro de tu Ubuntu sin tener que instalar ninguno de los dos. Puedes tenerlos en 5 minutos listos para jugar con ellos y perderles el miedo.

************************************************

instalar LXC:

sudo apt install lxc bridge-utils libvirt-bin debootstrap (DEBIAN-UBUNTU-LINUXMINT)
sudo pacman -S lxc bridge-utils debootstrap (ARCH-ANTERGOS-MANJARO)
sudo zypper in lxc bridge-utils debootstrap (OPENSUSE)

************************************************

crear un contenedor LXC:

sudo lxc-create -t gentoo -n minigentoo (crea contendor tipo (-t) “gentoo” de nombre (-n) “minigentoo”
los tipos pueden ser: debian, archlinux, gentoo, fedora, centos, oracle, opensuse, ubuntu, un servidor sshd, etc, etc.
las plantillas (templates) de las distros que se pueden instalar están aquí:

/usr/share/lxc/templates/

************************************************

ver contenedores creados y su estado:
sudo lxc-ls -f      (lista los contenedores creados y su estado)

los contenedores están en:

/var/lib/lxc/

************************************************

ver información de un contenedor:

sudo lxc-info -n minigentoo      (me muestra información importante del contenedor, su IP, su PID, la memoria que está usando, etc.)

************************************************

arrancar y entrar en un contenedor:

sudo lxc-start -n minigentoo

arranca y ya tengo un login, en Gentoo:

user: root

pw: toor

(poner atención al crear un contenedor pues cada distro tiene su propio password de root, y al crear el contenedor te informa de ello.)

************************************************

arrancar un contenedor en segundo plano (no entra en él):

lxc-start -n minigentoo -d
puedo ver su estado ahora:

sudo lxc-info -n minigentoo      (me informa de que está funcionando, pero estoy fuera)

************************************************

abrir prompt de minigentoo (estando en segundo plano):

sudo lxc-attach -n minigentoo      (entro, me muestra el prompt como root)

************************************************

login en minigentoo (estando en segundo plano):

sudo lxc-console -n minigentoo

************************************************

cuando estás dentro de un contenedor es como estar en ese sistema operativo, por lo tanto si estás en un XLC Arch, funcionará pacman, o en Gentoo funcionará Portage… (con todo lo que eso significa).

para apagarlo:

sudo poweroff

😉

a disfrutar, confieso que para mí, los LXC son un vicio.

************************************************
Más info:

https://linuxcontainers.org/
https://wiki.debian.org/LXC
https://help.ubuntu.com/lts/serverguide/lxc.html
https://www.suse.com/documentation/sles11/singlehtml/lxc_quickstart/lxc_quickstart.html

gentoo-en-ubuntu
un contenedor LXC de Gentoo funcionado dentro de Ubuntu 14.04