Академический Документы
Профессиональный Документы
Культура Документы
Cochabamba – Bolivia
2018
ii
Resumen 6
Introducción 7
1. Generalidades 8
2. Metodología 9
3. Docker 10
4. Implementación de Docker 14
6. Docker Compose 23
7. Repositorio DockerHub 26
3
4
8.1 Kubernetes 27
10.1 Análisis 31
10.2 Diseño 32
10.3 Codificación 32
10.4 Pruebas 32
10.5 Instalación 33
11.1 Despliegue 34
12. Conclusiones 37
13. Bibliografía 39
5
Resumen
Docker es un proyecto que permite crear aplicaciones en contenedores de software que son ligeros,
portátiles y autosuficientes.
La principal diferencia de Docker con los modelos tradicionales de virtualización es que utiliza los
contenedores en vez de las máquinas virtuales.
Los contenedores son un paquete de elementos que permite crear un entorno donde correr
aplicaciones independientemente del sistema operativo.
Estos contenedores pueden ser compartidos de manera privada o ser usados por la comunidad, a
través de DockerHub, donde pueden ser encontrados entornos de trabajos para diferentes tipos de
proyectos de software. Docker además permite describir un conjunto de contenedores que se
relacionan entre ellos. El despliegue y la configuración de una aplicación dentro el proceso de
desarrollo de software es más sencillo gracias a Docker.
Palabras clave: docker, imagen, contenedor docker, Dockerfile, docker compose, docker hub.
7
Introducción
Dentro del proceso de desarrollo de software, existen varias etapas en las que participan diferentes
recursos, cada uno de estos debe tener el entorno de desarrollo necesario para poder cumplir con
sus objetivos, y en muchos casos un mismo recurso debe tener varios entornos de desarrollo al
mismo tiempo. Preparar estos entornos consume bastante tiempo.
Docker ofrece una solución a este problema dando la posibilidad de encapsular el entorno de
desarrollo dentro de un contenedor, el cual se traduce en una imagen Docker que puede ser
instanciada de manera rápida.
1. Generalidades
El concepto de contenedores no es algo nuevo, las primeras ideas aparecieron bajo el comando
“chroot()” en entornos Unix, seguidamente pasaron a utilizarse en Linux y actualmente ya se
pueden utilizar en sistemas operativos de Windows y MacOs.
Docker nació de un proyecto en una compañía francesa llamada “dotCloud” que ofrecía a sus
clientes principalmente servicios PaaS (Platform as a Service). Bajo la dirección de Solomon
Hykes, en principio utilizaba LXC (Linux Containers) como su driver de ejecución, posteriormente
crearon su propia librería “libcontainer” para este propósito que fue liberado en la versión 0.9.
Chroot (1979), se introdujo durante el desarrollo de Unix V7, es una llamada al sistema que permite
cambiar el directorio raíz de un proceso y sus hijos a una nueva ubicación en el sistema de archivos.
Este avance fue el inicio del aislamiento del proceso.
FreeBSD Jails (2000), lanzado por un proveedor de hosting de entorno compartido, permite lograr
una clara separación entre sus servicios y los de sus clientes por seguridad y facilidad de
administración. Los administradores pueden dividir un sistema informático FreeBSD en varios
sistemas independientes más pequeños, llamados "Jails", con la capacidad de asignar una dirección
IP para cada sistema y configuración.
LXC (2008), LXC (LinuX Containers) fue la primera y más completa implementación del gestor
de contenedores Linux, utiliza la funcionalidad "cgroups" y "namespaces" de Linux, y funcionaba
en un solo kernel. Es una tecnología de virtualización a nivel de sistema operativo y permite que
un servidor físico ejecute múltiples instancias de sistemas operativos aislados conocidos como
entornos virtuales.
9
2. Metodología
3. Docker
Docker permite al usuario crear "imágenes" de una aplicación con todas sus dependencias que
necesita para poder ejecutarse. Las imágenes se inicializan en una o varias instancias, a los que se
los denomina "contenedores", de esta manera, solo se necesita crear el contenedor para tener una
aplicación funcional. (Mouat, 2016)
La principal diferencia es que una máquina virtual necesita tener virtualizado todo el sistema
operativo, mientras que el contenedor Docker aprovecha el sistema operativo sobre el que se
ejecuta, compartiendo el Kernel e incluso parte de sus bibliotecas. Para el sistema operativo
anfitrión, cada contenedor no es más que un proceso que corre sobre el Kernel.
Tamaño en disco, una máquina virtual convencional puede ocupar bastante, sin embargo, los
contenedores Docker sólo contienen lo que las diferencia del sistema operativo en el que se
ejecutan, ocupando una media de 150-250 Mb. (Thakur, 2016)
Un contenedor, no es más que una imagen puesta en ejecución a la que otorgamos recursos. Estas
imágenes están compuestas por capas de solo lectura a las que se le añade una capa superior de
escritura que perdurará sólo mientras el contenedor está en ejecución. En la construcción de la
imagen se crea una capa por cada cambio que se hace.
En un principio contamos con una imagen base, sobre la que realizaremos los diferentes cambios.
Tras confirmar estos cambios mediante la aplicación Docker, crearemos la imagen que usaremos.
Esta imagen contiene únicamente las diferencias que hemos añadido con respecto a la base. Cada
vez que queramos ejecutar esta imagen necesitaremos la base y las “capas” de la imagen. Docker
se encargará de acoplar la base, la imagen y las diferentes capas con los cambios para darnos el
entorno que queremos desplegar para empezar a trabajar. En la Figura 3 se muestra el sistema de
imágenes Docker. (McKendrick & Gallagher, 2017)
13
4. Implementación de Docker
Docker puede ser implementado en los diferentes sistemas operativos: Linux, Windows, MacOS.
Los requisitos mínimos para poder instalar Docker en Linux son: Una versión de 64bits con kernel
igual o superior a 3.10, un usuario con permiso de “sudo”.
A continuación, se muestra los comandos necesarios para instalar Docker en una distribución de
Linux Ubuntu 16.04 64-bit que cumple con los requisitos mínimos. Para obtener la última versión,
se recomienda instalar desde el repositorio oficial de Docker. (Docker Inc., 2018)
Actualizar la base de datos de paquetes, con los paquetes Docker desde el repositorio recién
agregado:
Instalar Docker:
Verificar que el demonio de Docker está iniciado y el proceso habilitado para iniciar en el arranque:
Con estos pasos, la instalación ha sido completada. En este punto se tiene el servicio de Docker
(demonio) corriendo, y también el cliente Docker (docker), que es una utilidad de línea de
comando para interactuar con el servicio de Docker. La sintaxis tiene la forma:
$ Docker
$ docker info
Una vez terminada la instalación de Docker, al igual que en Linux, se tiene corriendo el servicio
de Docker (demonio), y también el cliente Docker (docker), como ya se mencionó anteriormente,
18
es un utilitario para interactuar con el servicio de Docker. De esta manera, ya estaría configurado
Docker en Windows.
En el sistema operativo MacOS (al igual que en Windows), anteriormente utilizaba VirtualBox,
conjuntamente con la herramienta ToolBox para poder instalar y configurar Docker. A partir de la
distribución “Yosemite“, es posible prescindir de la herramienta ToolBox y utilizar Docker de
manera nativa gracias a la capa de virtualización “Hyperkit”. (Docker Inc., 2018)
Para poder hacer una instalación nativa de Docker, se requiere Yosemite 10.10.3 o distribuciones
superiores. La instalación es bastante sencilla, Docker provee el archivo binario en su sitio oficial
de la web, los pasos a seguir:
Una vez terminada la instalación, se tiene, tanto el servicio Docker (demonio) y el cliente Docker
(docker) en ejecución.
19
Las imágenes Docker son la base para la creación de los contenedores. Una nueva imagen puede
ser creada a partir de una imagen base (imagen creada con anterioridad) a través de Dockerfile, o
también puede ser creada a partir de un contenedor.
Un Dockerfile es un fichero de texto donde se indica los comandos que se deben ejecutar sobre
una imagen base para crear una nueva imagen. Docker construye la nueva imagen leyendo las
instrucciones del fichero Dockerfile y la información de un entorno (un directorio, repositorio git).
(Thakur, 2016)
La creación de la imagen es ejecutada por el servicio Docker que recibe toda la información del
entorno, por lo tanto, el archivo Dockerfile debe estar en un directorio con todos los ficheros
necesarios para la creación de la imagen.
El comando "docker build" ejecuta las instrucciones de un Dockerfile línea por línea, cada
instrucción ejecutada crea una imagen intermedia. Este es un mecanismo de caché, de manera que,
si en algún momento falla la creación de la imagen, al corregir el Dockerfile y volver a construir
la imagen, para los pasos que habían funcionado anteriormente se utilizan las imágenes
intermedias, y el proceso continúa por la instrucción que causó el fallo. (Docker Inc., 2018)
FROM
Esta instrucción indica la imagen base que va a utilizar para seguir futuras instrucciones. Buscará
la imagen localmente, si no se encuentra, descargará de internet.
Sintaxis:
FROM <imagen>
20
FROM <imagen>:<tag>
LABEL
La instrucción LABEL agrega metadatos a una imagen. Un LABEL es un par clave-valor.
Sintaxis:
RUN
Esta instrucción ejecuta cualquier comando en una capa nueva encima de una imagen y hace un
commit de los resultados. Esa nueva imagen intermedia es usada para el siguiente paso en el
Dockerfile.
Sintaxis:
ENV
Esta instrucción configura las variables de ambiente, estos valores estarán en los ambientes de
todos los comandos que sigan en el Dockerfile.
Sintaxis:
Estos valores persistirán al momento de lanzar un contenedor de la imagen creada y pueden ser
usados dentro de cualquier fichero del entorno, por ejemplo, un script ejecutable. Pueden ser
sustituida pasando la opción -env en docker run. Ejemplo:
ADD
21
Esta instrucción copia los archivos o directorios de una ubicación especificada y los agrega al
sistema de archivos del contenedor en la ruta especificada. Tiene dos formas:
Sintaxis:
EXPOSE
Esta instrucción le especifíca a docker que el contenedor escucha en los puertos especificados en
su ejecución. EXPOSE no hace que los puertos puedan ser accedidos desde el host, para esto se
debe mapear los puertos usando la opción -p en docker run.
Ejemplo:
EXPOSE 80 443
CMD y ENTRYPOINT
Estas dos instrucciones nos permiten especificar el comando que se va a ejecutar por defecto, sino
indicamos ninguno cuando ejecutamos el docker run. Normalmente las imágenes bases están
configuradas con estas instrucciones para ejecutar el comando /bin/sh o /bin/bash.
Para construir la imagen se debe ejecutar el comando “build” del cliente Docker dentro de la
carpeta del proyecto:
Una vez construida la imagen, podemos generar un contenedor en base a esta imagen con el
comando “run” del cliente Docker:
Para la creación de una imagen Docker a partir de un contenedor, primeramente, se debe identificar
el ID del contenedor Docker. El comando “ps” nos permite listar todos los contenedores y sus
principales propiedades, entre ellas el ID:
$ docker ps
Una vez identificado el ID del contenedor, el comando “commit” del cliente Docker nos permite
crear una nueva imagen a partir de este contenedor:
6. Docker Compose
Docker compose simplifica el uso de Docker generando scripts que facilitan el diseño y la
construcción de servicios en aplicaciones multi-contenedor.
Docker Compose es una herramienta para definir y correr aplicaciones multicontenedores. Se hace
uso del archivo “docker-compose.yml” para configurar los servicios que necesita una aplicación.
El archivo de compose provee instrucciones para documentar y configurar todas las dependencias
de la aplicación, se define la imagen o imágenes a utilizar, la exposición de puertos o los
volúmenes, y al final solo se tiene que hacer uso del comando "docker-compose up" para levantar
todo el ambiente. (Karl & Sean P., 2015)
Ejecuta todas las instrucciones del archivo docker-compose.yml, levanta todos los servicios.
$ docker-compose up
25
$ docker-compose down
$ docker-compose ps
$ docker-compose exec
26
7. Repositorio DockerHub
Docker Hub permite a los usuarios subir y compartir en la nube, las imágenes Docker construidas.
Docker Hub es el repositorio en la nube de Docker donde se encuentran todas las imágenes de los
contenedores, 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 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. (Docker Inc.,
2018)
Para subir una imagen al repositorio de Docker Hub, se debe ejecutar el siguiente comando:
En la actualidad las aplicaciones son complejas y no basta con desplegar un solo contenedor en
producción, salvo en los casos más sencillos. Por lo general se necesitan varios contenedores, que
además deben escalar de manera diferente y otras complejidades. Por ejemplo, un contenedor para
el Front-End, uno o varios para la interfaz de servicios, otro para la base de datos, y ni hablar de
aplicaciones distribuidas que utilizan microservicios.
Los contenedores son tan ligeros y flexibles que han dado lugar a nuevas arquitecturas de
aplicaciones. Este nuevo enfoque consiste en empaquetar los diferentes servicios que constituyen
27
Configuración automática.
Despliegue automático de servicios basados en contenedores.
Balanceado de carga.
Auto-escalado y auto-reinicio de contenedores.
Control del estado de cada contenedor.
Intercambio de datos y networking.
8.1 Kubernetes
Figura 7: Kubernetes
Fuente: (Domingo, 2016)
Swarm es la solución que propone Docker ante los problemas de los desarrolladores a la hora de
orquestar y planificar contenedores a través de muchos servidores. Swarm viene incluido junto al
motor de Docker desde la versión 1.12.0, y ofrece muchas funciones avanzadas integradas como
el descubrimiento de servicios, balanceo de carga, escalado y seguridad. (Randall, 2017)
Los servicios en línea CaaS (Container as a Service), ofrecen una infraestructura completa para
gestionar el desarrollo de aplicaciones de software utilizando contenedores Docker.
CaaS permite gestionar completamente el ciclo de vida de las aplicaciones de software. Cuando se
utiliza un entorno de desarrollo en la nube según el modelo de PaaS, tiene que limitarse a las
tecnologías que facilita el proveedor, como los lenguajes de programación o los frameworks.
Container as a Service, por el contrario, ofrece a los usuarios una plataforma libre de programación
en la cual las aplicaciones, encapsuladas en contenedores, pueden escalarse a cualquier
infraestructura. (Thakur, 2016)
Container as a Service, tiene como base un clúster de ordenadores accesible en la nube que los
usuarios pueden alquilar parcialmente para subir, crear, gestionar y ejecutar aplicaciones basados
en contenedores. Esto supone minimizar los costos que implica administrar una infraestructura
31
como esta. Los principales proveedores de este servicio son: Google Container Engine (GKE),
Amazon EC2 Container Service (ECS) y Microsoft Azure Container Service (ACS).
10.1 Análisis
Extraer los requisitos de un producto de software es la primera etapa para crearlo. Mientras que
los clientes piensan que ellos saben lo que el software tiene que hacer, se requiere de habilidad y
experiencia en la ingeniería de software para reconocer requisitos incompletos, ambiguos o
contradictorios. El resultado del análisis de requisitos con el cliente se plasma en el documento
32
ERS, Especificación de Requerimientos del Sistema, cuya estructura puede venir definida por
varios estándares. La captura, análisis y especificación de requisitos, es una parte crucial; de esta
etapa depende en gran medida el logro de los objetivos finales. Se han ideado modelos y diversos
procesos de trabajo para estos fines. La IEEE Std. 830-1998 normaliza la creación de las
Especificaciones de Requisitos Software (Software Requirements Specification). (Boronat, 2015)
10.2 Diseño
En esta etapa se modela el sistema y se define su estructura para que soporte todos los requisitos,
incluyendo los requisitos no funcionales y otras restricciones. Se refiere a determinar cómo
funcionará de forma general sin entrar en detalles. Consiste en incorporar consideraciones de la
implementación tecnológica, como los lenguajes de programación, bases de datos, el hardware, la
red, etc. Se definen los casos de uso para cubrir las funciones que realizará el sistema, y se
transforman las entidades definidas en el análisis de requisitos en clases de diseño. (Boronat, 2015)
En esta fase se estudian las posibles alternativas de implementación para el sistema de información
que se construirá y se ha de decidir la estructura general que tendrá el sistema (su arquitectura).
10.3 Codificación
Una vez que se han definido las funciones debe desempeñar el sistema de información (análisis) y
se ha decidido cómo estará organizada sus distintos componentes (diseño), es el momento de pasar
a la etapa de implementación. Antes de empezar a codificar, es fundamental haber comprendido
bien el problema que se pretende resolver y haber aplicado principios básicos de diseño que nos
permitan construir un sistema de información de calidad. La complejidad y la duración de esta
etapa está íntimamente ligada al o a los lenguajes de programación utilizados. (Boronat, 2015)
10.4 Pruebas
Las pruebas de software son parte esencial del proceso de desarrollo del software. Esta parte del
proceso tiene la función de detectar los errores de software lo antes posible. Consiste en comprobar
33
que el software realice correctamente las tareas indicadas en la especificación. Una técnica de
prueba es probar por separado cada módulo del software, y luego probarlo de forma integral, para
así llegar al objetivo. Se considera una buena práctica el que las pruebas sean efectuadas por
alguien distinto al desarrollador que la programó, idealmente un área de pruebas. (Boronat, 2015)
10.5 Instalación
Una vez concluidas las etapas de desarrollo de un sistema de información (análisis, diseño,
implementación y pruebas), llega el instante de poner el sistema en funcionamiento, su instalación
o despliegue. El despliegue comienza cuando el código ha sido suficientemente probado, ha sido
aprobado para su liberación y ha sido distribuido en el entorno de producción. (Boronat, 2015)
Para la instalación, se debe planificar el entorno en el que el sistema debe funcionar, tanto hardware
como software, equipos necesarios y su configuración física, redes de interconexión entre los
equipos y de acceso a sistemas externos, sistemas operativos, bibliotecas y componentes
suministrados por terceras partes, etc. (Boronat, 2015)
34
Dentro del proceso de desarrollo de software, Docker permite implementar todo el entorno de
desarrollo en contenedores, haciendo que el despliegue de la aplicación sea rápida y automática.
11.1 Despliegue
Docker nos ofrece la posibilidad de poder desplegar cualquier tipo de aplicación de software a
través de sus contenedores, además nos permite que nuestras aplicaciones sean portables y puedan
desplegarse en cualquier entorno donde se tenga instalado Docker.
Dentro del proceso de desarrollo de software, Docker es una herramienta diseñada para beneficiar
tanto a desarrolladores, testers, como administradores de sistemas, en relación a las máquinas, a
los entornos donde se ejecutan las aplicaciones de software, los procesos de despliegue.
(Chelladhurai, Singh, & Raj, 2017)
En el caso de los desarrolladores, el uso de Docker hace que puedan centrarse en desarrollar su
código sin preocuparse de si dicho código funcionará en la máquina en la que se ejecutará. Por
ejemplo, sin utilizar Docker un posible escenario podría ser el siguiente:
Este escenario desaparece con Docker. Para ejecutar la aplicación, Pepe se crea un contenedor de
Docker con la aplicación, la versión 8 de Java y el resto de recursos necesarios, y se lo pasa a José.
José, teniendo Docker instalado en su ordenador, puede ejecutar la aplicación a través del
contenedor, sin tener que instalar nada más. (Chelladhurai, Singh, & Raj, 2017)
35
En el área de testing, Docker es muy bueno para tener entornos de pruebas de manera rápida. Por
un lado, es muy sencillo crear y borrar un contenedor, además de que son muy livianos, por lo que
podemos ejecutar varios contenedores en una misma máquina (donde dicho contenedor tendría el
entorno de nuestra aplicación: base de datos, servidor, librerías). Por otro, un mismo contenedor
funcionará en cualquier máquina donde se tenga instalado Docker: El ordenador de pruebas, un
portátil, máquinas alojadas en la nube, un servidor propio. (Chelladhurai, Singh, & Raj, 2017)
Docker también beneficia a la parte de administración de sistemas, ya que como los contenedores
son más livianos que las máquinas virtuales, se reduce el número de máquinas físicas necesarias
para tener un entorno. (Chelladhurai, Singh, & Raj, 2017)
Sin embargo, desarrollar un proyecto de software con esta arquitectura, implica manejar muchos
microservicios, realizar el despliegue de la aplicación de manera nativa para los diferentes
ambientes de test, pre producción, o incluso producción, tomaría bastante tiempo y la aplicación
no estaría disponible de manera inmediata. Utilizando Docker, y algunas herramientas de
automatización de tareas como Jenkins, se podría solucionar este problema.
Las facilidades y ventajas que nos ofrece el uso de Docker en el desarrollo del proyecto de software
son:
Crear una imagen Docker para cada microservicio, esto nos permitirá el fácil despliegue y
la portabilidad del microservicio.
Automatizar la creación de las imágenes Docker, utilizando herramientas como Jenkins, se
puede capturar un evento (por ejemplo, fusión a la rama master si se trabaja con repositorio
Git) que lance la ejecución de una tarea para crear la imagen Docker.
Despliegue de todos los microservicios de manera automática, utilizando la herramienta
Docker Compose, es posible configurar las imágenes Docker para que los contenedores se
desplieguen de manera simultánea.
Disponibilidad inmediata de la aplicación en cualquier ambiente (desarrollo, test) ante
cualquier cambio.
Se asegura el despliegue del mismo código tanto para ambientes de Dev (Development),
QA (Quality Assurance), UAT (User Acceptance Testing) como para producción, por lo
que no se esperan incidencias inesperadas en la puesta en marcha.
Puesta en producción de manera sencilla.
Fácil manejo de la escalabilidad horizontal ante el aumento de la demanda de consumo de
los microservicios.
Reducción de costos de mantenimiento, los contenedores Docker son ligeros y no utilizan
muchos recursos.
37
12. Conclusiones
Si bien, en principio Docker solo se podía implementar de manera nativa en sistemas operativos
con Kernel Linux, en la actualidad, gracias al auge de los contenedores, las grandes empresas como
Microsoft han contribuido para que ahora, también sea posible implementar y configurar Docker
de manera nativa y sencilla en Windows y MacOS.
Al permitir utilizar una imagen base, o el mismo contenedor para la creación de una nueva imagen,
Docker facilita en gran medida la creación de estas, ya que la mayoría de las herramientas o
recursos que se utilizan para el despliegue de una aplicación, tienen su respectiva imagen Docker.
Docker Compose es una herramienta que permite simplificar el uso de Docker, generando scripts
que facilitan el diseño y la construcción de servicios en aplicaciones multi-contenedor. En vez de
utilizar una serie de comandos bash para el despliegue de cada uno de los contenedores, Docker
compose permite configurar un script de manera que todo el proceso de despliegue sea
automatizado.
Los servicios en línea CaaS (Container as a Service), ofrecen una infraestructura completa para
gestionar el desarrollo de aplicaciones de software utilizando contenedores Docker. Para los
clientes, esto implica minimizar los costos de administrar una infraestructura propia.
Dentro del proceso de desarrollo de software, implementar contenedores Docker del entorno de
desarrollo de una aplicación, permite hacer portable todo el ambiente de desarrollo, de manera que
el despliegue de la aplicación para cada uno de los involucrados en las diferentes etapas
(programadores, testers, administradores de sistemas), se lo puede hacer de forma rápida, sin la
necesidad de estar instalando de manera separada todos los recursos necesarios para que la
aplicación sea desplegada.
39
13. Bibliografía