Primeros pasos con Docker

Docker es proyecto opensource que te permite manejar contenedores, una especie de máquinas virtuales, pero más ligeras y totalmente portables.

El nombre de contenedores viene de los recipientes de carga estandarizados que se utilizan en barcos, camiones y trenes, que permiten cargar, descargar y apilar los containers durante largas distancias facilitando el transbordo de un medio de transporte a otro. Estos contenedores han supuesto una verdadera revolución en el mundo del transporte, reduciendo costes, tiempos de carga/descarga, daños en mercancías, etc.

Docker lleva este mismo concepto al mundo del software, permitiendo encapsular cualquier arquitectura, convirtiéndola en un contenedor portable y autosuficiente, de forma que se pueda manipular mediante operaciones establecidas y ejecutar de manera consistente en cualquier hardware.

docker fauna

Esto tiene bastantes ventajas:

  • Completamente portables, te permiten ejecutar tu aplicación en local sobre cualquier sistema operativo, en cualquier servidor on-premise o incluso en la nube. Esto hace que Docker sea un complemento perfecto para los equipos ágiles y acaba con el “esto en mi ordenador funcionaba”.
  • Te permite tratar la infraestructura como un fichero más dentro de las fuentes de tu proyecto, con lo que puedes automatizar dentro del build la creación de la propia infraestructura, creando una imagen completa con el software base y tu aplicación instalada.
  • Hay miles de imágenes ya disponibles en DockerHub con casi cualquier stack tecnológico, las puedes usar directamente o modificarlas para evitar partir de cero.
  • La gestión de paquetes y dependencias es muy simple y transparente, facilitando la integración de los equipos de desarrollo y sistemas.
  • Tiene mejor rendimiento que la virtualización tradicional, ya que está basado en LXC, que corre directamente sobre el kernel de la máquina donde se aloja, evitando la capa de virtualización tradicional basada en un hipervisor que penaliza el rendimiento.
  • Por las mismas razones que el punto anterior, los contenedores arrancan en segundos, mucho más rápido que una máquina virtual.

Pero no todo es perfecto, hay críticos que se quejan de que el aislamiento entre los contenedores es menor y que está aún algo verde.

Ejemplo de uso de Docker

Con Docker te cuesta lo mismo hacer un “hola mundo” que desplegar una arquitectura compleja. Así que os voy a mostrar un ejemplo de cómo desplegar una arquitectura lemp completa (linux, ngnix, php, mysql), primero en la nube en Google Cloud y después en local en un mac. Si no tenéis instalados algunos componentes el proceso os puede llevar la primera vez un poco más de tiempo, pero si no ambos procesos no ocupan más de dos o tres minutos.

Vamos a utilizar una imagen de Docker ya creada con esta arquitectura que está disponible en DockerHub, se llama stenote/docker-lemp. Como podéis ver, el fichero docker que define el contenedor es bastante simple y se entiende muy bien:

FROM debian:latest
MAINTAINER stenote stenote@163.com

ENV DEBIAN_FRONTEND noninteractive

## Install php nginx mysql supervisor
RUN apt-get update && \
    apt-get install -y php5-fpm php5-cli php5-gd php5-mcrypt php5-mysql php5-curl \
                       nginx \
                       supervisor && \
    echo "mysql-server mysql-server/root_password password" | debconf-set-selections && \
    echo "mysql-server mysql-server/root_password_again password" | debconf-set-selections && \
    apt-get install -y mysql-server && \
    rm -rf /var/lib/apt/lists/*

## Configuration
# php-fpm
RUN sed -i 's/^listen\s*=.*$/listen = 127.0.0.1:9000/' /etc/php5/fpm/pool.d/www.conf && \
    sed -i 's/^\;error_log\s*=\s*syslog\s*$/error_log = \/var\/log\/php5\/cgi.log/' /etc/php5/fpm/php.ini && \
    sed -i 's/^\;error_log\s*=\s*syslog\s*$/error_log = \/var\/log\/php5\/cli.log/' /etc/php5/cli/php.ini && \
    mkdir /var/log/php5/ && \
    touch /var/log/php5/cli.log /var/log/php5/cgi.log && \
    chown www-data:www-data /var/log/php5/cgi.log /var/log/php5/cli.log

# nginx
RUN unlink /etc/nginx/sites-enabled/default
ADD nginx/default /etc/nginx/sites-enabled/default
RUN mkdir /var/www/
ADD nginx/index.php /var/www/
RUN chown -R www-data:www-data /var/www/

# mysql
RUN sed -i 's/^key_buffer\s*=/key_buffer_size =/' /etc/mysql/my.cnf
RUN chown -R mysql:mysql /var/lib/mysql

# supervisor
ADD supervisor/php5-fpm.conf /etc/supervisor/conf.d/php5-fpm.conf
ADD supervisor/nginx.conf /etc/supervisor/conf.d/nginx.conf
ADD supervisor/mysql.conf /etc/supervisor/conf.d/mysql.conf

WORKDIR /var/www/

VOLUME /var/www/
EXPOSE 80

CMD ["/usr/bin/supervisord", "--nodaemon", "-c", "/etc/supervisor/supervisord.conf"]

Desplegar un contenedor Docker en Google Cloud

Google Cloud es la plataforma cloud que está actualmente mejor preparada para trabajar con contenedores. Tiene un componente específico, el Google Container Engine, que utiliza la librería opensource Kubernetes, un orquestador para manejar arquitecturas completas basadas en contenedores, que se está convirtiendo un estándard aceptado ya por otros fabricantes como Microsoft, Red Hat, VMware o IBM.

Lo primero es crearos una cuenta en Google Cloud, al crear un usuario os dan unos créditos para pruebas que duran un mes. Lo siguiente es instalaros el api GCloud, que os permite desplegar y operar Google Cloud de forma sencilla desde vuestra línea de comandos en local. Las instrucciones para esto las tenéis aquí:
https://cloud.google.com/container-engine/docs/before-you-begin#enable_the_api

Una vez que tengáis funcionado la interfaz GCloud lo siguiente es seleccionar la zona de Google que queráis utilizar, por ejemplo:

gcloud config set compute/zone us-central1-a

El siguiente paso es crear un cluster, que son básicamente las máquinas sobre las que vais a desplegar el contenedor:

gcloud preview container clusters create hello-lemp --num-nodes 1 --machine-type g1-small

Una vez que haya terminado podéis probar si se ha creado correctamente:

gcloud compute instances list

El siguiente paso es crear un pod, un concepto que añade Kubernetes a Docker. Un pod es un grupo de contenedores que se administran y gestionan juntos, pensado para desplegar arquitecturas completas con varios contenedores. En este ejemplo el pod tendrá un único contenedor basado en la imagen de DockerHub con lemp que hemos comentado antes. En el mismo comando abrimos también el puerto 80 para que el contenedor sea accesible desde el exterior y poder probarlo:

gcloud preview container pods create --name hello-lemp-pod --image=stenote/docker-lemp --port=80

Para ver el detalle del contenedor desplegado:

gcloud preview container pods describe hello-lemp-pod

Apuntaros la ip que os devuelve para acceder después al contenedor, la que aparece en la columna “host” después de la “/“.

Después habilitamos el tráfico en el puerto 80 de la máquina base en la que hemos desplegado el contenedor:

gcloud compute firewall-rules create hello-lemp-node-80 --allow tcp:80 --target-tags k8s-hello-lemp-node

Y por último probamos que todo funciona accediendo al ngnix desplegado accediendo desde el navegador a la ip que os ha dado el contenedor.

Bueno realmente este no es el final, el final es borrar todo esto de Google Cloud para que no os siga cobrando por ello. Eliminamos el cluster:

gcloud preview container clusters delete hello-lemp

Y eliminamos la regla del firewall:

gcloud compute firewall-rules delete hello-lemp-node-80

Desplegar un contenedor Docker en local (Mac)

Vamos ahora con la misma prueba pero en local en un mac. Veréis que tiene más o menos la misma complejidad que hacerlo en la nube.

Docker hace uso de componentes que solo están disponibles en los kernel de Linux, con lo cual no podemos desplegar los contenedores directamente en un mac, sino que tenemos que hacerlo sobre una máquina virtual ligera como boot2docker. Las instrucciones para instalar esto están en: https://docs.docker.com/installation/mac/

Para inicializar boot2docker podéis directamente arrancarlo desde la interfaz gráfica en el directorio de aplicaciones, pero mejor hacedlo por línea de comandos. Inicializar boot2docker:

boot2docker init

Arrancar la máquina virtual ligera boot2docker:

boot2docker start

Setear la variable DOCKER_HOST para esta consola. Esto es para decirle a Docker en qué ruta está arrancado boot2docker:

$(boot2docker shellinit)

Arrancar la imagen de DockerHub con lemp sobre la máquina virtual, conectando el puerto 80 del contenedor con el puerto 80 de la máquina virtual raíz para podernos conectar desde fuera:

docker run --name hello-lemp -d -p 80:80 stenote/docker-lemp

Abrir en vuestro navegador predeterminado la página por defecto de ngnix para comprobar que todo ha ido bien. boot2docker ip devuelve la ip de la máquina virtual de boot2docker:

open http://$(boot2docker ip 2>/dev/null)/

Al final parar el contenedor:

docker stop hello-lemp

Borrarlo:

docker rm hello-lemp

Y por último parar la máquina virtual donde estaba el contenedor:

boot2docker stop

Sobre un windows el proceso es casi idéntico. Sobre un linux es incluso más sencillo y eficiente, ya que despliegas directamente el contenedor sobre el kernel y te ahorras la máquina virtual.

¿Os animáis a probarlo?

 

Mi rol es diseñar proyectos de Internet y hacer que salgan bien. Es lo que me gusta hacer y a lo que me he dedicado los últimos 10 años. Siempre en busca de nuevos retos, me interesan temas tan diversos como las metodologías ágiles, las tecnologías Cloud o el diseño de producto. Para hacer buenos productos, procuro siempre crear un marco de trabajo que permita a las personas mejorar y dar su mejor versión.

Ver toda la actividad de José Ignacio Herranz Roldán

Recibe más artículos como este

Recibirás un email por cada nuevo artículo.. Acepto los términos legales

Posts relacionados

Comentarios

  1. […] una especial relevancia. Y es que al día de hoy, gracias al cloud y a la contenerización (como Docker) podemos tener un servicio con completa autonomía con un coste y esfuerzo bastante […]

Escribe un comentario