Como funciona docker

Interiores de los contenedores

Como hemos explicado en post anteriores Docker es un sistema de
“virtualización” que usa algunas tecnologías, entre ellas el LXC del
kernel de Linux.

La principal ventaja de este sistema frente a los habituales métodos de
virtualización es la rapidez con la que se arranca y se para una máquina. Esto
es debido a que desaparece el sistema operativo del invitado con lo que pasamos
de 2 o 3 minutos que puede tardar un arranque con VMWARE a un par de
segundos.

Por otro lado el uso de esta tecnología nos debe hacer cambiar un poco el
concepto de como organizar nuestras aplicaciones. Tenemos que descomponer todos
los elementos y tratarlos como cajas negras que nos devuelven algo que
necesitamos cuando se lo hemos pedido.

“Cajas negras”

Otro de los concepto que hay que manejar cuando se trabaja con Docker es el
hecho de nuestras aplicación tiene que funcionar tras eliminar un contenedor y
volverlo a crear. Eso significa que tenemos que saber que datos tienen que ser
persistentes y de que máquina así como todos los procesos que se harán cuando
el contenedor arranque.

Antes de llegar a estas ideas vamos a comenzar por los pasos básicos tras la
instalación.

Comandos básicos

Cuando instalamos Docker no disponemos de ninguna imagen y bien podremos
descargar desde un repositorio (en Docker se llaman hub o registry) o crear
nuestras propias máquinas. Estas imágenes equivalen a nuestras ISO de sistemas
operativo que usamos en VirtualBox.

Gestión de imágenes

Para gestionar las imágenes:

>_ docker images
REPOSITORY  TAG     IMAGE ID      CREATED      VIRTUAL SIZE
python-bce  latest  e6c6b9f243b3  9 days ago   692.5 MB
node-gulp   latest  af8ac3d2b121  10 days ago  661.7 MB
puppet      v1      6fac737d4ff8  13 days ago  337.2 MB

Vamos a comprobar como Docker se asemeja a GIT en muchas de sus
utilidades y comandos. El primero de ellos es a la hora de descargar una
imagen:

>_ docker pull httpd

Esto nos permite descargar el servidor de páginas estáticas Apache. Como en
GIT podemos disponer de distintas versiones y en Docker también podemos
descargarnos una versión de una imagen siempre que esté disponible. En el caso
de Apache podemos bajar la versión 2.2.

>_ docker pull httpd:2.2

Ejecutar contenedores

Toda esta información acerca de la disponibilidad de versiones de una imagen se
explica en la página del hub de Docker docker hub

La sintaxis es muy sencilla

>_ #docker run [modificadores] <imagen>[:tag] [comando]
>_ docker run -ti busybox echo "hola mundo"

Esto arrancará una imagen llamada Busybox (es un imagen muy simple y
ligera que se suele usar de manera didactica o para tener imagenes que solo
necesiten comandos básicos
) que ejecuta un echo por pantalla.

A este comando, Docker le da en PID número 1, eso significa que es el
proceso principal y que cuando termine el resto terminará y apagará esa
máquina. Esto es similar a lo que pasa en todos los xNIX. Podemos verificar
en nuestra propia máquina:

>_ ps -ea | awk '$1 == "1" {print $0}'
1 ?        00:00:01 init

En este caso nos indica init es el proceso padre y si matáramos ese se
apagaría la máquina.

Normalmente los contenedores que queremos que se mantengan activos serán
servicios en background como Apache o MongoDB.

Una vez explicado esto vamos a arrancar nuestra primera máquina para servir
páginas estática:

>_ docker run -d --name apache -p 8888:80 httpd:2.2 

Hemos añadido 3 modificadores:

  • Para ejecutar una máquina en segundo plano -d
  • Si queremos asignar un nombre a una máquina --name
  • Mapear un puerto de nuestra máquina con el contenedor -p in:out

Ampliar una imagen

Con el contenedor de Apache (httpd) podemos servir páginas estáticas. Pero
la configuración carga todos los módulos de apache y esto no es útil para
nuestro propósito que es servir páginas estáticas por lo que vamos a quitar la
carga de los módulos.

Una vez que tenemos la máquina arrancada tenemos podemos ejecutar una tarea en
esta máquina usando en comando exec en este caso vamos a ejecutar una
terminal

>_ docker exec -ti apache /bin/bash
>_ sed -i ‘/^LoadModule/s,^,#,g’ /usr/local/apache2/conf/httpd.conf
>_ exit

Una vez comentadas estas lineas vamos a guardar la configuración para que
cuando volvamos a crear la máquina ya dispongamos de esta configuración:

>_ docker commit apache mi-apache

Ahora ya tenemos disponible esta nueva imagen para su uso.

>_ docker stop apache
>_ docker rm apache

Estas dos ordenes apagan la máquina y la borran respectivamente.

Distribuir las imágenes

Igual que podemos descargar imágenes vamos a poder subirlas a un espacio
virtual con el fin de disponer ubicuidad en nuestro sistema y que esté
disponible en cualquier momento y desde cualquier sitio.

Lo primero que haremos es crear una cuenta en el servicio donde queramos
guardar la imagen. Podemos usar el hub de DonDocker o el de Docker

Con la cuenta ya creada nos tenemos que loguear en el sistema:

>_ #docker login <servicio>
>_ docker login hub.dondocker.com  #DonDocker 
>_ docker login [ hub.docker.com ]  #Docker (no es necesario especificar)

Ahora tenemos que etiquetar nuestra imagen con el nombre del servicio y nuestro
usuario de esta manera:

>_ #docker tag <imagen_local> <servicio>/<usuario>/<repositorio>
>_ docker tag mi-apache hub.dondocker/canonale/mi-apache 
>_ docker tag mi-apache [hub.docker.com/]canonale/mi-apache

 “imagen de proceso subida docker”

Una vez etiquetado esta imagen solo falta subirla y, si se hace como con GIT:
push.

>_ #docker push <servicio>/<usuario>/<repositorio>
>_ docker push hub.dondocker/canonale/mi-apache 
>_ docker push [hub.docker.com/]canonale/mi-apache

Ahora solo es necesario hacer un pull para disponer de esa imagen.

Trabajo con datos

Hemos arrancado nuestro servidor apache, pero ¿dónde está mi código? pues
donde lo hayas dejado pero el contenedor no lo tiene. Para hacer que el
contenedor tenga acceso a ficheros que no están dentro de el tenemos que
especificarlo de esta manera:

>_ #docker run -d -v <ruta_caperta>:/<ruta_contenedor> <imagen>
>_ docker run -d --name apache -v /home/canonale/app:/usr/local/apache2/htdocs/  mi-imagen

De esta forma podemos servir nuestro código en un contenedor. Pero esta no es
la mejor forma cuando estamos usando los contenedores para entornos de
producción ya que es aconsejable no tener código fuera de los contenedores.

Para ello, lo importante es definir volumenes dentro de un contenedo, lo
cual le dará persistencia aunque se elimine el mismo. Para definir un volumen
solo tenemos que usar el modificador -v pero solo con la ruta del contenedor
y copiar el código en esa ruta.

El código tendrá que estar en un lugar ubicuo, desde el que podamos acceder en
cualquier momento y desde cualquier sitio: git, ftp, web…

Normalmente este código en producción se pone en un contenedor cuyo propósito
es únicamente ese: albergar el código, nada más. De tal manera que el
contenedor arranca, baja el código a ese volumen y se apaga. Luego tendremos
que vincularlo a nuestro apache:

>_ docker run -ti --name code -v /usr/local/apache2/htdocs/ 
alpine apk --update add git && git clone repo /usr/local/apache2/htdocs/ 
>_ docker run -d --volumenes-from code -p 88:80 mi-apache

El apache montará la carpeta definida en code de tal manera que si cambiamos
la configuración o se destruye la máquina el código está aislado

Gestión de Redes

Cuando instalamos Docker nos crea una interfaz nueva para aislar la red de
nuestro equipo de la red de Docker. Esto es útil para que no haya problemas
con agentes externos y muy común en los sistemas de virtualización

Esta interfaz crea una red con ip 172.17.0.1/24 de tal manera que cualquier
contenedor que creemos va a tener una ip de ese rango.

Por ejemplo creamos un contenedor que sirva webs y obtiene una ip 172.17.0.2,
si ponemos en el navegador http://172.17.0.2/ veremos la web.

 “Redes e interfaces”

Pero ¿y si alguien de nuestra red 192.168.0.1/24 quiere ver la web?, pues no
podría porque la red 172 es solo para el equipo local. La solución o una de las
soluciones es hacer PAT o lo que es lo mismo mapear un puerto de nuestro equipo
con otro del contenedor:

>_ docker run -d -p 8080:80 apache 

Esto mapea el puerto 8080 al 80 del contenedor de tal manera que con saber cual
es nuestra ip local alguien de la red interna podría ver la web.

Esto puede parecer muy trivial pero si alguien (como es mi caso) no sabe mucho
de redes le puede parecer magia.

Espero que te sirva para ir comenzando con Docker.

Leave a comment

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *