Probando Docker en Windows 10

Hoy quería ponerme con un pequeño proyecto para mejorar una de mis webs. He decidido montarlo como un microservicio separado, ya que se trata de una funcionalidad fácilmente separable y me ha aparecido un pequeño problema logístico. Tengo Windows 10 instalado en casa. Generalmente virtualizo máquinas con vmware player para estas cosas, pero como en Waynabox llevamos un tiempo usando Docker  y le he cogido el gustillo, he pensado que podría probar la nueva implementación de Docker para Windows 10.

Y aquí tenéis mis primeras experiencias en lo que sería una guía para novatos, escrita por un novato.

Lo primero, la documentación oficial

Por algún lado hay que empezar, y lo mejor es leerse la página oficial de Docker al respecto, Getting Started with Docker for Windows.

Aquí encontramos algunas advertencias sobre la versión de Windows necesaria y la necesidad de activar Microsoft Hyper-V. De momento voy a ignorar estos avisos, (mi windows está a la última), espero que no explote en la cara dentro de unos minutos.

Paso 1: Instalando Docker

Lo típico, Descargar docker del enlace oficial, botón siguiente, siguiente, etc… Docker instalado y un aviso de que de Hyper-V no está instalado en mi ordenador y la pregunta de si quiero que Docker lo active por mi… Hasta ahora muy limpio todo, si señor.

hyper-v-not-installed-by-docker

Reinicio el ordenador y vuelvo en un minutos…. ¡Fantástico! Docker está instalado y tengo un icono en la bandeja del sistema que me dice que está corriendo.

De momento el invento funciona muy bien.

Paso 2: Probando Docker en Windows

Seguimos con la guía de instalación, abro una consola de sistema (Recordatorio: He de probar bash para Windows,…) y ejecuto docker run hello-word.

¡Genial! Parece que todo funciona. Ha sido tan fácil que incluso me da vergüenza estar escribiendo este tutorial.

Probaremos algo más ambicioso, descargar un ubuntu y ejecutar bash en modo interactivo dentro de ese ubuntu.

Docker se descargará una imagen de ubuntu en pocos segundos y ejecutará bash dentro de el. Hacemos un ls y en efecto, funciona, exactamente igual que en linux. Estoy corriendo en un windows un container docker que tiene un bash corriendo en ubuntu perfectamente funcional. Para cerrarlo, simplemente ejecutamos exit, lo que cerrará el bash. Al estar en modo interactivo ( parámetro -it), el contenedor de docker se cerrará. Si volvemos a lanzarlo veremos que arranca infinitamente más rápido, ya que ahora no necesita descargar la imagen de ubuntu.

¡Docker mola mucho!

Paso 3: Montando contenedores docker

Bueno.. a partir de ahora habría que seguir por lo obvio, exactamente igual que en linux, crear un archivo de configuración con los contenedores que nos interesen, compartir una unidad de disco entre el contenedor y el host si queremos tocar código de manera fácil, o exportar los logs, mapear los puertos internos y externos, etc..

De todo eso se trata en la propia guía de docker Get Started with Docker y se escapa un poco de lo que pretendía ser este artículo.

Por lo que a mi respecta, me voy a buscar una buena imagen para correr apache con php7 y posiblemente otra para un mongodb o un redis (aún no tengo claro) y crearé un docker compose que me lance las 2 y las configure adecuadamente.

Instalando varnish

En un artículo anterior ya hicimos una introducción previa a varnish por lo que si quieres saber mejor cómo puede ayudarte te aconsejo que lo leas por encima.

En este artículo os voy a explicar los puntos mínimos que hemos de cubrir para tener una configuración mínima de varnish funcionando. Al acabar el tutorial tendrás una instalación mínima que funciona, que cachea en parte tu aplicación web y que será la base para construir sistemas mucho más complejos que se adapten a tus necesidades.

Consideraciones previas

El tema de los puertos

Como bien sabrás los servidores web funcionan habitualmente escuchando el puerto 80 para http y el 443 para https (En este artículo dejaremos de lado https ya que debido a que el tráfico está encriptado hay que tener algunas consideraciones adicionales).

Varnish es un acelerador web que se coloca delante del servidor web, entre este y el usuario. Es decir, las peticiones que antes se dirigían hacia el web server, ahora las atenderá varnish, y varnish se encargará de hablar con el servidor web.

Por tanto, varnish y apache (o nginx) no pueden estar escuchando en el mismo puerto.

Existen varias soluciones a este problema. Podríamos instalar varnish en otro servidor, siendo esta una de las soluciones habituales en entornos de alta demanda.

También podemos mover el puerto en el que apache atiende a otro diferente, por ejemplo el 8000. Entonces, dejaremos que varnish sirva sobre el 80 y realice las peticiones sobre el 8000, donde el servidor web le atenderá.

Varnish en el mismo servidor donde ya corren varias webs

En mi caso, me encontré con que tenía varias webs en el servidor, todas ellas corriendo con apache y, por supuesto, en el puerto 80. Yo quería instalar varnish en el mismo servidor, por lo que debía hacer varios cambios en las configuraciones que me iban a dejar las webs caídas por algo de tiempo.

Yo aproveché para hacer un cambio de servidor completo, gracias a las ventajas de los servidores virtuales. Creé una nueva instancia, instalé un sistema limpio y actualizado, configuré apache para correr en el puerto 8000 y varnish en el 80 moví sólo una web. Una vez estuvo todo correcto, empecé a mover webs del server antiguo al nuevo. Cuando finalicé la migración de todas las webs apagué el server antiguo. Sólo pagué por dos servidores durante los días que los tuve en marcha pero el proceso me sirvió para limpiar bien la casa.

Otra alternativa si no quieres, o no puedes levantar otra máquina virtual es instalar varnish en el puerto 8000 en lugar del 80. A partir de aquí, sólo tu sabes que corre en el 8000 (también puedes filtrar el tráfico por IP para que nadie haga el cotilla). Así puedes ir probando todas tus webs con varnish, accediendo a ellas a través del nuevo puerto. Cuando estés seguro de que todo funciona, configuras apache para servir en el 8000 y varnish en el 80, es decir, le das la vuelta a la instalación. Es bastante sencillo y seguro.

Memoria y CPU

Varnish es básicamente un consumidor de memoria y CPU. En realidad, básicamente de memoria, porque la CPU que usa la está ahorrando a otros servicios como el servidor web o la base de datos.

En mi experiencia,  con 500 MB o 1 GB es suficiente para que varnish suponga una mejora MUY importante en rendimiento del server. Pero estos números dependen de cada uno, tipo de web, comportamiento de las visitas, si usamos un CDN para estáticos o bien si los guardaremos en varnish, etc…

Si instalas varnish en tu servidor actual, tienes que asegurarte de que dispones de esa memoria adicional. Ten en cuenta también que cuando varnish esté correctamente configurado, tu apache correrá mas ligero por lo que necesitará menos recursos que pueden asignarse a varnish.

Si lo estás instalando en un servidor nuevo que hará de frontal, mi consejo es que empieces con una configuración mínima de 2GB o 4 GB que siempre puedes ampliar en el futuro, especialmente si corres con virtual servers. ¿Todavía con máquinas físicas? Tendrás que llamar a tu proveedor para le meta RAM, pero.. ¿De verdad estás usando aún máquinas físicas?

Instalando varnish

Ya he hablado antes de que existen diferentes configuraciones posibles. Aquí vamos a explicar como instalar varnish en un servidor nuevo, donde un apache escucha en el puerto 8000 y varnish correrá delante de el en el puerto 80.

Dependiendo de tu sistema operativo tendrás que descargar el paquete del repositorio adecuado. En mi caso, usé un debian y la instalación fue mi sencilla, simplemente un

sudo apt-get install varnish

El archivo de configuración de varnish es /etc/default/varnish. Allí configuré varnish para usar el puerto 80 y una memoria de 1024 MB. Esta es la parte que te interesa:

DAEMON_OPTS=”-a :80 \
-T localhost:6082 \
-f /etc/varnish/default.vcl \
-S /etc/varnish/secret \
-s malloc,1024m”

Un restart de apache y varnish, y todo está corriendo ya bajo varnish.

sudo service apache2 restart

sudo service varnish restart

NOTA: El orden es importante. A partir de ahora, siempre que quieras reiniciar tu servidor web debes reiniciar primero apache y luego varnish. Si lo haces al revés, varnish podría no reflejar parte de los cambios que hayan necesitado reiniciar tu apache.

Y ya lo tienes, si visitas tu web debería funcionar. El navegador ha pedido la página al puerto 80, allí varnish ha atendido la petición, ha visto que no tenía la página en memoria y la ha solicitado al apache. Cuando ha obtenido la respuesta, la ha entregado a tu navegador.

Puedes usar firebug u otro plugin que estudies las cabeceras de respuesta de la petición.  Verás que la respuesta incluye algunos campos como  Age=0, Via=1.1 varnish-v4 y X-varnish.

Varnish instalado, pero, ¿Está funcionando?

Técnicamente si. Está funcionado. Si el ejemplo que has usado es una página estática con algunos recursos pesados como imágenes notarás claramente como se sirve más rápido. Puedes verlo fácilmente con firebug, evaluando los tiempos de respuesta. Puedes comparar pidiendo la misma página al puerto 80 y al 8000 y mirando los tiempos.

También puedes fijarte en la cabecera http llamada age. Si tiene un valor diferente a cero y se incrementa en cada petición, significa que se está sirviendo desde la cache.

También puedes abrir tu log de apache y realizar múltiples peticiones. Verás como sólo aparece la primera. El resto, se entregan desde varnish y apache ni se entera.

También puedes usar la herramienta de consola varnishstat para ver que es lo que está pasando en varnish. main.cache_hit es un indicador que deberíamos mirar. Expresa el número de peticiones que se han servido desde la cache de varnish.

Mi varnish no cachea

Puede ocurrir, y en la realidad es muy frecuente, que después de una instalación básica de varnish no notemos ninguna mejora. Esto puede deberse a diferentes motivos que iremos exponiendo más adelante.

Uno de ellos puede ser la configuración de tiempos de expiración de tu apache. Si apache está sirviendo las páginas indicando que no se cacheen, o sin tiempos de expiración, varnish obedecerá a esas directivas y no cacheará salvo que se lo digamos explicitamente.

Otro motivo son las cookies. Como sirven para guardar estados dentro de una sesión concreta, varnish es muy conservador y por defecto decide ignorar cualquier petición que tenga cookies, para evitar riesgos y servir una página de un usuario a otro. ¡Imagina que ocurriría si consulto mi saldo bancario y me enseñan los datos de otro cliente!

En el siguiente artículo os explicaré como solucionar el tema de las cookies y os mostraré lo que debería ser un archivo básico de configuración que ofrece un buen rendimiento.

Varnish. ¿Qué es y cómo puede solucionar casi todos tus problemas?

Dice la wikipedia que Varnish es un acelerador de aplicaciones web, también conocido como un caché de proxy http inverso. Vale, muy bien, y eso, ¿Que significa y para que sirve?

En realidad es bastante sencillo. Se trata de un servicio que se coloca entre tu servidor web y tus clientes, es decir, entre tu apache o nginx y los navegadores o servicios que realizan peticiones a tu servidor. La parte interesante es que se encarga de cachear en memoria peticiones de recursos (páginas, imágenes, css, javascripts, etc..) que se le hacen recurrentemente a tu servidor http. Eso significa que se ahorrarán muchas peticiones a tu servidor web, que serán servidas directamente a los clientes desde memoria y no desde disco.

Tus visitantes tendrán una mejor experiencia porque es verdaderamente rápido y tu servidor http funcionará mucho más relajado ya que tendrá que atender muchas menos peticiones.

Lo más interesante de varnish es que es muy rápido. Mucho más que un apache o nginx. Un servidor pequeño puede pasar de un límite de 10 o 100 peticiones por segundo a varios miles. Trabaja en memoria y está programado a bajo nivel. No toca el disco y básicamente usa dos recursos como son la memoria y la CPU que habitualmente están desaprovechados en un servidor web. Los recursos de un servidor se usan más y mejor.

¿Quien necesita un varnish?

Generalmente se entiende que necesitas un varnish en servidores de alto rendimiento, es decir, aquellos que tienen muchísimas peticiones por segundo. Mi opinión es mucho más amplia. Practicamente cualquier instalación puede beneficiarse de un varnish ya que:

  • Varnish acelera muchísimo la velocidad de entrega de los recursos de tu web. Eso es bueno para la experiencia de los usuarios y también es muy bueno para el SEO.
  • Varnish libera recursos de tu servidor. Eso significa que podrías contratar un servidor con menos memoria o CPU y asumir la misma carga de trabajo. Muy interesante para los que tenemos contratada una VPS para nuestros jueguecitos.
  • Varnish permite escalar horizontalmente, es decir, te permite disponer varios servidores web que entreguen el mismo contenido. Lleva implementado un balanceador de carga que puede ayudarte mucho si un día tu web es más famosa que facebook. Puedes empezar con un único servidor y poco a poco ir añadiendo servidores en función de tus necesidades.
  • Puede ayudarte con la seguridad de tu web. En parte porque te asegura más capacidad de carga, es más difícil que te lo tumben. Además, muchas reglas de seguridad que habitualmente colocamos en un htaccess pueden llevarse a la configuración de varnish, respondiendo antes y más rápido que un apache.

La pregunta del millón. ¿Es fácil?

Si. Es sencillo de instalar. La documentación es buena aunque se echa en falta un tutorial. A veces hay que leer más de lo deseable, pero aquí estoy yo para ayudarte ;-). Hay muchos recursos en la red que te pueden ayudar.

Necesitas algunos conocimientos mínimos de configuración de servicios web. Por ejemplo, si varnish corre en el mismo servidor que apache, tendrás que cambiar el puerto en el que apache escucha (generalmente el 80), porque no puedes tener dos servicios escuchando el mismo puerto.

Si instalas varnish en otro servidor (muy recomendable si piensas balancear carga en el futuro), tendrás que apuntar tu dominio a la nueva máquina.

Yo no soy ningún lumbreras como devop y monté mi primer varnish en unas horas.

¿Es peligroso usar varnish?

Respuesta rápida. No.

Respuesta más meditada. Depende de ti.

Por defecto, varnish no cache nada que tenga una cookie. Las cookies se usan para mantener sesiones de usuarios, por ejemplo. Como varnish no sabe cual es el objetivo de una cookie en concreto, simplemente no hace nada si ve cookies. En la mayoría de instalaciones no existe ningún peligro usando un varnish por defecto. Sin embargo, la principal frustación es que varnish apenas hace nada en muchas instalaciones porque casi todas las webs usan cookies. No te preocupes, que es fácil decirle como ignorarlas.

Por otro lado, varnish es una cache. Es tu responsabilidad saber que puedes cachear y que no. Como ya hemos dicho, varnish es muy miedoso y no cachea nada si intuye algún peligro. Mediante los ficheros de configuración le diremos que riesgos debe ignorar. Por ejemplo, es habitual decirle a varnish que no cache ninguna página de administración, o que ignore todas las cookies excepto las de sesión.

Varnish para contenido estático como imágenes o assets

Las páginas web tienen mucho contenido estático que se entrega una y otra vez en cada página y que raramente cambia, por ejemplo, imágenes, archivos css o javascripts. Este tipo de archivos son candidatos de primer nivel a ser cacheados y, en realidad, generalmente el propio browser ya los cachea. Con varnish puedes, además, evitar que apache esté sirviendo una y otra vez el mismo recurso, dedicándose sólo a aquello que es importante, generar páginas html.

Hay alguna línea de pensamiento que cree que no es buena idea hacerlo. Argumentan que las imágenes o vídeos consumen mucha memoria, limitando la cantidad de entradas que varnish puede asumir. Algunos de los defensores de esta idea usan CDNs para servir contenidos estáticos. Otros usan nginx que tiene mecanismos para cachear en memoria estos contenidos estáticos. It’s up to you! Es una decisión de arquitectura.

Personalmente, soy un gran defensor de usar varnish para contenidos estáticos, especialmente en instalaciones pequeñas. Además, es muy fácil de configurar. Si miras un log de apache verás que la mayoría de peticiones son de pequeños archivos estáticos. ¿Cuantas veces se pide el logo de tu web o tu favicon? Con varnish, esas peticiones desaparecen.

Varnish con WordPress

Varnish es completamente agnóstico respecto al tipo de web o contenido que se está entregando. Sólo sirve y cachea peticiones web. Por tanto, funciona perfectamente con wordpress. Sin embargo, como todo sistema de cache hemos de tener en cuenta conceptos como la invalidación de entidades.

Un ejemplo. ¿Que pasa si varnish está cacheando tus páginas por 30 minutos, pero alguien añade un comentario en un post?  Tenemos dos soluciones. La primera, ignorar el problema. El comentario aparecerá cuando pasen los 30 minutos de vida. La segunda, purgar la cache automáticamente. Sin miedo. Es fácil. Los mejores plugins de cache de wordpress saben hablar con varnish y pedirle que invalide una página cuando se produce un cambio. Simplemente tendrás que configurar tu varnish para que acepte peticiones de purge y configurar tu wordpress para que lance esas peticiones cuando lo estime conveniente.

Varnish con Symfony y otros frameworks

Symfony tiene mecanismos casi de serie para comunicarse con un varnish u otros proxies. Tienes que mirarte el tema de ESI (Edge Side Includes). Seguro que otros frameworks también lo usan. En todo caso, no es difícil de implementar a mano.

Básicamente, lo de ESI consiste en crear unas marcas en html que le dicen a varnish u otros CDNs que determinadas partes de tu página pueden ser diferentes para cada usuario. Por ejemplo, el menú de un usuario logado puede ser diferente a uno anónimo.  En esas marcas ESI se le dice que url debe solicitar al servidor para recuperar esa parte de la información.Cuando varnish encuentra esas marcas en una página que está en su memoria, realiza una llamada al apache para cargar la parte de la página que le falta, la incluye en la página madre y la entrega al cliente.

Aquí hay algunas consideraciones que desarrollaré más ampliamente en otro tema. Y es que symfony es un framework pesado y a veces puede suponer un problema hacer muchas llamadas esi dentro de la misma página, resultando en una carga más lenta de  tu web. Pero existen estrategias para minimizar el problema y aún así el uso de varnish puede mejorar el rendimiento de tu servidor a cambio de una entrega de algunos recursos algo más lenta.