R Shiny es una de las formas más eficientes de crear aplicaciones de datos interactivas. Y cuando llega el momento de entregar tus paneles analíticos avanzados a los usuarios, es importante garantizar entornos reproducibles y estabilidad. Esto evitará sorpresas desagradables y retrasos al final del proceso, cuando tanto tú como tus usuarios pensaban que todo estaba listo.
La necesidad de un camino fluido desde el desarrollo hasta los despliegues en producción no es exclusiva de Shiny, sino que se aplica a muchas tecnologías en diferentes industrias. Docker es una excelente manera de lograr esto, tanto es así que Docker (y los contenedores en general) se han convertido en un estándar de la industria para la entrega de aplicaciones.
En esta publicación de blog, aprenderás cómo comenzar a ejecutar una aplicación Shiny desde un contenedor y luego usar Faucet para desplegar tu aplicación Shiny en producción.
Docker es la herramienta más popular para construir y ejecutar contenedores. Aloja el registro más popular de imágenes de contenedores, DockerHub, y ha sido adaptado para todas las plataformas populares.
El uso de contenedores puede ofrecer muchos beneficios, entre los que se incluyen, pero no se limitan a:
Puedes comenzar con Docker visitando: docker.com para obtener instrucciones específicas de instalación para cada plataforma.
Para este ejemplo, crearemos una aplicación Shiny muy sencilla. Utilizaremos un único archivo app.R en lugar de separarlo en múltiples archivos para mayor simplicidad, sin embargo, el ejemplo será válido en ambos casos.
Este será el código que incluiremos en el archivo app.R:
library(shiny)
library(bslib)
ui <- page_sidebar(
title = "Hello Shiny!",
sidebar = sidebar(
sliderInput(
inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30
)
),
plotOutput(outputId = "distPlot")
)
server <- function(input, output) {
output$distPlot <- renderPlot({
x <- faithful$waiting
bins <- seq(min(x), max(x), length.out = input$bins + 1)
hist(x, breaks = bins, col = "#007bc2", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times")
})
}
shinyApp(ui = ui, server = server)
Podemos verificar que la aplicación funciona ejecutándola en nuestra consola de R con shiny::runApp().
En esta sección, aprenderás a escribir un Dockerfile para tu aplicación Shiny. El Dockerfile contiene la receta para crear tu imagen. Un Dockerfile típicamente incluye una imagen base y un conjunto de instrucciones.
Este es el Dockerfile que utilizaremos para nuestra aplicación Shiny mínima:
# Base image for our image
FROM ixpantia/faucet:r4.4
# Install the packages we need
RUN Rscript -e "install.packages(c('shiny', 'bslib'))"
# Copy the file app.R from our computer to the image
COPY app.R app.R
# We are done!
Este Dockerfile se puede resumir en lo siguiente:
Antes de continuar, se recomienda guardar este archivo con el nombre Dockerfile en el mismo directorio donde se encuentra la app.R.
ixpantia/faucet
?La imagen de Docker ixpantia/faucet
viene con Faucet pre configurado para ejecutarse en el directorio de trabajo predeterminado. Esto te permite crear archivos Docker mínimos sin mucha configuración adicional.
Faucet ofrece varios beneficios integrados, como réplicas de la aplicación, registro de solicitudes, un enrutador multi-aplicaciones y soporte para APIs de Plumber. Esto significa que puedes usar el mismo flujo de trabajo para la mayor parte de la infraestructura que necesitas desplegar con R, lo que proporciona un gran impulso a la productividad de tu equipo.
ixpantia/faucet
también es compatible con arm64 y amd64, lo que significa que Faucet se ejecuta de forma nativa en servidores ARM, PCs y portátiles, mientras que otras opciones pueden estar disponibles sólo para sistemas x86 o requerir capas de emulación que afectan al rendimiento.
Para aprender más sobre faucet puedes visitar GitHub o leer la documentación oficial.
Ahora que tenemos un Dockerfile, necesitamos construirlo en una imagen. Asegúrate de que tu directorio de trabajo sea el mismo en el que se encuentran el Dockerfile y app.R. Luego, puedes ejecutar el siguiente comando:
docker build -t shiny-app .
Esto iniciará el proceso de construcción con la etiqueta shiny-app.
Una vez que la imagen esté construida, podemos ejecutar la aplicación. Algo importante a tener en cuenta es que necesitaremos exportar un puerto al equipo del usuario. Podemos hacerlo utilizando la bandera -p.
Para ejecutar el contenedor, podemos ejecutar el siguiente comando:
docker run -p 3838:3838 shiny-app
¡Ahora podemos acceder a localhost:3838
y ver nuestra aplicación en funcionamiento!
Si observas la salida de tu terminal, es posible que veas registros detallados sobre lo que está ocurriendo en la aplicación.
Si estás buscando llevar tu aplicación a producción, puede que te interese modificar algunas opciones para asegurarte de que la aplicación funcione como deseas.
Si utilizas el contenedor en un sistema multinúcleo, probablemente notes que se inician varios workers. Estos workers son réplicas de nuestra aplicación, lo que te permite escalarla al servir conexiones concurrentes en diferentes núcleos/procesos de tu contenedor. Puedes ajustar esto configurando la variable de entorno FAUCET_WORKERS
en tu Dockerfile. Si no se establece, el número de workers será igual al número de núcleos lógicos en tu contenedor.
# Base image for our image
FROM ixpantia/faucet:r4.4
# Install the packages we need
RUN Rscript -e "install.packages(c('shiny', 'bslib'))"
# Copy the file app.R from our computer to the image
COPY app.R app.R
# Set four workers
ENV FAUCET_WORKERS=4
# We are done!
Si planeas desplegar tu aplicación en un servicio como Google Cloud Run, AWS ECS o Fargate, el apagado controlado hará que el proceso de despliegue continuo sea más fluido. El apagado controlado permite que la aplicación y sus réplicas no se detengan hasta que todas las conexiones o solicitudes se hayan completado. Podemos añadir el apagado controlado configurando la variable de entorno FAUCET_SHUTDOWN
en tu Dockerfile. Esto asegura que las actualizaciones o despliegues no interrumpan las solicitudes en curso.
# Base image for our image
FROM ixpantia/faucet:r4.4
# Install the packages we need
RUN Rscript -e "install.packages(c('shiny', 'bslib'))"
# Copy the file app.R from our computer to the image
COPY app.R app.R
# Enable graceful shutdown
ENV FAUCET_SHUTDOWN=graceful
# We are done!
En conclusión, utilizar Docker para contenerizar tu aplicación R Shiny ofrece beneficios significativos, como estabilidad, portabilidad y reproducibilidad. Siguiendo los pasos descritos en esta guía, puedes asegurarte de que tu aplicación Shiny funcione en un entorno consistente, tanto para el desarrollo como para la producción.
Si deseas llevar tu infraestructura R al siguiente nivel, ¡Contáctanos y comienza tu camino con ixpantia!