lunes, 6 de junio de 2016

Trabajando con imágenes Docker y repositorios

La base de los contenedores son las imágenes, los cuales están construidos por bloques. Vamos a ir viendo como manejarlas, modificarlas, crear, almacenar y compartir nuestras imágenes. También vamos a ver los repositorios que almacenan imágenes.
Qué es una imagen Docker
Una imagen Docker se compone de un sistema de archivos en capas una sobre la otra. En la base,  es un sistema de archivos de arranque, bootfs, que se asemeja al típico sistema de archivos de arranque de Linux. Un usuario Docker, normalmente nunca interactuará con el sistema de archivos de arranque. De hecho, cuando un contenedor se inicia, se mueve a la memoria, y el sistema de archivos de arranque se desmonta para liberar la memoria RAM utilizada por la imagen de disco initrd.
Esto hasta ahora es más o menos como una pila típica de virtualización Linux. De hecho, Docker provee capas desde un sistema de archivos raíz, rootfs, en la parte superior del sistema de archivos de arranque. Este rootfs puede ser uno o mas sistemas operativos (por ejemplo, en un sistema de archivos de Debian o Ubuntu).
En un arranque más tradicional Linux, el sistema de archivos raíz se monta de sólo lectura y luego cambia a lectura escritura, después de arrancar y realizar una comprobación de integridad. En el mundo Docker, sin embargo, el sistema de archivos raíz permanece en modo de sólo lectura y Docker se aprovecha de una unión de montaje para añadir más sistemas de ficheros de sólo lectura en el sistema de ficheros raíz. Una unión de montaje es un montaje que permite que varios sistemas de archivos puedan ser montados en un momento, pero parecen ser un sistema de archivos. La unión de montaje superpone los sistema de archivos uno encima de otro para que el sistema de archivos resultante pueda contener archivos y subdirectorios de cualquier o todos los sistemas de archivos subyacentes. Docker llama a cada uno de estos sistemas de archivos imágenes. Las imágenes se pueden superponer una encima de la otra. La imagen de abajo se llama imagen padre, y se puede recorrer cada capa hasta llegar a la parte inferior de la pila de imágenes donde la imagen final se llama la imagen base. Por último, cuando un contenedor se pone en marcha a partir de una imagen, Docker monta un sistema de ficheros de lectura escritura en la parte superior de las capas inferiores. Aquí es donde los procesos de nuestro contenedor Docker serán ejecutados.
Las capas del sistema de archivos de docker
Cuando Docker crea un contenedor por primera vez, la capa inicial de lectura y escritura esta vacía. Cuando se producen cambios, éstos se aplican a esta capa, por ejemplo, si desea cambiar un archivo, entonces ese archivo se copia desde la capa de sólo lectura inferior a la capa de lectura y escritura. Seguirá existiendo la versión de sólo lectura del archivo, pero ahora está oculto debajo de la copia.
Este patrón se llama tradicionalmente “copiar al escribir” y es una de las características que hace que Docker sea tan poderoso. Cada capa de sólo lectura de imagen es de sólo lectura; esta imagen nunca cambia. Cuando se crea un contenedor, Docker construye desde la pila de imágenes y luego agrega la capa de lectura y escritura en la parte superior. Esa capa, combinada con el conocimiento de las capas de imagen por debajo de ella y algunos datos de configuración, forman el contenedor. Los contenedores pueden ser cambiados, tienen estado y pueden iniciarse y detenerse. Ésto, y el marco de imágenes por capas, nos permite construir rápidamente imágenes y contenedores de ejecución con nuestras aplicaciones y servicios.
Listando imágenes docker
Para comenzar con las imágenes Docker y ver que imágenes tenemos disponibles en nuestro host Docker, podemos hacerlo utilizando el comando “docker images”.
$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              e9ae3c220b23        3 weeks ago         187.9 MB
Podemos ver que tenemos una imagen, de un repositorio llamado Ubuntu. Esta imagen viene de cuando ejecutamos el comando “docker run” con la imagen Ubuntu, entonces se inició automáticamente un proceso de descarga de la imagen. La imagen ha sido descargada de un repositorio, las imágenes se almacenan dentro de repositorios y en los repositorios están los registros. El registro predeterminado es el registro público gestionado por Docker Inc. , Docker Hub.
El código del registro de Docker es de código abierto. También podemos ejecutar nuestro propio registro. Docker Hub también está disponible como producto comercial detrás de un cortafuegos llamado Docker Trusted Registry (Registro Docker de confianza).
Las imágenes locales se almacenan en nuestro Docker host en el directorio /var/lib/docker. Cada imagen, está dentro de un directorio nombrado por su controlador de almacenamiento, por ejemplo, aufs o devicemapper. También están todos los contenedores en el directorio /var/lib/docker/containers.
Docker Hub
Dentro de Docker Hub las imágenes se almacenan en repositorios. Podemos pensar en un repositorio de imágenes como en un repositorio Git. Contiene imágenes, capas y metadatos sobre esas imágenes.
Cada repositorio puede contener varias imágenes (por ejemplo, el repositorio de Ubuntu contiene imágenes para Ubuntu 12.04, 12.10, 13.04, 13.10 y 14.04). Vamos a ver como obtener otra imagen desde el repositorio Ubuntu ahora.
$ docker pull ubuntu:12.04
12.04: Pulling from library/ubuntu
b45376f323f5: Pull complete
23c388b926b6: Pull complete
10f1b5844a9c: Pull complete
2a7a952931ec: Pull complete
Digest: sha256:f41afd7e2c72502f3f9194b1a84abb8fc6148c6565ab8c38900d009ba80c2ef7
Status: Downloaded newer image for ubuntu:12.04
Hemos utilizado el comando “docker pull” para obtener la imagen de Ubuntu 12.04 desde el repositorio de Ubuntu. Si ejecutamos el comando “docker images” de nuevo veremos una nueva línea:
ubuntu                12.04               2a7a952931ec        3 weeks ago         136 MB
Decimos que Ubuntu es el sistema operativo Ubuntu, pero en realidad no es el sistema operativo completo. Es una versión muy reducida con lo básico para ejecutar la distribución.
Identificamos cada imagen dentro de ese repositorio con lo que Docker denomina etiquetas. Cada imagen está siendo catalogado por las etiquetas aplicadas a la misma, por ejemplo, 12.04, 12.10, y así sucesivamente. Cada etiqueta marca en conjunto una serie de capas de imágenes que representan una imagen específica (por ejemplo, la etiqueta 12.04 recoge a todas las capas de la imagen de Ubuntu 12.04). Esto nos permite almacenar más de una imagen dentro de un repositorio.
Podemos hacer referencia a una imagen específica dentro de un repositorio sufijo el nombre del repositorio con dos puntos y nombre de etiqueta, por ejemplo:

# docker run -t -i --name nuevo_contenedor ubuntu:12.04 /bin/bash
Esto ejecutará un contenedor con la imagen de Ubuntu:12.04, la cual es un sistema operativo Ubuntu 12.04.
Podemos ver que nuestra nueva imagen 12.04 aparece dos veces con el mismo ID en el resultado de “docker images”. Esto es porque la imágenes pueden tener más de una etiqueta. Esto hace que sea más fácil para ayudar a las imágenes de marca y hacer que sean más fáciles de encontrar. En este caso, el ID de imagen es en realidad un etiquetado con 12.04 y precise, el número de versión y el nombre en clave de la liberación de Ubuntu respectivamente.
Siempre es buena idea construir un contenedor con etiquetas específicas. De esa manera, sabremos exactamente cual es la fuente de nuestro contenedor.
Hay dos tipos de repositorios: repositorios de usuarios, que contienen las imágenes aportadas por los usuarios Docker, y repositorios de primer nivel, que son controlados por el equipo de Docker.
Un repositorio de usuario requiere un nombre de usuario y un repositorio, por ejemplo, jalapuente/miweb.
  • Nombre de usuario: jalapuente
  • Nombre de repositorio miweb
Alternativamente, un repositorio de nivel superior sólamente tiene un nombre como el repositorio de Ubuntu. Los repositorios de nivel superior son administrador por Docker Inc y por los proveedores seleccionados que proporcionan imágenes base, para poder construir sobre ellas (por ejemplo, el equipo de Fedora proporciona una imagen de fedora). Los repositorios de alto nivel también representan un compromiso por parte de los vendedores y Docker Inc de que las imágenes contenidas en ellas están bien construidas y seguras hasta la fecha.
Las imágenes aportadas por usuarios son construidas por los miembros de la comunidad Docker. Se deben utilizar bajo nuestro propio riesgo: no se validan o verifican en modo alguno por Docker Inc.
Obteniendo imágenes
Cuando ejecutamos un contenedor a partir de imágenes con el comando “docker run”, si la imagen no está almacenada localmente, entonces Docker la descargará desde Docker Hub. Por defecto, si no se específica una etiqueta específica, Docker descargará la última etiqueta, por ejemplo:
$ docker run -t -i --name nuevo_contenedor ubuntu /bin/bash
Descargará la imagen ubuntu:latest si no está ya presente en el host.
Alternativamente, podemos usar el comando “docker pull” para obtener las imágenes nosotros mismos de forma preventiva. Usando el comando “docker pull”, nos ahorra algún tiempo el lanzamiento de un contenedor de una nueva imagen. Vamos a ver que ahora como obtener la imagen base fedora:20.
$ docker pull fedora:20
Podemos ver esta nueva imagen en nuestro anfitrión Docker con el comando “docker images”. Esta vez, sin embargo, vamos a restringir nuestras imágenes para que sólo aparezcan las imágenes de fedora. Para ello, podemos especificar el nombre de la imagen después del comando imágenes Docker.
$ docker images fedora
Buscando imágenes
Podemos también buscar todas las imágenes públicas disponibles en Docker Hub usando el comando “docker search”
$ docker search aspnet
y nos aparecería una relación de todas las imágenes disponibles en Docker Hub que contengan la palabra “aspnet”.
También podríamos ver las imágenes disponibles en “https://hub.docker.com”. como resultado de la búsqueda nos devuelve, además de los nombres de repositorio, una descripción de la imagen. Las estrellas o popularidad de la imagen nos indican si es una imagen oficial y “automatizada”, es decir, si la imagen ha sido construida por un proceso automático.

Manejo de contenedores

Manejo de contenedores
Lo primero que debemos hacer antes de comenzar, es comprobar que Docker está trabajando correctamente, para ello podemos utilizar el comando “docker info”, el cual nos indica la configuración que tiene Docker actualmente, incluido el número de contenedores e imágenes.
Ejecutando nuestro primer contenedor
Vamos a ver como probar y ejecutar nuestro primer contenedor con Docker. Vamos a utilizar el comando “docker run”, el cual nos permite ejecutar contenedores en Docker. Lo usaremos para crear nuevos contenedores.
$ docker run -i -t ubuntu /bin/bash
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu

0a85502c06c9: Pull complete
0998bf8fb9e9: Pull complete
a6785352b25c: Pull complete
e9ae3c220b23: Pull complete
Digest: sha256:f91f9bab1fe6d0db0bfecc751d127a29d36e85483b1c68e69a246cf1df9b4251
Status: Downloaded newer image for ubuntu:latest
root@17e9e0d4c05b:/#
Hemos ejecutado el comando “docker run” y hemos pasado dos parámetros –i y –t , -i permite redirigir la entrada estándar, esto es necesario para poder tener una sesión interactiva con el Shell. El parámetro –t le dice a Docker que asigne un pseudo-tty al contenedor que hemos creado y es el que realmente permite una sesión interactiva con el Shell del nuevo contenedor. Esta línea es básica cuando queramos crear un contenedor que planeamos interactuar en línea de comandos.
El siguiente parámetro le indica a Docker que imagen debe usar para crear el contenedor, en este caso una imagen base de Ubuntu, la cual nos la provee Docker Inc. en el registro Docker Hub. Hay imágenes similares de fedora, debían, centos, etc.. que sirven de base para la construcción de nuestras imágenes en el sistema operativo elegido por nosotros. En este caso hemos usado una imagen básica sin ningún añadido.
Vamos a ver lo que ha sucedido en realidad al ejecutar el comando, lo primero de todo Docker checkea localmente para buscar la imagen de Ubuntu. Si ella no se encuentra en nuestro host local, Docker host irá a buscarla al registro Docker Hub y comprobará si está allí. Una vez que Docker ha encontrado la imagen, la misma es descargada y almacenada en nuestro Docker local.
Docker entonces usa esta imagen para crear un nuevo contenedor dentro en el sistema de ficheros. El contenedor tiene una red, dirección ip y un interface en modo puente que se comunica con nuestro host local. Finalmente, Docker ejecutará un comando en nuestro nuevo contenedor, en este caso ejecuta un Shell bash con el comando “/bin”bash”
Cuando el contenedor ha sido creado, Docker ejecuta el comando “/bin/bash” dentro de él y la Shell del contenedor se presenta así:
root@17e9e0d4c05b:/#
Trabajando con nuestro contenedor
Ahora estamos conectados dentro de un nuevo contenedor, con ID 17e9e0d4c05b como usuario root. Esta es una máquina Ubuntu en toda regla, podemos hacer lo que queramos en él, vamos a explorar un poco, comenzando por pedir su nombre de host.
root@17e9e0d4c05b:/# hostname
17e9e0d4c05b
root@17e9e0d4c05b:/#
Podemos ver que el nombre de host de nuestro contenedor es el identificador de contenedor. Vamos a ver el archivo /etc/hosts .
root@17e9e0d4c05b:/# cat /etc/hosts
172.17.0.2  17e9e0d4c05b
127.0.0.1   localhost
::1   localhost ip6-localhost ip6-loopback
fe00::0     ip6-localnet
ff00::0     ip6-mcastprefix
ff02::1     ip6-allnodes
ff02::2     ip6-allrouters
Docker también ha añadido una entrada al fichero host para nuestro contenedor con su dirección IP. Vamos a ver la configuración de red.
root@17e9e0d4c05b:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.2/16 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe11:2/64 scope link
valid_lft forever preferred_lft forever
Como podemos ver, tenemos la interfaz de bucle invertido lo y la interfaz de red eth0 estándar con una dirección IP de 172.17.0.2 como cualquier otro host. También podemos comprobar sus procesos en ejecución.
root@17e9e0d4c05b:/# ps -aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  18180  3300 ?        Ss   11:11   0:00 /bin/bash
root        19  0.0  0.1  15572  2148 ?        R+   12:14   0:00 ps -aux
Ahora vamos a ver si instalamos un paquete.
root@17e9e0d4c05b:/# apt-get update && apt-get install vim
Ya tenemos Vim instalado en nuestro contenedor. Podríamos seguir jugando con el contenedor durante mucho tiempo y cuando hayamos terminado escribiremos “exit”, y volverá a la línea de comandos del servidor.
Nuestro contenedor ahora ha dejado de funcionar. El contenedor sólo se ejecuta durante el tiempo que dura el comando que especificamos, en nuestro caso fue “/bin/bash”. Una vez que el comando ha terminado, se sale del contenedor, y por tanto, el contenedor es detenido.  El contenedor aún existe, podemos mostrar una lista de todos los contenedores que tenemos utilizando el comando “docker ps –a”
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
17e9e0d4c05b        ubuntu              "/bin/bash"         About an hour ago   Exited (0) 4 seconds ago                       cranky_mcclintock
Por defecto, cuando ejecutamos “docker ps”, vamos a ver sólo los contenedores en ejecución. Cuando se especifica la opción –a nos mostrará todos los contenedores, tanto parados como en funcionamiento.
También podemos utilizar el comando “docker ps –l” para ver el último contenedor que se ejecutó, aunque esté actualmente en marcha o parado.
Nos muestra también un poco de información sobre nuestro contenedor: su identidad, la imagen utilizada para crearlo, el comando de su última ejecución, cuando fue creado y su estado de salida (en nuestro caso es 0 porque sale normalmente utilizando el comando “exit”). También podemos ver que cada contenedor tiene un nombre.
Nombrando contenedores
Docker generará automáticamente un nombre al azar por cada contenedor que creamos. Podemos ver que el contenedor que acabamos de crear se llama cranky_mcclintock. Si queremos especificar un nombre particular del contenedor en lugar del nombre generado automáticamente, podemos hacerlo a través del parámetro “—name”.
$ docker run –name mi_primer_contenedor –i –t ubuntu /bin/bash
Este comando crearía un nuevo contenedor llamado mi_primer_contenedor. Un nombre de contenedor válido puede contener los caracteres: a a la z, la A a la Z, los dígitos del 0 al 9, el guión bajo, el punto y guión medio.
Podemos usar el nombre del contenedor en lugar del ID de contenedores en todos los comandos Docker, los nombres de contenedores son útiles para ayudar a identificar y construir conexiones lógicas entre contenedores y aplicaciones. También es mucho mas fácil recordar un nombre específico que un ID o incluso que un nombre aleatorio.
Los nombre son únicos. Si tratamos de crear dos contenedores con el mismo nombre el comando fallará. Tendríamos que eliminar el contenedor anterior con el mismo nombre antes de poder crear uno nuevo. Para eliminar el anterior, podríamos hacerlo con el comando “docker rm”.
Comenzando un contenedor parado
Si queremos iniciar un contenedor parado lo haríamos con el siguiente comando:
$ docker start mi_primer_contenedor
También podríamos referirnos al contenedor por su ID
$ docker start 17e9e0d4c05b
Ahora, si nosotros ejecutáramos el comando “docker ps” sin el parámetro –a, nosotros veremos nuestro contenedor ejecutándose.
Conectando a un contenedor
Nuestro contenedor se reiniciará con las mismas opciones que habíamos especificado cuando lo lanzamos con la orden de ejecución inicial. Así que hay una sesión interactiva dentro de nuestro contenedor en ejecución. Podemos volver a conectar a la sesión utilizando el comando “docker attach”
$ docker attach mi_primer_contenedor
o a través del ID del contenedor
$ docker attach 17e9e0d4c05b
y volveremos a la línea de comando bash de nuestro contenedor, debemos pulsar Enter para que salga la línea de comando.
$ docker attach mi_primer_contenedor
root@17e9e0d4c05b:/#
si nosotros salimos del Shell, nuestro contenedor se parará de nuevo.
Creación de contenedores como demonio o servicio
Además de los contenedores interactivos, podemos crear contenedores con mayor duración de funcionamiento. Contenedores que se ejecutan como un servicio o demonio no tienen sesión interactiva y son ideales para la ejecución de aplicaciones y servicios. La mayoría de contenedores lo más probable es que funcionen como servicio. Vamos a ver como ejecutar un contenedor como demonio.
$ docker run --name demonio -d ubuntu /bin/sh -c "while true; do echo hola mundo; sleep 1; done"
173cf34b9b95977756cab0d85117b849e646191ff473fb07ed164cb3ff3a647e
Hemos lanzado el comando “docker run” con el parámetro “-d” para decirle a Docker que ejecute el contenedor en segundo plano. También hemos especificado un bucle “while” como comando de nuestro contenedor, nos mostrará por la salida estándar hola mundo una y otra vez hasta que el contenedor se detenga o el proceso se detenga.
Con esta combinación de parámetros, en lugar de ver en pantalla el último contenedor nos ha devuelto un ID de contenedor y volvemos a nuestra línea de comando. Si ejecutamos “docker ps” veremos que el contenedor se está ejecutando.
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS               NAMES
173cf34b9b95        ubuntu              "/bin/sh -c 'while tr"   33 minutes ago      Up 33 minutes                           demonio
Ahora tenemos un contenedor funcionando como servicio en nuestro bucle “while”, vamos a ver en el interior del contenedor lo que está sucediendo. Para eso podemos usar el comando “docker logs”.
$ docker logs demonio
hola mundo
hola mundo
hola mundo
hola mundo
Aquí podemos ver los resultados de nuestro bucle while “echo hola mundo”. Docker nos muestra la salida de los  últimos registros y luego termina. También podemos ver los registros del contenedor de forma similar al comando “tail –f “.
$ docker logs -f demonio
Además se puede ver una parte de la cola de registros de un contenedor utilizando el parámetro “—tail –f”. Por ejemplo, podríamos ver los últimos 10 registros con “docker –tail 10 demonio” también podríamos ver los nuevos registros sin tener que leer el registro entero con “docker –tail 0 –f demonio”.
Para depurar de una forma más fácil, también podemos añadir el parámetro –t para ver nuestro registro con marcas de tiempo.
$ docker logs -ft demonio
2015-12-07T14:14:58.133609409Z hola mundo
2015-12-07T14:14:59.134666096Z hola mundo
2015-12-07T14:15:00.139933607Z hola mundo
2015-12-07T14:15:01.143312652Z hola mundo
Inspección de los procesos del contenedor
Además de los registros del contenedor, también podemos inspeccionar los procesos que se ejecutan dentro del contenedor. Para ello, se utiliza el comando “docker top”.
$ docker top demonio
PID                 USER                COMMAND
3175                root                /bin/sh -c while true; do echo hola mundo; sleep 1; done
7509                root                sleep 1
Podemos ver cada proceso, principalmente nuestro bucle while, con que usuario se está ejecutando y el PID del proceso
Estadísticas Docker
También podemos utilizar el comando “docker stats”. Éste muestra las estadísticas de uno o más contenedores Docker funcionando. Vamos a ver las estadísticas de nuestro contenedor demonio.
$ docker stats demonio
CONTAINER           CPU %               MEM USAGE/LIMIT     MEM %               NET I/O
demonio             0.23%               446.5 kB/2.1 GB     0.02%               648 B/648 B
Podemos ver el contenedor y su CPU, la memoria, uso de red y almacenamiento.
Ejecución de un proceso dentro de un contenedor
Podemos ejecutar procesos adicionales dentro de nuestros contenedores utilizando el comando “docker exec”. Hay dos tipos de comandos que se pueden ejecutar dentro de un contenedor. De fondo (como demonio) e interactiva. Tareas que se ejecutan en segundo plano del contenedor sin interacción y tareas interactivas que se mantienen en primer plano. Las tareas interactivas son útiles para tareas como abrir un Shell dentro de un contenedor. Vemos un ejemplo de una tarea en segundo plano.
$ docker exec -d demonio touch /etc/nuevo_fichero
El parámetro –d indica que estamos ejecutando un proceso en segundo plano, a continuación se especifica el nombre del contenedor en el que ejecutar el comando y el comando a ejecutar. En este caso, creará un nuevo archivo vacío llamado /etc/nuevo_fichero dentro de nuestro contenedor demonio. Podemos utilizar el comando “docker exec” para ejecutar tareas de mantenimiento, seguimiento o de gestión dentro de un contenedor en funcionamiento.
También podríamos ejecutar tareas interactivas como abrir un Shell dentro de nuestro contenedor “demonio”.
$ docker exec -t -i demonio /bin/bash
root@173cf34b9b95:/#
Los parámetros –t y –i son usados para ejecutar un contenedor interactivo  que captura la entrada estándar para nuestra ejecución, en nuestro caso, nuestro comando crea una nueva sesión de bash dentro del contenedor demonio. Entonces podríamos utilizar esta sesión para ejecutar otros comando dentro de nuestro contenedor.
Detener un contenedor ejecutado como servicio
Si queremos parar nuestro contenedor que se está ejecutando como servicio o demonio, podemos hacerlo con el comando “docker stop”
$ docker stop demonio
o a través de su ID.
El comando “docker stop” envía una señal SIGTERM al proceso en ejecución del contenedor docker. Si deseamos que un contenedor se pare inmediatamente podemos usar el comando “docker kill”, el cual enviará una señal SIGKILL al proceso contenedor.
Podemos utilizar el comando “docker ps” para comprobar que el contenedor ha parado. También podemos utilizar el comando “docker ps –n x”, el cual nos muestra los últimos x contenedores ejecutados o parados.
Reinicio automático de contenedores
Si un contenedor se ha detenido debido a un error, se puede configurar Docker para reiniciarlo utilizando el parámetro “--restart”. El parámetro “—restart” comprueba el código de salida del contenedor y toma una decisión si debe o no reiniciarlo. El comportamiento predeterminado es no reiniciar ningún contenedor.
Se debe especificar el parámetro “--restart” con el comando “docker run”
$ docker run --restart=always --name demonio1 -d ubuntu /bin/sh -c "while true; do echo hol; sleep1; done"
En este ejemplo, se ha establecido reiniciar siempre. Docker intentará reiniciar el contenedor, no importa lo que la salida de código devuelva.
Alternativamente, se puede especificar un valor de fallo en el que se reinicia el contenedor si sale con un código de salida distinto de cero. El parámetro también acepta un recuento de reinicio opcional.
“--restart=on-failure:5”
De esta forma, se intentará reiniciar el contenedor un máximo de cinco veces si se recibe un código de salida distinto cero.
  •  Información sobre nuestro contenedor
Además de la información que tenemos sobre nuestro contenedor utilizando el comando “docker ps”, podemos conseguir mucha más información a través del comando “docker inspect”.
$ docker inspect demonio1
[
{
"Id": "ff3363f968295b36ba634a0acedc6b15006a6abd74c5a2520da86477fa17a87e",
"Created": "2015-12-07T14:57:12.279724499Z",
"Path": "/bin/sh",
"Args": [
"-c",
"while true; do echo hol; sleep1; done"
],…..
El comando “docker inspect” interroga a nuestro contenedor y nos devuelve su información de configuración, incluyendo nombre, comandos, configuración de red y una amplia variedad de otros datos útiles.
También podemos consultar selectivamente resultados utilizando el parámetro “—format”.
$ docker inspect --format={{.State.Running}} demonio1
true
Esto nos devuelve el estado de ejecución del contenedor, que en nuestro caso es verdadero. También podemos obtener información útil, como la dirección IP del contenedor.
$ docker inspect --format='{{ .NetworkSettings.IPAddress }}' demonio1
172.17.0.2
Borrando un contenedor
Si hemos terminado con un contenedor, podemos borrarlo usando el comando “docker rm”
$ docker rm demonio
o bien podríamos utilizar el ID del contenedor. También podríamos borrar todos los contenedores con una simple línea:
$ docker rm ‘docker ps –a -q’
Este comando listará todos los contenedores actuales utilizando el comando “docker ps” con el parámetro “-a” para listar todos los contenedores y el parámetro “-q” solo devuelve los IDs de contenedor. Esta lista es pasada al comando “docker rm”, el cual borra cada contenedor.

INSTALANDO DOCKER

Vamos a ver de una forma práctica como podríamos manejar un entorno con Docker. La primera tarea que debemos realizar es instalar Docker, aunque hoy día hay muchos proveedores de servicios en la nube que nos ofrecen ya una plantilla de una máquina virtual con Docker preinstalado, no obstante en la mayoría de los casos no suele estar instalada la última versión.
La instalación habitualmente nos instala tanto el demonio o servicio Docker como un cliente Docker. Como se ha comentado anteriormente, el demonio Docker sólo funciona en un entorno Linux, aunque actualmente hay una versión beta para Windows Server, con lo que a la hora de instalarlo en Windows o Mac nos crea una máquina virtual Linux con el demonio Docker preinstalado.
Actualmente, el equipo de Docker recomienda desplegar Docker en Ubuntu, Debian o productos de la familia Red Hat (CentOS, Fedora, etc) y pone a nuestra disposición paquetes que podemos usar para instalar.
Los requerimientos para poder instalar Docker:
  • Arquitectura de 64-bit (actualmente x86_64 y amd64). Las plataformas de 32-bit no están actualmente soportadas.
  • Estar ejecutando un Linux con kernel 3.8 o posterior. Algunos kernels a partir de la versión 2.6.x y posteriores podrían ejecutar Docker correctamente, pero los resultados pueden variar, oficialmente no está soportado.
El servicio Docker escuchará por defecto en un Unix socket en /var/run/docker.sock para requerimientos entrantes, pero se puede cambiar la forma que escucha Docker con el flag –H cuando el servicio se está ejecutando, por ejemplo, para que escuche por todas las redes:
$ docker daemon –H tcp://0.0.0.0:2375
Para el desarrollo de este TFG se han realizado pruebas e instalaciones en 3 entornos, que si bien son diferentes a la hora de instalar, no lo serán tanto a la hora de ejecutar y manejar contenedores.
Instalación en la nube
Para esta prueba se ha optado por el proveedor Atlantic y se ha creado una máquina virtual, eligiendo la plantilla de una máquina con sistema operativo Ubuntu y Docker preinstalado. Como podemos ver en la figura 5, dentro las opciones de lanzamiento de una máquina virtual, además de elegir el lugar físico y el sistema operativo, nos permite elegir si queremos que tenga Docker preinstalado.
Dado que la versión de Docker que venía no estaba actualizada, se han tenido que actualizar los repositorios de Ubuntu según indica en la web oficial de Docker para poder utilizar la versión actual de Docker.
En la actualidad, muchos proveedores nos ofrecen Docker preinstalado además del utilizado en este caso, como Amazon EC2, Rackspace Cloud y Google Compute Engine.
instalación en un mac os x
Para esta prueba se ha utilizado un MacBook Air con sistema operativo “OS X El Capitan”. Para instalar Docker según indica en su web oficial se ha utilizado la herramienta Docker Toolbox, la cual incluye las siguientes herramientas de Docker:
  • Docker Machine
  • Docker Engine
  • Docker Compose
  • Kitematic
  • Un Shell ya configurado para poder utilizar Docker desde la línea de comandos
  • Una máquina virtual de Oracle VirtualBox
Al instalarlo, nos crea un icono denominado “Docker Quickstart Terminal.app”, que nos permite acceder al Shell configurado.
Aquí podemos ver el Shell en ejecución, el cual nos muestra la ip de la máquina virtual que corre el demonio Docker.
Puesto que realmente el demonio Docker está virtualizado, la dirección ip será la del servidor que contiene el demonio, así pues, si por ejemplo levantamos un contenedor en el puerto 8000 con un servidor web, tendremos que utilizar el formato “http:// ip de la maquina:8000”, mientras que si fuera un servidor Linux hubiéramos podido apuntar directamente a “http://localhost:8000”
Instalación en una máquina linux
Para esta prueba se ha instalado la distribución OpenSuse Leap 42.1
Hay unos pre-requisitos que son requeridos para instalar y ejecutar en un Linux hosts.
Lo primero debemos confirmar que contamos un kernel lo suficientemente reciente, se puede comprobar usando el comando “uname”.
$   uname -a
Siempre debemos asegurarnos que tenemos un kernel 3.8 o posterior.
La instalación en nuestro caso que tenemos OpenSuse es bastante sencilla, gracias a que va incorporada en el gestor de paquetes del sistema, lo mismo ocurre en otras distribuciones Linux muy conocidas, como Ubuntu.
A partir de ahora vamos a suponer que estamos utilizando el usuario root, en caso contrario, debemos anteponer “sudo” a cada instrucción, pues se requieren permisos de root para la instalación, en nuestro caso, instalamos los paquetes de Docker:
$ zypper in Docker
Luego arrancamos el servicio o demonio Docker
$ systemctl start Docker
Y ya esta instalado, podemos comprobar que todo funciona correctamente lanzando un contenedor básico llamado hello-world
$ docker run hello-world
Por último sería conveniente configurar que Docker se inicie al arrancar la máquina:
$ systemctl enable docker

COMPONENTES DE DOCKERS

  • Docker Engine
  • Docker Hub
  • Docker Machine
  • Docker Compose
  • Kitematic
  • Docker Swarm
  • Docker Registry

Docker Engine: Cuando hablamos de Docker Engine, nos referimos al demonio Docker que se ejecuta dentro del sistema operativo, puesto que Docker está basado en Linux (aunque actualmente hay versiones desarrollándose para Windows). Sólo es capaz de ejecutarse en este entorno, no obstante, dentro de su página web podemos encontrar instrucciones para poderlo instalar, tanto en Linux en diversas distribuciones, así como instrucciones para instalarlo en entornos Mac OS X y Windows. A Docker Engine también se le denomina Docker Cliente y Servidor.
Docker está disponible para Windows Server y Linux.
Lo que hace en realidad las instalaciones no Linux es levantar una máquina virtual con un Linux muy básico que contiene el demonio Docker, que es el que hace de servidor, y la parte cliente de Docker sí que puede ejecutar en otros sistemas operativos.
El Demonio o servidor es el proceso principal de gestión del engine que corre en la máquina anfitriona. El usuario nunca interactúa con el demonio directamente, sino que lo hace por medio del cliente.
El Cliente es el binario que constituye la interfaz de usuario entre el cliente y el demonio del servicio. Acepta y procesa las acciones del cliente a través de una serie de comandos.
Una Imagen de Docker es análogamente como una plantilla de una máquina virtual, las imágenes son utilizadas para crear contenedores. Las imágenes se pueden actualizar fácilmente y se pueden compartir públicamente, por ejemplo, podemos descargar una imagen con WordPress y ejecutarlo en nuestro entorno, como haríamos con las aplicaciones de una máquina virtual.
Las imágenes están construidas por capas, los contenedores se lanzan o ejecutan desde imágenes, las cuales están construidas previamente. Su formato por capas se construye paso a paso usando una serie de instrucciones, por ejemplo: añadir un fichero, ejecutar un comando, abrir un puerto. Se podría considerar que las imágenes son el “código fuente” para nuestros contenedores, los cuales son portables y pueden ser compartidos, almacenados y actualizados.
  • Los Registros de Docker son almacenes de imágenes tanto para acceso privado como público. El lugar habitual donde se comparten públicamente la colección de imágenes se denomina Docker Hub. Cualquiera puede crear una cuenta en Docker Hub y usarla para compartir y almacenar nuestras imágenes. También contiene mas de 10.000 imágenes que otras personas han construido y compartido.
  • Un Contenedor de Docker es similar a una carpeta/directorio de un sistema de ficheros, el contenedor alberga todo lo necesario para que una aplicación pueda ejecutarse de forma aislada. En un contenedor, podemos empaquetar nuestras aplicaciones y servicios. Un contenedor lo podemos iniciar, parar, mover o borrar. Un contenedor se ejecuta usando una imagen y puede contener uno o más procesos ejecutándose. Se podría decir que las imágenes construyen y empaquetan aspecto de Docker y los contenedores son los que ejecutan y dan vida a esos aspectos.
  • En un entorno de máquinas virtuales, tenemos máquinas individuales donde se ejecuta un sistema operativo completo, con las librerías necesarias y el software que ejecuta las aplicaciones. Con Docker, el “sistema operativo invitado” se convierte en el “Hypervisor”, cada contenedor comparte recursos con el OS anfitrión, en particular, el núcleo de Linux. Este último punto es importante, ya que permite utilizar contenedores que usen distintos sistemas operativos, proporcionando gran flexibilidad. Así que podríamos tener un Ubuntu con SO anfitrión que contuviese contenedores donde corriese CentOS, Debian o Redhat Linux.
Desplegar código desde desarrollo a producción se hace usando contenedores sin que su contenido requiera ningún cambio en alguna etapa intermedia.

Docker Hub
El Docker Hub es un servicio de registro basado en la nube para la construcción y envío de aplicaciones o servicios de contenedores. Proporciona un recurso centralizado para el descubrimiento de la imagen de contenedores , la distribución y la gestión del cambio , el usuario y la colaboración en equipo , y la automatización del flujo de trabajo a lo largo de la línea de desarrollo .
Específicamente , Docker Hub ofrece las siguientes características y funciones principales :
  • Repositorio de imágenes: Buscar, administrar y enviar y obtener imágenes oficiales de la comunidad y bibliotecas de imágenes privadas.
  • Construcciones automatizadas : Creación automática de nuevas imágenes cuando realiza cambios en una fuente GitHub o un repositorio Bitbucket.
  • WebHooks : Una característica para automatizar construcciones, WebHooks permite desencadenar acciones después de enviar con éxito a un repositorio.
  • Organizaciones: Crear grupos de trabajo para gestionar el acceso de usuarios a los repositorios de imágenes.
  • Integración GitHub y Bitbucket: Añadir las imágenes alojadas en Docker Hub a sus flujos de trabajo.
Docker Machine
Docker Machine permite crear máquinas virtuales en diferentes proveedores, en una máquina anfitrión con VirtualBox hasta Amazon EC2 o Digital Ocean. La lista de controladores soportados es bastante amplia.
Para empezar a utilizar Docker, primero debemos configurar un demonio de Docker. Docker Machine configura automáticamente Docker en su ordenador, en los proveedores en la nube, y dentro de su centro de proceso de datos. Docker machine instala el demonio Docker (también llamado Docker engine) en los anfitriones y luego configura el cliente Docker para que se comunique con los demonios de Docker.
Docker machine automatiza todas las tareas de aprovisionamiento e instalación de un único host Docker .
Con el siguiente comando de ejemplo crearíamos una máquina virtual llamada “dev” dentro de nuestro virtualbox local
$ docker-machine create -d virtualbox dev
Por defecto, cuando se instala Docker en Mac os x, nos instala una aplicación llamada Docker Quickstart Terminal, la cual en realidad arranca usando Docker-machine, una máquina virtual llamada “default” en virtualbox.

Docker Compose
Nos permite definir aplicaciones de varios contenedores en un archivo con las mismas propiedades que indicaríamos con el comando “Docker run” individualmente. Con un único comando, podremos iniciar todos los contenedores y en el orden que especifiquemos.
El archivo descriptor nos puede servir no sólo como forma de iniciar los contenedores en un entorno de desarrollo, sino de documentación de la aplicación en la que veremos claramente que contenedores, imágenes, volúmenes, enlaces y demás propiedades tienen.
El descriptor de contenedores
El descriptor de los contenedores o archivo de definición a usar con Docker Compose es un archivo de texto con formato yaml en la que especificamos los diferentes contenedores y sus propiedades. Básicamente podemos indicar las mismas propiedades que si lo hiceramos arrancando los contenedores individualmente con el comando “docker run”.
Iniciar los contenedores con Docker Compose
Escrito el archivo de definición de contenedores y llamándolo docker-compose.yml, podemos iniciar los contenedores con el comando docker-compose up estando en el mismo directorio de trabajo donde esté ubicado el archivo yml (y previamente habiendo iniciado el servicio o demonio de docker). Con “docker-compose ps” podremos ver el estado de los contenedores y de cuales está compuesta la aplicación. Con la opción –help podemos ver la lista completa de comandos disponibles.
Docker Compose inicia los contenedores en el orden que hemos indicado en el archivo de definición, las trazas emitidas de los servicios de los contenedores aparecerán en la terminal si iniciamos los contenedores en primer plano y con Ctrl+C se pararán los contenedores. Indicando la opción -d los contenedores se iniciarán en segundo plano, con “docker-compose stop” podremos pararlos, con “docker-compose restart” reiniciarlos, “docker-compose rm” para eliminar completamente los contenedores y con “docker-compose logs” veremos las trazas emitidas por los servicios que nos serán de utilidad si iniciamos los contenedores en segundo plano.

Kitematic
Es un proyecto open source (de código abierto) creado para simplificar y racionalizar el uso de Docker en Mac o Windows. Kitematic automatiza el proceso de instalación y configuración de Docker y proporciona una interfaz intuitiva gráfica de usuario para el funcionamiento de los contenedores Docker. Kitematic se integra con Docker-machine para provisionar máquinas virtuales en VirtualBox e instalar el demonio Docker en su máquina.
Una vez instalada la interfaz gráfica de usuario, Kitematic lanza y permite desde la pantalla de inicio en la que muestra las imágenes disponibles que se puedan ejecutar al instante con una sola pulsación de raton. Podemos buscar cualquier imagen pública sobre Docker Hub en Kitematic con tan sólo escribir en la barra de búsqueda. Podemos utilizar la interfaz gráfica de usuario para crear, ejecutar y administrar sus contenedores con sólo hacer clic en los botones. Kitematic le permite alternar entre el Docker CLI y la GUI. Kitematic también automatiza características avanzadas, tales como la gestión de puertos y configuración de volúmenes. Podemos utilizar Kitematic para cambiar las variables de entorno, registros de log, y hacer clic en un sólo terminal en su contenedor Docker, todo desde la interfaz gráfica de usuario.
Lista de contenedores: Listas Kitematic lista todos los contenedores, tanto los que están ejecutándose como los inactivos en el lado izquierdo, debajo del vínculo "Nuevo Contenedor".
La lista contenedor incluye todos los contenedores, incluso los que no han sido iniciados por Kitematic, dándole una vista rápida del estado del demonio Docker.
Se puede hacer clic en cualquier contenedor para ver sus logs (la salida del proceso principal del contenedor), reiniciar, detener o ejecutar en ese contenedor.
La gestión de contenedores podemos hacerla a través del GUI Kitematic. Está aún en fase “Alpha”, pero funciona a la perfección. Desde ella podremos buscar en el repositorio Docker Hub y administrar los contenedores e imágenes que tengamos ya descargadas y/o ejecutándose.
Tenemos una guía completa en: https://docs.docker.com/kitematic/userguide/
Docker Swarm
Swarm es la forma más fácil de ejecutar un contenedor Docker en producción. Permite que una aplicación que está en desarrollo implementarlo en un clúster de servidores.
Debido a que Docker Swarm utiliza el API estándar Docker, cualquier herramienta que se comunique con el demonio Docker puede utilizar Swarm para escalar de forma transparente a múltiples host.
Algunas de las herramientas soportadas serían:
  • Dokku
  • Docker Compose
  • Krane
  • Jenkins
Y por supuesto el cliente Docker en sí es compatible.
El primer paso para el uso de swarm en nuestra red es obtener la imagen de Docker Swarm. Después, usando Docker configurar el gestor de swarm y todos los nodos ejecutarán Docker Swarm, esto requiere abrir un puerto TCP en cada nodo para la comunicación con el gestor Swarm, tener Docker instalado en cada nodo y crear y administrar certificados TLS para garantizar la seguridad del clúster.
Como punto de partida, el método manual es el más adecuado para los administradores experimentados. La alternativa sería utilizar Docker Machine para instalar Swarm.
Usando Docker Machine, se puede instalar rápidamente un Docker Swarm en un proveedor, en la nube o dentro de nuestro propio centro de proceso de datos. Si tenemos VirtualBox instalado en la máquina local, podría crear rápidamente Docker Swarm en un entorno local. Este método genera automáticamente un certificado para garantizar la seguridad del clúster.
El uso de Docker Machine es el mejor método para comenzar con Docker Swarm.
Docker Registry
Es un repositorio que nos permite almacenar nuestras propias imágenes.
Por defecto, el registro se levanta sobre una conexión http en claro y sin autenticación.
En el momento de escribir esto Docker registry va por la versión 2.
docker run -d -p 5000:5000 --restart=always --name registry registry:2

¿CÚAL ES LA DIFERENCIA ENTRE DOCKER Y UNA MÁQUINA VIRTUAL?

Los contenedores tienen beneficios de aislamiento y asignación de recursos similares a las máquinas virtuales , pero con un enfoque arquitectónico diferente que les permite ser mucho más portátiles y eficientes.
Se trata de un choque de titanes de virtualización, por un lado tenemos la tecnología de máquinas virtuales, y por otro la tecnología de contenedores. En realidad, ambas tecnologías son complementarias y tienen cualidades distintas y pueden ser utilizadas en tándem para obtener un beneficio combinado.
Los contenedores proporcionan aislamiento de procesos a nivel de sistema operativo, mientras que las máquinas virtuales ofrecen el aislamiento en la capa de abstracción de hardware, es decir, la virtualización de hardware. Así que en casos de uso IaaS (Infraestructura como servicio) la máquina virtual es el ajuste ideal, mientras que los contenedores son los más adecuados para garantizar la portabilidad del software y modular su ensamblaje y transporte. Una vez más, las dos tecnologías se pueden utilizar en combinación con otras para obtener beneficios adicionales, por ejemplo, los contenedores Docker se pueden crear dentro de las máquinas virtuales para hacer una solución ultra-portátil.
Máquina Virtual
La diferencia, sin duda es tanto conceptual como de peso, sobre todo de peso. Los sistemas más extendidos de virtualización -aunque con numerosas virtudes- tienen un problema en cuanto a la portabilidad, puesto que un snapshot incluye tanto el Sistema Operativo (guest/invitado) como las librerías y aplicaciones. Esto, en algunas ocasiones puede representar una ventaja, pero cuando se trata de replicar entornos que debemos transmitir por red, por ejemplo, desde un entorno local a un CPD, resulta tedioso, y más si tenemos que repetirlo con frecuencia.
Docker
El notable éxito de esta tecnología tiene como característica principal la ligereza, y por extensión, la portabilidad. Los contenedores (dockers) consisten en una copia de las configuraciones, las librerías/binarios y la aplicación o aplicaciones. Evitamos todo el peso del sistema, sólo nos tenemos que asegurar que el Sistema de destino es compatible con Docker. Se pueden considerar los dockers como máquinas virtuales ligeras.
Entrando un poquito más en materia, y estudiando la tecnología, vemos que en realidad Docker no es un sistema de virtualización al uso, está basado en LXC (LinuX  Containers) que a su vez es un método para ejecutar entornos y asignación de recursos (cpu, memoria, i/o) mediante una característica del kernel llamada cgroups.
Básicamente, un Docker es un contenedor donde se encuentra todo lo que una aplicación necesita para funcionar sin necesidad de acceder a recursos externos, con lo cual controlamos mucho mejor las configuraciones y evitamos que algún otro programa actualice o elimine una librería que inconscientemente, afecte en la ejecución y estabilidad de nuestro programa. Asimismo, la portabilidad se facilita porque el engine de Docker se encarga de su integridad y de la gestión de recursos.

¿Qué es Docker?

Docker es una plataforma de código abierto (Open Source) para que desarrolladores y administradores de sistemas puedan construir, cargar, y ejecutar aplicaciones. Consiste en un entorno de ejecución ligero, portable y herramientas de empaquetado, como resultado se puede implementar más rápido y ejecutar la misma aplicación sin cambios tanto en portátiles, centros de proceso de datos o máquinas virtuales en la nube.
Docker es una herramienta que permite crear contenedores. Estos contenedores, son sistemas de virtualización ligera que nos permiten tener aplicaciones empaquetadas, de forma que sean autosuficientes (al disponer de todas las bibliotecas y dependencias que necesiten), lo cual facilita que posteriormente puedan ser desplegados en cualquier otro sistema operativo compatible con Docker.
Docker es una plataforma para la construcción, el transporte y la ejecución de aplicaciones distribuidas. Le da a los programadores, equipos de desarrollo y administradores de sistemas la caja de herramientas común que necesitan para disponer de un sistema distribuido y en red.
Construir: Docker permite componer una aplicaciones desde micro servicios, sin preocuparse por las incoherencias entre los entornos de desarrollo y producción, y sin bloquear ninguna plataforma ni lenguaje de programación.
Portabilidad de aplicaciones y flexibilidad de la infraestructura: Empaquetar una aplicación, dependencias y configuraciones juntos para asegurarse de que su aplicación funcionará sin problemas en cualquier entorno y en cualquier infraestructura al igual que en la máquina original.
Actualización dinámica, las aplicaciones construidas en contenedores Docker son fáciles de actualizar y escalar sin preocuparse de los demás contenedores. Los contenedores ligeros pueden manejar en un segundo gran cantidad de recursos.
Docker es un proyecto de código abierto con el que podremos crear contenedores fácilmente. Estos contenedores se podrían definir como máquinas virtuales ligeras, menos exigentes con los chips y  memorias de los equipos donde se ejecutarán. Sus principales ventajas son:
  • Portabilidad: El contenedor Docker podremos desplegarlo en cualquier otro sistema (que soporte esta tecnología), con lo que nos ahorraremos el tener que instalar en este nuevo entorno todas aquellas aplicaciones que normalmente usemos.
  • Ligereza: El tamaño de este sistema no tiene comparación con cualquier otro sistema de virtualización más convencional que estemos acostumbrados a usar. Por poner un ejemplo, cualquier imagen de Ubuntu que queramos usar ocupará en torno a 1Gb si contamos únicamente con la instalación limpia del sistema. En cambio, un Ubuntu con Apache y una aplicación web, ocuparía alrededor de 180Mb, lo que nos demuestra un significativo ahorro a la hora de almacenar diversos contenedores que podamos desplegar con posterioridad.
  • Autosuficiencia: Un contenedor Docker no contiene todo un sistema completo, sino únicamente aquellas librerías, archivos y configuraciones necesarias para desplegar las funcionalidades que contenga. Asimismo, Docker se encarga de la gestión del contenedor y de las aplicaciones que contenga. Además, su ligereza hace que en equipos con algunos años se desenvuelva prácticamente igual que el sistema anfitrión, aparte de ofrecernos un entorno a base de capas para controlar los cambios que se hagan en la máquina virtual o contenedor.
Para obtener esta fluidez, Docker extiende LXC (LinuX Containers), un sistema de virtualización ligero que permite crear múltiples sistemas totalmente aislados entre sí sobre la misma máquina o sistema anfitrión. Y no se emula un sistema operativo completo, sólo las librerías y sistemas de archivos necesarios para la utilización de las aplicaciones que tengamos instaladas en cada contenedor.
El notable éxito de esta tecnología se puede comprobar, además de por sus virtudes, por la aceptación e implicación de grandes empresas que acogen este tipo de servicios en entornos de producción. Ejemplo de ello serían Digital Ocean y Google, que integran soporte para este software.
También sería destacable la inversión de Microsoft en adaptar esta tecnología al mundo Windows, ya que en la versión de Windows Server 2016 Preview existente en este momento, ya incluye la posibilidad de instalar una versión de Docker específica para este entorno.
Docker se compone de tres elementos fundamentales:
  1. Contenedores Docker: Son como un directorio, contienen todo lo necesario para que una aplicación pueda funcionar sin necesidad de acceder a un repositorio externo al contenedor. Cada uno de éstos es una plataforma de aplicaciones segura y aislada del resto que podemos encontrar o desplegar en la misma máquina host. Para hacer un símil con las tecnologías actuales, un contenedor sería como una máquina virtual.
  2. Imágenes Docker: La imagen Docker podríamos entenderla como un sistema operativo con aplicaciones instaladas. Sobre esta base, podremos empezar a añadir aplicaciones que vayamos a necesitar en otro equipo donde tengamos intención de usar la imagen. Docker nos ofrece una forma muy sencilla de actualizar las imágenes que tengamos creadas, así como para crear imágenes nuevas, sería similar a las plantillas que actualmente se tienen preparadas para crear nuevas máquinas virtuales.
  3. Repositorios Docker: También conocidos como Registros Docker, contienen imágenes creadas por los usuarios y puestas a disposición del público. Podemos encontrar repositorios públicos y gratuitos en su totalidad o repositorios privados donde se pueden comprar las imágenes que necesitemos. Estos registros, permiten desarrollar o desplegar aplicaciones de forma simple y rápida en base a plantillas, reduciendo el tiempo de creación o implementación de aplicaciones o sistemas. También podemos optar por instalar nuestro propio repositorio o Registro Docker para usarlo internamente en nuestra organización que, como no podía ser de otra forma, se instala en un contenedor Docker.

Resumen con las principales características y funcionalidades de Docker:
  • Autogestión de los contenedores.
  • Es fácil de instalar.
  • Compatible con muchos sistemas operativos y sistemas cloud.
  • Aplicaciones libres de las dependencias instaladas en el sistema anfitrión.
  • Capacidad para desplegar multitud de contenedores en un mismo equipo físico.
  • Puesta en marcha de los servicios en un abrir y cerrar de ojos.
  • Contenedores muy livianos que facilitan su almacenaje, transporte y despliegue.
  • Capacidad para ejecutar una amplia gama de aplicaciones (prácticamente cualquier cosa que se nos ocurra podrá ejecutarse en un contenedor Docker).
  • Compatibilidad multi-sistema, podremos desplegar nuestros contenedores en multitud de plataformas.
  • La aplicación base de Docker gestionará los recursos existentes para asignarlos responsablemente entre los contenedores desplegados.
  • Podremos establecer una base desde la que comenzar nuestros proyectos, lo que nos ahorrará el tiempo de preparar el entorno para cada uno de ellos.
  • Podremos compartir nuestros contenedores para aumentar los repositorios de Docker, así como beneficiarnos de los que compartan los demás.

El origen de los contenedores

El origen de los contenedores está basado en contenedores de Linux, los cuales mantienen unidas las aplicaciones y sus componentes de tiempo de ejecución mediante la combinación de aislamiento de aplicaciones ligeras y un método de implementación basado en imágenes.
Los contenedores introducen la autonomía para las aplicaciones agrupándolas con las bibliotecas y otros binarios de los que dependen. Esto evita los conflictos entre aplicaciones que, de otro modo, dependerían de componentes clave del sistema operativo host subyacente. Los contenedores no incluyen un kernel (OS), por lo que son más rápidos y ágiles que las máquinas virtuales. No obstante, esto significa que todos los contenedores de un host deben utilizar el mismo kernel.
 Las ventajas principales de los contenedores por roles
  • Para los desarrolladores de aplicaciones: Lanzamientos de calidad superior, mejor escalabilidad de aplicaciones, mayor aislamiento de aplicaciones.
  • Para arquitectos de TI: Escalabilidad horizontal más rápida, ciclos de pruebas más cortos, menos errores de implementación.
  • Para Operaciones de TI: Lanzamientos de calidad superior, sustitución eficiente de todas las máquinas virtuales en producción, gestión de aplicaciones más fácil.
Portabilidad de aplicaciones
Los contenedores dependen del kernel y del sistema operativo para funcionar. Los elementos clave de construcción se deben estandarizar para que las aplicaciones en contenedores sean verdaderamente portátiles entre los host de contenedor.