Docker
Docker
Docker
applications
1 Docker
1.1 Introducción
Docker es una aplicación cliente servidor que nos permite crear aplicaciones de una forma
empaquetada, optimizada y estándar para provisionar y ejecutarla en un entorno aislado. En
cierto modo Docker permite la virtualización de aplicaciones pero de una forma mucho más
óptima que si utilizaremos una máquina virtual completa.
Docker nació como un proyecto interno de una empresa de cloud computing; se trataba de una
herramienta programada en lenguaje Go y que utilizaban para precisamente para provisionar
sus infraestructuras. Su rápido crecimiento, la absorción de muchas otras herramientas y sobre
todo su naturaleza de estándar ha sido determinante para convertirse en un éxito.
Imágenes
Las imágenes son una plantilla de solo lectura que define cómo debe ser la aplicación. Cuál es
su base, que configuración tiene, qué ficheros iniciales tiene, etc. Para generar una imagen se
utiliza el comando build y este se basa en las especificaciones de un fichero llamado Dockerfile.
Containers
Un container es una instancia ejecutable de una imagen. En principio son aplicaciones aisladas
pero pueden usarse dentro de conjuntos de composer o comunicarse con otros containers
independientes. Los datos que se guarden pueden hacerse persistentes o no, según la
configuración. Para generar el container utilizamos el comando docker run, y a partir de ahí
podemos para, reiniciar, eliminar el container como queramos.
1
Cuatrovientos CI Pello Altadill
Cuando se ejecuta de forma virtual lo que se utiliza es una máquina virtual Linux que hace la
función de host Docker.
Además de eso, alrededor de los servicios básicos y esos comandos también tenemos:
Docker Machine
Docker composer
Docker Swarm
Docker Registry
2 Instalación
2.1 Linux
En los sistemas Linux de 64 bits no deberíamos tener problemas para instalar docker. Si bien la
instalación no es tan simple como hacer un install con el gestor de paquetes correspondiente,
según la distribución necesitaremos:
https://docs.docker.com/engine/installation/linux/ubuntu/
En cualquier caso, si nuestra distribución no dispone de imagen, podemos instalar Docker como
un binario. Las instrucciones se encuentran en:
https://docs.docker.com/engine/installation/binaries/
https://download.docker.com/win/stable/InstallDocker.msi
2
Cuatrovientos CI Pello Altadill
https://docs.docker.com/toolbox/toolbox_install_windows/
Como para Mac. En el en caso de Mac sí podemos tener el modo nativo o la opción del Docker
Toolbox
https://docs.docker.com/docker-for-mac/
3 Hello Docker
3.1 Introducción
En el DockerHub hay una imagen de una aplicación muy sencilla: hello-world. Esta nos permite
ejecutar esa imagen y convertirla en un container que es ejecutado por Docker.
4 Herramientas Docker
4.1 Docker Machine
Docker machine es la herramienta que nos permite crear hosts Docker, tanto de forma local
como en proveedores de computación en la nube.
3
Cuatrovientos CI Pello Altadill
Localmente podemos usar VirtualBox o VMWare para crear nuevos hosts Docker, pero en la
nube tenemos AWS, Azure, Google, DigitalOcean, Exoscale, OpenStack, RackSpace, SoftLayer,
VMware vSphere, vCloud Air y un largo etc.
Vamos a echar un vistazo a la que tenemos más a mano en sistemas normales, donde Docker
no puede instalarse de forma normal. Lo que tenemos en estos sistemas es una docker-machine
virtual llamada default.
Cuando inicies la consola mediante el Docker Quickstart Terminal debes prestar atención a la ip
que se asigna para luego saber a qué dirección debes acceder:
¡OJO!
En el caso de estar utilizando un host Windows con el Docker Quickstart Terminal, conviene
tener los proyectos alojados dentro de c:\Users\MI_USUARIO, ya que de lo contrario al hacer
un build puede haber directorios y volúmenes que no se añadan correctamente al container.
1. Creando una máquina virtual dentro de nuestro propio equipo como por ejemplo un
sistema Linux (Debian, Ubuntu) o un Windowd 2016 Server
2. Creando una máquina de Virtual Box a través del propio comando docker-machine
4
Cuatrovientos CI Pello Altadill
Luego la iniciamos:
Y cambiamos a su Shell:
docker-machine ip nombre_host
4.2 Docker
4.2.1 Introducción
El comando docker es quien nos permite construir imágenes, descargarlas y lo más importante,
ejecutar, detener y en definitiva gestionar los containers.
docker images
Este comando nos muestra aquellas imágenes que tenemos instaladas en el sistema.
docker images
docker search
5
Cuatrovientos CI Pello Altadill
docker pull
Vamos a descargar por ejemplo una imagen de nginx, un proxy inverso que nos permite acelerar
contenido web estático.
Cada imagen está identificada con un tag. Podemos indicar el nombre sin más, por lo que docker
aplicará el tag “latest”. Si queremos alguna otra versión de la imagen tendremos que indicar el
tag.
En el caso de estar detrás de un proxy, debemos definir una variable de entorno específica. En
el caso de Windows, debemos aplicar la siguiente configuración en la consola, donde 172.30.0.1
es el servidor proxy y 80 su puerto
set proxy=http://172.30.0.1:80
set HTTP_PROXY=%proxy%
set HTTPS_PROXY=%proxy%
docker run
Este es el comando que ejecuta las aplicaciones. Lo que hace es coger la imagen y convertirla en
un container. Si la imagen no está ya descargada docker la descarga en el momento.
Podemos indicar otras opciones como -p para mapear los puertos TCP en caso de aplicaciones
de redes
6
Cuatrovientos CI Pello Altadill
docker ps
Puede que no salga nada. Mediante la opción -a podemos ver los últimos containers que estaban
en ejecución anteriormente
docker logs
Si queremos saber algo sobre la puesta en marcha del container, en especial en caso de fallo,
podemos usar docker logs para saber qué ha pasado dentro del sistema.
docker inspect
Esta opción nos muestra detalles sobre los containers en ejecución. Basta con indicar el
identificar del mismo y obtendremos mucha información útil
docker exec
Esta opción nos permite ejecutar comandos sobre un container en ejecución. Algo
especialmente útil si queremos iniciar un Shell y entrar en ese container para administrarlo.
Esto es lo que podríamos ver, por ejemplo, en un container nginx: los procesos mínimos y un
sistema de ficheros Linux:
docker cp
cp nos permite copiar ficheros desde nuestro sistema al container y viceversa. Como todo
comando cp, indicaremos un origen y un destino. Por ejemplo, aquí copiamos el fichero
default.conf del container a nuestra carpeta actual:
7
Cuatrovientos CI Pello Altadill
docker cp container:/etc/apache2/default.conf .
docker stop
docker rm
docker rm nombre_app
docker rmi
Elimina imágenes que tenemos instaladas. Basta con indicar el nombre de la imagen o bin su id.
docker volume
Nos permite crear volúmenes, una especie de discos virtuales que podemos montar en los
containers, que podemos gestionar al margen de estos y reutilizarlos en distintos containers.
Usando esta opción podremos ver todos los volúmenes ya existentes en nuestro sistema:
docker volumen ls
Lo primero que se hace es crear un volumen, que no deja de ser un directorio de nuestro host:
8
Cuatrovientos CI Pello Altadill
Para crear este tipo de aplicaciones se utiliza un fichero llamado docker-compose.yml donde se
define cada uno de los componentes y en el momento de generarlo, docker-compose genera
una imagen de cada uno y ejecuta los containers según las especificaciones indicadas.
Más adelante se muestran algunos escenarios de compose y el formato del fichero docker-
compose.
Una vez configurado, dentro del propio directorio donde se encuentre eses fichero docker-
compose.yml podemos ejecutar:
docker-compose build
Lo cual generará las imágenes implicadas Si además queremos ejecutarlas en modo detach o
como daemon, hacemos:
docker-compose up -d
docker-compose start/stop/restart
docker-compose rm -f
Vamos a crear un cluster creando este host de containers al que llamaremos local:
A continuación nos vamos a poner nuestra terminal en ese nuevo host Docker.
Ahora vamos crear algo llamado “Discovery Token”, un dato que cada componente de nuestro
cluster utilizará para formar el Swarm.
9
Cuatrovientos CI Pello Altadill
La última línea que genera ese comando es el token que necesitamos. Podemos verificar la
información relativa al token en:
https://discovery.hub.docker.com/v1/clusters/TOKEN
Ahora podemos crear nodos para nuestro cluster, empezando por el nodo maestro o Swarm
Master:
10
Cuatrovientos CI Pello Altadill
Ahora ya podemos borrar la docker-machine llamada local creada antes y pasarnos al master.
docker info
Y a partir de ahí, puedes ejecutar aplicaciones y verás cómo utilizan distintos nodos:
docker ps
FROM
MAINTAINER
Nos permite indicar el nombre de autor y el email de quien mantiene este fichero
ARG
Se trata de argumentos como los que se pasan en el comando docker build, que en este caso lo
podemos poner en el Dockerfile
RUN
ENV
CMD
Nos permite introducir un comando en el inicio del container. Estos comandos pueden ser
sobreescritos a través del comando run de docker
ENTRYPOINT
11
Cuatrovientos CI Pello Altadill
Los ficheros Dockerfile pueden tener un CMD o un ENTRYPOINT. Este último se utiliza cuando
tenemos un container que es directamente ejecutable.
ADD
A través de esta instrucción podemos indicar que se copies los nuevos ficheros/directrios dentro
de un directorio específico del sistema del container docker.
EXPOSE
A través de esta instrucción podemos This instruction exposes specified port to the host
machine.
Dockerfile
FROM bash:4.4
COPY hello.sh /
CMD ["bash", "hello.sh"]
Build y Ejecución
Para ejecutar un programa Java utilizaremos una imagen basada en openjdk, la más directa y
estándar para aplicaciones Java de consola.
Presta atención a cómo se deben pasar los parámetros en la configuración CMD: es un array con
cada una de las opciones.
Dockerfile
12
Cuatrovientos CI Pello Altadill
FROM openjdk:alpine
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac -d bin src/io/pello/docker/Main.java
CMD ["java","-cp","bin","io.pello.docker.Main"]
Build y Ejecución
Dockerfile
El fichero es muy sencillo, basta con indicar el directorio público y copiarlo a un punto concreto:
FROM httpd:2.4
COPY ./public-html/ /usr/local/apache2/htdocs/
Ejecución
En este caso el container quedará en ejecución como demonio y le mapearemos el puerto del
8888 al 80.
¡OJO! Estamos mapeando el puerto de nuestro host del 8888 al puerto 80 del container. Para
probarlo tendremos que poner en el navegador la ip de nuestra docker-machine (default)
además del puerto 8888:
13
Cuatrovientos CI Pello Altadill
A diferencia de muchos otros lenguajes como php que se apoyan en servidores web existentes
como Apache o LightHTTPD, una aplicación web desarrollada en Node.js tiene la particularidad
de que el propio servidor web es también parte de la aplicación. Gracias a las facilidades que da
el entorno más varios frameworks específicos como Express esta tarea se facilita enormemente.
Dependencias
Una particularidad de los proyectos Node.js es que siempre se componen de muchos paquetes
externos, y cada aplicación depende de muchas librerías. Las dependencias se especifican en un
fichero especial llamado package.json, donde además de la configuración del proyecto hay un
listado con las librerías que necesita cada proyecto.
npm install
En nuestra container Docker para aplicaciones, por tanto, tendremos que preocuparnos de
ejecutar esa orden antes de poner en marcha el servicio.
Dockerfile
Este es el aspecto del fichero de configuración de la imagen. Cada línea está comentada para
conocer su propósito:
14
Cuatrovientos CI Pello Altadill
EXPOSE 3000
CMD [ "npm", "start" ]
Build y Ejecución
La ejecución se hace a través de npm start que en realidad, si observamos el fichero package.json
lo que hace es ejecutar node bin/www.js
Al final, ejecutamos el container mapeando el puerto 3000 y en el navegador veríamos algo así:
15
Cuatrovientos CI Pello Altadill
5.6 Nginx
Nginx es un proxy web inverso, es decir, en lugar de ser utilizado por los usuarios para navegar
más rápido cacheando contenidos ya descargados lo que hace es utilizarse para servir contenido
de una web de forma más rápida y eficiente. Se utiliza principalmente para servir contenidos
estáticos de las webs como el HTML, JavaScript, CSS, imágenes, etc.
En realidad Nginx es un acelerador para protocolos TCP, pero su uso más extendido es el de
proxy para aplicaciones web.
Podemos utilizar nginx de forma directa creando un container y ejecutándolo sobre un directorio
ya existente:
Dockerfile
Vamos a publicar una web utilizando Nginx. En este caso en el fichero indicaremos tanto el
contenido de la web como de un fichero de configuración propio:
FROM nginx
COPY ./public-html/ /usr/share/nginx/html
COPY default.conf /etc/nginx/conf.d/default.conf
default.conf
server {
listen 80;
server_name localhost;
(Se omite el resto)
Build y ejecución
Esto es lo que veremos en la página principal. En este caso sirviendo un diseño basado en el
framework Foundation, una alternativa a Bootstrap:
16
Cuatrovientos CI Pello Altadill
5.7 MySQL
Crear un programa en formato de container Docker no tiene por qué ser siempre para tener una
aplicación de usar y tirar. Un container Docker sirve perfectamente para guardar datos de forma
persistente y por tanto los SGBD son ideales para ser integrados como containers.
De hecho, crear aplicaciones utilizando varios containers a la vez pero haciendo que estos sean
independientes e intercambiables. De esa manera, por ejemplo, se puede probar una aplicación
web sobre un container de BD de desarrollo y luego asociarle un container de producción. La
gestión de proyectos de varios containers se hace mediante Docker composer, como se muestra
más adelante
Ejecución directa
OJO, si queremos acceder a este MySQL, tendremos que hacerlo de la siguiente manera,
creando otro container docker como cliente y pasando los datos de acceso:
También podemos iniciar una sesión de bash para entrar en el propio container y desde ahí
entrar en mysql de forma local:
17
Cuatrovientos CI Pello Altadill
Variables de entorno
Algunas variables de entorno interesantes que podemos utilizar son las siguientes:
Los datos de MySQL pueden almacenarse dentro del propio container, pero también podemos
hacer que MySQL utilice un directorio de datos externo. Mediante esta ejecución, en la que le
pasamos los volúmenes de directorio de datos y configuración conseguiremos ese resultado:
Podemos hacer que la instancia de MySQL contenga una BD concreta cargada con datos si al
hacer el build metemos el volcado de la BD a una carpeta /docker-entrypoint-initdb.d. Dentro
de esa carpeta, todos aquellos ficheros .sh, .sql o .sql comprimidos se ejecutarán y llenarán la
BD.
Por lo tanto, en nuestro directorio donde haremos el build de esta imagen, tendremos un fichero
con el volcado. En el Dockerfile indicaremos cuál y cómo copiarlo a /docker-entrypoint-initdb.d
Dockerfile
18
Cuatrovientos CI Pello Altadill
Mediante un Dockerfile podremos crear un container personalizado, con datos iniciales y sin
necesidad de pasar tantos parámetros.
FROM mysql
MAINTAINER Pello Altadill
# We copy our db config and dump
COPY mysql/ /etc/
ADD dump/series.sql.gz /docker-entrypoint-initdb.d
ENV MYSQL_DATABASE=series \
MYSQL_USER=seriesuser \
MYSQL_PASSWORD=secret \
MYSQL_ROOT_PASSWORD=secret
EXPOSE 3306:3306
CMD ["mysqld"]
Build y ejecución
¡OJO!
Ese container puede iniciarse/pararse siempre que haga falta, pero obviamente, si se elimina se
perderán los datos. Si esto no es lo que interesa puede pensarse en otra estrategia para
gestionar los datos, o bien en un volumen externo, o bien en otro container.
19
Cuatrovientos CI Pello Altadill
5.8 MongoDB
MongoDB es un SGBD NoSQL, es decir, es una base de datos orientada a documentos que no
tiene nada que ver con el clásico modelo relacional. Las aplicaciones más frecuentes de
MongoDB suelen estar vinculadas al Big Data o a proyectos que precisan ser rápidamente
escalables. Son aplicaciones en cuyos datos se renuncian a la integridad pero que a la vez son
muy flexibles y permiten un alto rendimiento en consultas.
Al margen de las diferencias con las BBDD SQL tradicionales, sigue siendo un almacén de datos
persistente y por tanto hay que tener algunas consideraciones similares.
Ejecución directa
[nombre]
--auth nos obligará a usar autenticación
--smallfiles en el inicio reservará unos ficheros de datos menores
--syslog mandará los logs al demonio syslog
Autenticación
Si queremos crear un container con autenticación, debemos añadir un usuario con su contraseña
y permisos en una BD especial llamada admin.
Dockerfile
En este Dockerfile vamos a especificar que el directorio donde Mongo guarda los datos lo
montaremos como un volumen. Eso nos permitirá adjuntarlo como un volumen reutilizable
docker.
20
Cuatrovientos CI Pello Altadill
FROM mongo
MAINTAINER Pello Altadill
EXPOSE 27017:27017
Build y ejecución
Para ejecutar a partir del Dockerfile anterior y poder utilizar un volumen Docker, primero
crearemos un volumen en nuestro sistema:
De esta manera, los datos manejados serán totalmente persistentes aunque destruyamos el
container o la imagen.
docker-compose.yml
Este sería el contenido del fichero donde se ve claramente cada container y su configuración:
mysqlcontainer:
image: mysql
21
Cuatrovientos CI Pello Altadill
container_name: my_mysql_container
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: sampledb
MYSQL_USER: sampleuser
MYSQL_PASSWORD: secret
apachephpcontainer:
image: nimmis/apache-php5
container_name: my_php_apache_container
ports:
- "8888:80"
- "8443:443"
volumes:
- ./public:/var/www/html
links:
- mysqlcontainer
Build y ejecución
Para ejecutarlo, primero nos debemos situar en el mismo directorio donde este el fichero
docker-compose.yml
docker-compose up -d
docker-compose ps
<?php
echo "<h1>PHP with Docker Works!</h1>";
22
Cuatrovientos CI Pello Altadill
$conn = mysqli_connect("mysqlcontainer","sampleuser","secret","sampledb") or
die("Connection failed: ");
echo "And MySQL works";
Como se puede ver, el nombre de host de MySQL, es el mismo que hemos establecidor en el
fichero docker-compose.yml. Docker crea una red entre los dos containers y los entre ellos son
accesibles a través de esos nombres.
Es una forma de repartir la configuración que puede ser interesante en proyectos más grandes.
docker-compose.yml
Este es el nuevo aspecto del docker-compose, donde a través de la directiva build dejamos en
manos los detalles de cada imagen a cada Dockerfile correspondiente
version: '2'
services:
mysqlcontainer:
23
Cuatrovientos CI Pello Altadill
container_name: my_mysql_container
build: ./mysql
phpcontainer:
container_name: my_php_container
build: ./php
ports:
- "8888:80"
depends_on:
- mysqlcontainer
Dockerfiles
Este sería el dockerfile de la imagen de php. Como se puede ver utiliza la base oficial de php
pero luego le añadimos la extensión de mysqli.
FROM php:7.0-apache
COPY php.ini /usr/local/etc/php/
COPY src/ /var/www/html/
RUN apt-get update \
&& apt-get install -y libmcrypt-dev \
&& docker-php-ext-install pdo_mysql mysqli
RUN chown -R www-data:www-data /var/www/html
RUN chmod -R 755 /var/www/html
EXPOSE 8888:80
1. MongoDB
2. Framework web MVC Express
3. Angular
4. Node.js
En este ejemplo vamos a crear este tipo de aplicación utilizando tres imágenes:
Como se ve en la aplicación, la configuración está lista para incluir más instancias de Node.js de
tal manera que Nginx puede usarlos de forma balanceada. Además separamos la configuración
específica en cada fichero Dockerfile
24
Cuatrovientos CI Pello Altadill
docker-compose.yml
6.3.1 Nginx
La configuración para conseguir el balanceo de carga empezaría así
Nginx.conf
Dockerfile
FROM nginx
# Copy custom configuration file
COPY nginx.conf /etc/nginx/nginx.conf
# Expose port
EXPOSE 8888
6.3.2 Node.js
El proyecto ya tiene integrado el framework Express y las librerías de acceso a MongoDB. Dentro
tiene una simple consulta a Mongo y muestra el resultado.
Dockerfile
FROM node:boron
# Create app directory
RUN mkdir -p /srv/www/src/app
WORKDIR /srv/www/src/app
# Install app dependencies
COPY src/package.json /srv/www/src/app/
RUN npm install
# Bundle app source
25
Cuatrovientos CI Pello Altadill
6.3.3 MongoDB
En este caso, tratamos de meter datos iniciales a través de la orden mongorestore
Dockerfile
EXPOSE 27017:27017
7 DockerHub y Git
Es habitual que se tengan proyectos alojados en repositorios como GitHub para gestionar
proyectos de software. Ahora, gracias a Docker, podemos convertir nuestros proyectos en
imágenes Docker para facilitar su implantación. Por lo tanto, nuestras aplicaciones pueden
alojarse en Github en forma de código fuente y en DockerHub en forma de imagen.
Para esto debemos activar la integración dentro de DockerHub y además incluir un fichero
específico dentro del proyecto. Gracias a esto podremos pasar nuestro repositorio GitHub a un
repositorio DockerHub de forma automática.
26
Cuatrovientos CI Pello Altadill
Seleccionamos GitHub y en concreto el acceso limitado, o de solo lectura. El otro tipo de acceso
es más apropiado para repositorios privados:
Esto nos llevará a la página de GitHub, tendremos que validarnos y aceptar el vínculo:
27
Cuatrovientos CI Pello Altadill
Desplegamos Add Service y seleccionamos Docker. Lo que te indica GitHub es que básicamente
necesitarás que el proyecto tenga un fichero Dockerfile y a su vez un repositorio de destino en
DockerHub.
28
Cuatrovientos CI Pello Altadill
Gracias al vínculo veremos la lista de proyectos de GitHub y seleccionaremos el que nos interese
29
Cuatrovientos CI Pello Altadill
Tendremos que indicar un nombre y una URL concreta hacia otro servicio
8 Referencias
8.1 URLs
https://www.docker.com/ Web oficial de docker
https://docs.docker.com/compose/compose-file/ Referencia de compose-file
https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/
Dockerfile, best practices
https://hub.docker.com Docker Hub, repositorio de imágenes
https://github.com/veggiemonk/awesome-docker Proyecto con guía de recursos
Docker.
https://github.com/pxai/dockerfile-samples Varios proyectos de ejemplo Docker
8.2 Libros
Using Docker, OReilly
Docker Up & Running, Oreilly
Docker Cookbook, OReilly
Docker in practice, Manning
The Docker Book, https://www.dockerbook.com/
8.3 Cursos
https://www.katacoda.com/courses/docker
https://katacoda.com/courses/docker-orchestration
https://cloudacademy.com/cloud-computing/introduction-to-docker-course/
https://training.docker.com/category/self-paced-online
30