Cómo poner una app Shiny en producción

Si usas R, entonces seguramente conozcas Shiny, uno de los paquetes de R, el cual permite crear aplicaciones web completamente en R. Shiny es muy potente y es muy fácil ponerlo en producción si usamos Shinyapps, pero… ¿y si queremos poner nosotros nuestra app Shiny en producción sin depender de nadie más?

En este post te explico cómo puedes poner una app Shiny en producción usando dos servicios diferentes de Google Cloud: Cloud Run y Compute Engine. Para ello usaremos Docker, el SDK de Google Cloud y el propio Google Cloud.

En cualquier caso, ¿por qué deberías aprender a subir tu app Shiny a diferentes servicios Cloud si ya tienes Shinyapps? Te lo explico.

Por qué subir una app shiny a Google Cloud

Cuando ponemos una app Shiny en producción tenemos dos opciones: usar Shinyapps o tener que subirla nosotros a un entorno Cloud.

Generalmente por sencillez usamos el primer caso ya que Shinyapps ofrece hospedar apps de forma gratuita. Sin embargo, tiene varias limitaciones:

  • Máximo solo puedes subir 5 aplicaciones.
  • Todas las aplicaciones solo pueden ejecutarse por 25 horas. Si la gente la usa más, entonces dejarán de funcionar. Y sí, 25 horas no son tantas como parecen.
  • En cuanto a almacenamiento, como máximo la aplicación contará con 1Gb de espacio en la versión Free. Cuanta más capacidad necesites, más pagarás, siendo el máximo 5Gb de aplicación.
  • Respecto a procesamiento, la aplicación contará como máximo con 1Gb en la versión Free.

En definitiva, si no crees que vayas a sobrepasar alguna de estas limitaciones, adelante, Shinyapps es la opción a elegir. Sin embargo, con aplicaciones medianas es muy posible que lo superes y, en esos casos, seguramente sea más económico subir la app a un entorno Cloud que subirlo a Shinyapps.

Bien, ahora que ya sabes por qué deberías saber poner en producción una app Shiny con Google Cloud, veámos cómo se hace.

Cómo poner una app Shiny en producción en Google Cloud

Paso 1. Crear la imagen Docker

Docker es un software muy utilizado en Data Science para aislar y paquetizar nuestro software, de tal forma que podamos ejecutarlo en cualquier entorno con Docker.

Si no sabes de Docker, te recomiendo que leas el tutorial sobre Docker para Data Science que he creado.

En nuestro caso, para crear una imagen Docker que use Shiny, partiremos de la imagen de rocker/shiny, la cual cuenta con todo lo necesario. Tal como indica la documentación, el directorio de la aplicación se encuentra en /srv/shiny-server/, por lo que es ahí donde tendremos que pegar nuestros ficheros.

En mi caso cuento con la siguiente estructura:

.
├── app
│   ├── ui.R  
│   └── server.R
│
└── Dockerfile

Teniendo esto en cuenta el fichero Dockerfile es el siguiente:

FROM rocker/shiny

# Install Packages
RUN R -e 'install.packages(c("shiny"))'


# Copy App
COPY ./app/* /srv/shiny-server/

# run app
CMD ["/usr/bin/shiny-server"]

Con esto ya tenemos el Dockerfile y podemos montar la imagen Docker:

docker build -t pi_app .

Ahora podemos lanzar la imagen Docker:

docker run --rm -p 3838:3838 pi_app

Por último, podemos comprobar que funciona correctamente accediendo a la página localhost:3838.

Aplicación Shiny en local

Genial, ya tenemos nuestra aplicación corriendo en local con Docker, ahora veamos cómo poner nuestra app shiny en producción, para lo cual tendremos que subir esta imagen Docker a Google Cloud.

Paso 2. Subir imagen Docker a Google Cloud

Para subir una imagen Docker a Google Cloud vamos a tener que hacer tres cosas:

  1. Habilitar las APIs requeridas.
  2. Instalar y configurar el Google Cloud SDK.
  3. Subir la imagen al Container Registry.

Veámos estos pasos de uno en uno.

1. Habilitar las APIs requeridas

Lo primero de todo para subir una imagen Docker a Google Cloud es habilitar las APIs necesarias en Google Cloud. Más especificamente tenemos que habilitar las APIs de Cloud Run, Cloud Build y Container Registry.

Aunque esto es algo que ya hemos visto en otros post como el de poner un modelo de R en producción o automatizar scripts de R en Google Cloud, explico cómo hacerlo:

  1. Ve a la librería de APIs de Google Cloud (enlace) y busca la API que quieras activar.
  2. Habilita la API haciendo clic en el botón habilitar.

2. Instalar y configurar el Google Cloud SDK

Un SDK (Software Development Kit) nos permite interactuar con otro servicio de forma sencilla. En este caso, podremos trabajar con Google Cloud desde nuestra propia terminal del ordenador. De esta forma, por ejemplo, podremos subir una imagen Docker al Container Registry, entre muchas otras cosas.

Para descagar el Google Cloud SDK simplemente debes acceder a este enlace, elegir tu sistema operativo y descargalo del enlace que aparecerá en la ficha explicativa.

Una vez lo hayas instalado deberás configurarlo. Más concretamente debes hacer tres cosas:

  1. Actualizar el Cloud SDK. No es obligatorio, pero suele ser una buena idea. Para ello debes ejecutar el siguiente comando:
gcloud components update

2. Vincular tu ordenador con tu cuenta de Google Cloud. Para vincularte simplemente deberás ejecutar el siguiente comando en la consola:

gcloud auth login
  1. Vincular Docker con Google Cloud. Para ello, primero deberás habilitar Docker, lo cual puedes hacerlo ejecutando el siguiente comando en la consola: . Tras haber hecho esto, puedes conectar Google Cloud y Docker con el siguiente comando:
gcloud auth configure-docker

Ahora que ya hemos configurado el Cloud SDK, veamos cómo subir la imagen Docker al Container Registry.

3. Subir imagen Docker al Container Registry

Para subir una imagen Docker al Container Registry tenemos que tener la siguiente información:</p>

1. Nombre de la imagen. Si te acuerdas, este nombre lo dimos al montar la imagen usando el Dockerfile usando el comando:

docker build -t <nombre_imagen>.
  1. Id de la cuenta de Google Cloud: lo puedes encontrar en la tabla de proyectos de tu cuenta de Google Cloud.
Id de un proyecto de Google Cloud

Una vez tengamos la información previa, tendremos que dar un nuevo nombre a nuestra imagen Docker. Para ello, abre una consola en terminal y ejecuta el siguiente comando:

docker tag <nombre imagen> gcr.io/< project id>/<nombre imagen>

# My case
# docker tag app_pi gcr.io/shiny-in-production/app_pi

Una vez le hemos dado un nuevo nombre, podremos subirla al Container Registry. Para ello solo hay que ejecutar el siguiente comando:

docker push gcr.io/< project id>/<nombre imagen>

# In my case
# docker push gcr.io/shiny-in-production/app_pi
Subida de una imagen Docker al Container Registry

Si has seguido los pasos y no te ha saltado ningún error (y te sale algo como la imagen anterior) perfecto, ya tienes tu app subida en el Container Registry. Ahora solo tendremos que desplegarla en uno de los distintos servicios que ofrece Google Cloud.

Paso 3. Desplegar la imagen Docker en un servicio de Google Cloud

Una vez hemos elegido la imagen Docker llega el momento de la verdad: elegir el servicio de Google Cloud en el que desplegaremos nuestra aplicación.

Desplegar nuestra app Shiny en Google Cloud es muy sencillo. Primero vamos al Container Registry, elegimos el bucket que tenga el mismo nombre que nuestra imagen y elegimos la imagen. Una vez hecho, nos saldrá una pantalla como la siguiente:

Deploy de una App Shiny en producción en Google Cloud

En la parte superior aparece un botón con el texto “Deploy”. Haciendo click nos dará tres opciones:

  • Cloud Run: es un servicio serverless, es decir, que no tienes un servidor contratado, sino que, a medida que se van recibiendo peticiones se van levantando servidores. Lo bueno es que, si no tienes tráfico a la página no pagarás.
  • Google Compute Engine (GCE): en este caso sí contratas un servidor, por lo que todas las peticiones las devolverá el servidor.
  • Google Kubernetes Engine (GKE): es similar a Cloud Run, con la diferencia de que puedes modificar cada aspecto de la orquestación, el almacenamiento, etc. Personalmente, en el caso de una aplicación Shiny no creo que tenga mucha sentido.

Asimismo, tanto en Cloud Run como en Compute Engine puedes elegir las capacidades del servidor, tanto la cantidad de CPUs como la cantidad de memoria RAM. En ambos casos es un desplegable.

Así pues, ¿cómo eliges entre desplegar la aplicación Shiny en Cloud Run o Compute Engine?

Cómo elegir entre Cloud Run y Compute Engine

Pues bien, aunque un servidor de Cloud Run podría ejecutar varias aplicaciones a la vez, la realidad es que Shiny es un servicio stateful, mientras que Cloud Run esta pensado para servicios stateless.

Esto supone que solo vas a poder tener una única aplicación por servidor y Cloud Run solo ofrece tener 1000 servidores levantados al mismo tiempo.

Por tanto, si supones que tu aplicación Shiny tendrá más de 1000 usuarios concurrentes, entonces podrás usar Cloud Run, sino, tendrás que usar Compute Engine.

De todos modos, este no será un problema en la gran mayoría de aplicaciones Shiny no superarán este límite. Y, si lo hacen, al tener la aplicación en Docker sería tan fácil como hacer el deploy en Compute Engine.

En cualquier caso, al hacer el deploy de la aplicación en Cloud Run se tendrá que fijar el número de requests por contenedor en uno, como en la imagen siguiente:

Elección de la capacidad y número de requests por contenedor

Asimismo, recuerda establecer el puerto de la conexión de Cloud Run el mismo que fijaste en Docker (en mi caso el 3838).

Si haces esto de forma correcta, habrás desplegado la aplicación y te aparecerá una pantalla resumen como la siguiente:

Resumen de la subida de la app Shiny en producción en Google Cloud

Si este es tu caso, ¡enhorabuena! Ya tienes tu aplicación Shiny en producción. Para acceder a ella simplemente tendrás que visitar la URL que aparece en la página parte superior de la pantalla:

Precio de Cloud Run

Perfecto, ya has puesto tu aplicación en producción, pero… ¿cuánto va a costar? Pues, depende del uso incluso puede que sea gratis. Y es que, por defecto, Cloud Run de forma gratuita ofrece :

  • 50 horas de CPU.
  • 100 horas de uso de 1Gb RAM (si usas 2Gb/máquina entonces serían 50).
  • 2 millones de solicitudes.

Vamos, que si vas a usar una aplicación que tenga 1CPU y 1Gb de RAM, mientras que con Shinyapps tendrías solo 25 horas gratis, con Cloud Run tendrás 50. Además, durante otras 50 únicamente deberías pagar por la CPU, lo cual cuesta 0,00002400$/s (enlace). Es decir, que las primeras 100 horas de tu aplicación únicamente te costarán 4,32 dólares, mientras que en Shinyapps cuesta más del doble (9$/mes).

En definitiva, poner tu app Shiny en producción en Cloud es algo más laborioso que subirla a Shinyapps, pero, sin duda, a nivel de coste merece la pena.

Conclusión

Como ves, si sabes de Docker es muy sencillo poner tus aplicaciones Shiny en producción en servicios Cloud. Esto te dará una gran flexibilidad y escalabilidad a la hora de hacer que tus aplicaciones lleguen a cientos de personas.

Espero que te haya gustado el post. ¡Nos vemos en el siguiente!