Al igual que en la entrada anterior, sobre copias de seguridad de volúmenes en OpenStack, en esta entrada vamos a mostrar otra funcionalidad que nos ofrece OpenStack cuando trabajamos con volúmenes con su componente Cinder.

Transferencia de volúmenes

Esta operación nos permite transferir un volumen de un proyecto a otro.

Crear una transferencia

Vamos a trabajar con el usuario demo, que tiene creado un volumen.

$ source demo-openrc.sh	

$ cinder list
+--------------------------------------+-------------------+--------+------+-------------+----------+-------------+
|                  ID                  |       Status      |  Name  | Size | Volume Type | Bootable | Attached to |
+--------------------------------------+-------------------+--------+------+-------------+----------+-------------+
| 917ef4cc-784d-4803-a19a-984b847b9f1e | awaiting-transfer | disco1 |  1   | lvmdriver-1 |  false   |             |
+--------------------------------------+-------------------+--------+------+-------------+----------+-------------+

Vamos a crear una transferencia, con las siguientes instrucciones:

$ cinder transfer-create 917ef4cc-784d-4803-a19a-984b847b9f1e
+------------+--------------------------------------+
|  Property  |                Value                 |
+------------+--------------------------------------+
|  auth_key  |           408af7d4a1441587           |
| created_at |      2016-01-08T17:07:03.412265      |
|     id     | d24d5659-40e9-446c-9437-238fc8868571 |
|    name    |                 None                 |
| volume_id  | 917ef4cc-784d-4803-a19a-984b847b9f1e |
+------------+--------------------------------------+

$ cinder transfer-list
+--------------------------------------+--------------------------------------+------+
|                  ID                  |              Volume ID               | Name |
+--------------------------------------+--------------------------------------+------+
| d24d5659-40e9-446c-9437-238fc8868571 | 917ef4cc-784d-4803-a19a-984b847b9f1e | None |
+--------------------------------------+--------------------------------------+------+

Continue reading

En esta entrada voy a explicar una característica muy específica que nos proporciona el componente Cinder de OpenStack, que es el encargado de gestionar el almacenamiento persistente con el concepto de volumen. La característica a la que me refiero es la posibilidad de hacer copias de seguridad del contenido de nuestro volúmenes. El estudio de esta opción la hemos llevado a cabo durante la realización del último curso sobre OpenStack que he impartido con Alberto Molina. Además si buscas información de este tema, hay muy poco en español, así que puede ser de utilidad.

El cliente cinder proporciona las herramientas necesarias para crear una copia de seguridad de un volumen. Las copias de seguridad se guardar como objetos en el contenedor de objetos swift. Por defecto se utiliza swift como almacén de copias de seguridad, aunque se puede configurar otros backend para realizar las copias de seguridad, por ejemplo una carpeta compartida por NFS.

Configurando devstack de forma adecuada

Podemos configurar nuestra instalación de OpenStack con devstack para habilitar la característica de copia de seguridad de volúmenes. En artículo anteriores he hecho una introducción al uso de devstack para realizar una instalación de OpenStack en un entorno de pruebas: Instalar Open Stack Juno con devstack.

Al crear nuestro fichero local.conf, tenemos que tener en cuenta dos cosas:

  • Habilitar el componente de swift (almacenamiento de objetos) donde vamos a realizar las copias de seguridad.
 enable_service s-proxy s-object s-container s-account
 SWIFT_REPLICAS=1
 SWIFT_HASH=password
  • Habilitar la característica de copia de seguridad de los volúmenes.
enable_service c-bak

Continue reading

wordpress-mysql-db-merge-180x180

En los artículos anteriores hemos estudiado como trabajar con imágenes y contenedores docker. En todos los ejemplos que hemos mostrado, los contenedores han trabajado ofreciendo uno o varios servicios, pero no se han comunicado o enlazado con ningún otro. En realidad sería muy deseable trabajar con el paradigma de “microservicio” donde cada contenedor ofrezca un servicio que funcione de forma autónoma y aislada del resto, pero que tenga cierta relación con otro contenedor (que ofrezca también un sólo servicio) para que entre todos ofrezcan una infraestructura más o menos compleja. En esta entrada vamos a mostrar un ejemplo de como podemos aislar servicios en distintos contenedores y enlazarlos para que trabajen de forma conjunta.

Instalación de wordpress en docker

Más concretamente vamos a crear un contenedor con un servidor web con wordpress instalado que lo vamos a enlazar con otro contenedor con un servidor de base de datos mysql. Para realizar el ejemplo vamos a utilizar las imágenes oficiales de wordpress y mysql que encontramos en docker hub.

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
wordpress           latest              55f2580b9cc9        5 days ago          516.5 MB
mysql               latest              e13b20a4f248        5 days ago          361.2 MB
debian              latest              256adf7015ca        5 days ago          125.1 MB
ubuntu              14.04               14b59d36bae0        5 days ago          187.9 MB

Docker nos permite un mecanismo de enlace entre contenedores, posibilitando enviar información de forma segura entre ellos y pudiendo compartir información entre ellos, por ejemplo las variables de entorno. Para establecer la asociación entre contenedores es necesario usar el nombre con el que creamos el contenedor, el nombre sirve como punto de referencia para enlazarlo con otros contenedores.

Por lo tanto, lo primero que vamos a hacer es crear un contenedor desde la imagen mysql con el nombre servidor_mysql, siguiendo las instrucción del repositorio de docker hub:

$ docker run --name servidor_mysql -e MYSQL_ROOT_PASSWORD=asdasd -d mysql

En este caso sólo hemos indicado la variable de entrono MYSQL_ROOT_PASSWORD, que es obligatoria, indicando la contraseña del usuario root. Si seguimos las instrucciones del repositorio de docker hub podemos observar que podríamos haber creado más variables, por ejemplo:  MYSQL_DATABASE, MYSQL_USER, MYSQL_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD.

A continuación vamos a crear un nuevo contenedor, con el nombre servidor_wp, con el servidor web a partir de la imagen wordpress, enlazado con el contenedor anterior.

$ docker run --name servidor_wp -p 80:80 --link servidor_mysql:mysql -d wordpress

Para realizar la asociación entre contenedores hemos utilizado el parámetro --link, donde se indica el nombre del contenedor enlazado y un alias por el que nos podemos referir a él. Continue reading

dockerhub

En artículos anteriores hemos estudiado la generación de imágenes docker utilizando ficheros Dockerfile y construyendo la nueva imagen con el comando docker buid. Las imágenes generadas por este método se crean en nuestro servidor docker. si queremos desplegar la aplicación o el servicio “dockerizado” desde nuestro entorno de prueba/desarrollo a nuestro entorno de producción, es necesario llevarnos la imagen de un entono a otro. Para transferir la imagen de un equipo a otro tenemos dos posibilidades:

  • Podríamos guardar la imagen en un fichero tar, que podemos copiar al otro equipo para restaurarlo en él.
  • Podríamos guardar la imagen en un registro docker. Podemos instalar un registro en nuestra infraestructura o utilizar docker hub, que es una aplicación web que nos proporciona la posibilidad de guardar nuestras imágenes. Una vez que la imagen esta guardada en el registro podemos descargarla desde el entorno de producción.

Para ver las distintas opciones que tenemos a nuestra disposición vamos a partir de la siguiente imagen que hemos creado:

docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
josedom24/apache2   latest              04800781aed6        17 seconds ago      183.7 MB

Continue reading

En la entrada: Dockerfile: Creación de imágenes docker, estudiamos el mecanismo de creación de imágenes docker, con el comando docker buid y los ficheros Dockerfile. En esta entrada vamos a estudiar algunos ejemplos de ficheros Dockerfile y cómo creamos y usamos las imágenes generadas a partir de ellos.

Tenemos dos imágenes en nuestro sistema, que son las que vamos a utilizar como imágenes base para crear nuestras imágenes:

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
debian              latest              9a02f494bef8        2 weeks ago         125.1 MB
ubuntu              14.04               3876b81b5a81        3 weeks ago         187.9 MB

Creación una imagen con el servidor web Apache2

En este caso vamos a crear un directorio nuevo que va a ser el contexto donde podemos guardar los ficheros que se van a enviar al docker engine, en este caso el fichero index.html que vamos a copiar a nuestro servidor web:

$ mkdir apache
$ cd apache
~/apache$ echo "<h1>Prueba de funcionamiento contenedor docker</h1>">index.html

En ese directorio vamos a crear un fichero Dockerfile, con el siguiente contenido:

FROM debian
MAINTAINER José Domingo Muñoz "josedom24@gmail.com"

RUN apt-get update && apt-get install -y apache2 && apt-get clean && rm -rf /var/lib/apt/lists/*

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

EXPOSE 80
ADD ["index.html","/var/www/html/"]

ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

En este caso utilizamos la imagen base de debian, instalamos el servidor web apache2, para reducir el tamaño, borramos la caché de paquetes apt y la lista de paquetes descargada, creamos varias variables de entorno (en este ejemplo no se van a utilizar, pero se podrían utilizar en cualquier fichero del contexto, por ejemplo para configurar el servidor web), exponemos el puerto http TCP/80, copiamos el fichero index.html al DocumentRoot y finalmente indicamos el comando que se va a ejecutar al crear el contenedor, y además, al usar el comando ENTRYPOINT, no permitimos ejecutar ningún otro comando durante la creación.

Vamos a generar la imagen:

~/apache$ docker build -t josedom24/apache2:1.0 .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM debian
 ---> 9a02f494bef8
Step 2 : MAINTAINER José Domingo Muñoz "josedom24@gmail.com"
 ---> Running in 76f3f8fe0719
 ---> fda7bdbf761c
Removing intermediate container 76f3f8fe0719
Step 3 : RUN apt-get update && apt-get install -y apache2 && apt-get clean && rm -rf /var/lib/apt/lists/*
 ---> Running in c50b14cc967d
Get:1 http://security.debian.org jessie/updates InRelease [63.1 kB]
Get:2 http://security.debian.org jessie/updates/main amd64 Packages [256 kB]
Ign http://httpredir.debian.org jessie InRelease
...
 ---> 0dedcfe17eb9
Removing intermediate container c50b14cc967d
Step 4 : ENV APACHE_RUN_USER www-data
 ---> Running in 85a85c09f96c
 ---> dac18d113b15
Removing intermediate container 85a85c09f96c
Step 5 : ENV APACHE_RUN_GROUP www-data
 ---> Running in 9e7511d92c74
 ---> 8f5824bdc71a
Removing intermediate container 9e7511d92c74
Step 6 : ENV APACHE_LOG_DIR /var/log/apache2
 ---> Running in 1b9173a822f8
 ---> 313e04f3a33a
Removing intermediate container 1b9173a822f8
Step 7 : EXPOSE 80
 ---> Running in 001ce73f08a6
 ---> 76f798e8d481
Removing intermediate container 001ce73f08a6
Step 8 : ADD index.html /var/www/html
 ---> 5ce11ae0b1e6
Removing intermediate container c8f418d3a0f6
Step 9 : ENTRYPOINT /usr/sbin/apache2ctl -D FOREGROUND
 ---> Running in 4ba6954632a5
 ---> 9109b0f27a08
Removing intermediate container 4ba6954632a5
Successfully built 9109b0f27a08

Generamos la nueva imagen con el comando docker build con la opción -t indicamos el nombre de la nueva imagen (para indicar el nombre de la imagen es recomendable usar nuestro nombre de usuario en el registro docker hub, para posteriormente poder guardarlas en el registro), mandamos todos los ficheros del contexto (indicado con el punto). Podemos comprobar que tenemos generado la nueva imagen:

$ docker images 
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
josedom24/apache2   1.0                 9109b0f27a08        4 minutes ago       183.7 MB
debian              latest              9a02f494bef8        2 weeks ago         125.1 MB
ubuntu              14.04               3876b81b5a81        3 weeks ago         187.9 MB

A continuación podemos crear un nuevo contenedor a partir de la nueva imagen:

$ docker run -p 80:80 --name servidor_web josedom24/apache2:1.0

Comprobamos que el contenedor está creado:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
67013f91ba65        josedom24/apache    "/usr/sbin/apache2ctl"   4 minutes ago       Up 4 minutes        0.0.0.0:80->80/tcp   servidor_web

Y podemos acceder al servidor docker, para ver la página web:
dockerfile1
Continue reading

dockerfileEn la entrada anterior, estudiamos un método para crear nuevas imágenes a partir de contenedores que anteriormente habíamos configurado. En esta entrada vamos a presentar la forma más usual de crear nuevas imágenes: usando el comando docker buid y definiendo las características que queremos que tenga la imagen en un fichero Dockerfile.

¿Cómo funciona docker build?

Un Dockerfile es un fichero de texto donde indicamos los comandos que queremos ejecutar sobre una imagen base para crear una nueva imagen. El comando docker build construye la nueva imagen leyendo las instrucciones del fichero Dockerfile y la información de un entorno, que para nosotros va a ser un directorio (aunque también podemos guardar información, por ejemplo, en un repositorio git).

La creación de la imagen es ejecutada por el docker engine, que recibe toda la información del entorno, por lo tanto es recomendable guardar el Dockerfile en un directorio vacío y añadir 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 y va mostrando los resultados en pantalla.

Tenemos que tener en cuenta que cada instrucción ejecutada crea una imagen intermedia, una vez finalizada la construcción de la imagen nos devuelve su id. Alguna imágenes intermedias se guardan en caché, otras se borran. Por lo tanto, si por ejemplo, en un comando ejecutamos cd /scripts/ y en otra linea le mandamos a ejecutar un script (./install.sh) no va a funcionar, ya que ha lanzado otra imagen intermedia. Teniendo esto en cuenta, la manera correcta de hacerlo sería:

cd /scripts/;./install.sh

Para terminar indicar que la creación de imágenes intermedias generadas por la ejecución de cada instrucción del Dockerfile, es un mecanismo de caché, es decir, si en algún momento falla la creación de la imagen, al corregir el Dockerfile y volver a construir la imagen, los pasos que habían funcionado anteriormente no se repiten ya que tenemos a nuestra disposición las imágenes intermedias, y el proceso continúa por la instrucción que causó el fallo. Continue reading