faucet en Contenedores (Docker)
Probablemente la manera más fácil y versátil de implementar faucet es construir una imagen de contenedor Linux y ejecutarla en un contenedor. Esto le permitirá ejecutar faucet en cualquier host de Linux que admita contenedores, como una computadora portátil, una máquina virtual o un servidor.
Construir una Imagen de Docker para faucet
En esta sección, utilizarás la imagen disponible de faucet + R desde Docker Hub. Sin embargo, también puedes construir tu propia imagen si lo deseas. Debes seguir las instrucciones de instalación disponibles para tu sistema operativo para instalar Docker.
Para construir correctamente la imagen de faucet, debes tener en cuenta los siguientes pasos:
- Instalar Docker en tu máquina host. Puedes encontrar las instrucciones específicas para tu sistema operativo en la Guía de Instalación de Docker.
- Considerar las dependencias de tu aplicación en R. Si estás utilizando paquetes R que requieren dependencias del sistema, deberás instalarlas en la imagen de Docker. También, ten en cuenta las versiones de R y las bibliotecas; te recomendamos utilizar renv. Para este tutorial, asumiremos que ya estás utilizando
renv
. - Ignorar archivos sensibles o innecesarios. Puedes utilizar un archivo
.dockerignore
para ignorar archivos que no son necesarios en la imagen de Docker, o puedes especificar manualmente los archivos que deseas incluir en la imagen. En este caso, utilizaremos un archivo.dockerignore
para ignorar dichos archivos.
Una aplicación básica Shiny o Plumber API
En esta sección, arrancarás una aplicación Shiny básica o Plumber API para utilizar como ejemplo. Puedes usar tu propia aplicación o API, pero asegúrate de tener renv
inicializado.
Aplicación Shiny
# app.R
library(shiny)
ui <- fluidPage(
titlePanel("¡Hola Shiny!"),
sidebarLayout(
sidebarPanel(
sliderInput("obs", "Número de observaciones:", min = 10, max = 500, value = 100)
),
mainPanel(
plotOutput("distPlot")
)
)
)
server <- function(input, output) {
output$distPlot <- renderPlot({
hist(rnorm(input$obs))
})
}
shinyApp(ui = ui, server = server)
Después de guardar la aplicación, puedes ejecutarla localmente con:
shiny::runApp()
Para asegurarte de que renv
detecte todos los paquetes utilizados en la aplicación, debes crear un archivo dependencies.R
con el siguiente contenido:
# dependencies.R
library(shiny)
Ahora puedes inicializar renv
e instalar los paquetes:
renv::init()
renv::activate()
Plumber API
# plumber.R
#* @get /echo
function(){
list(msg = "¡Hola Mundo!")
}
Después de guardar la API, puedes ejecutarla localmente con:
library(plumber)
# 'plumber.R' es la ubicación del archivo mostrado anteriormente
pr("plumber.R") %>%
pr_run()
Para asegurarte de que renv
detecte todos los paquetes utilizados en la API, debes crear un archivo dependencies.R
con el siguiente contenido:
# dependencies.R
library(plumber)
Ahora puedes inicializar renv
e instalar los paquetes:
renv::init()
renv::activate()
Dockerfile
Dockerignore
El primer paso para construir nuestra imagen de Docker es crear un archivo .dockerignore
en la raíz de nuestro proyecto. Este archivo contendrá los archivos que deseas ignorar al construir la imagen de Docker. En este caso, ignoraremos los siguientes archivos de renv
:
renv/library/
renv/local/
renv/cellar/
renv/lock/
renv/python/
renv/sandbox/
renv/staging/
Si este fuera un proyecto real, probablemente también ignorarías archivos como .git
, .Rproj.user
, .DS_Store
y archivos sensibles como .env
, .htpasswd
, etc.
Escribir el Dockerfile
El primer paso para construir nuestra imagen de Docker es crear un archivo Dockerfile
en la raíz de nuestro proyecto. Este archivo contendrá las instrucciones para construir nuestra imagen de Docker. En este caso, utilizarás la imagen ixpantia/faucet
como base. Esta imagen se basa en la imagen rocker/r-ver
, que es una imagen R mínima basada en Debian Linux.
FROM ixpantia/faucet:r4.3
# Algunas variables de entorno para indicar a `renv`
# instalar paquetes en la ubicación correcta
# y sin enlaces simbólicos innecesarios
ENV RENV_CONFIG_CACHE_SYMLINKS FALSE
ENV RENV_PATHS_LIBRARY /srv/faucet/renv/library
# Copias los archivos necesarios para arrancar `renv`
COPY ./renv.lock .
COPY ./renv ./renv
COPY ./.Rprofile .
# Instalas los paquetes
RUN Rscript -e "renv::restore()"
# Copias los archivos de la aplicación/API; en este caso,
# reemplaza `app.R` con `plumber.R` si estás utilizando
# una Plumber API
COPY ./app.R .
# Puedes ejecutar el contenedor como un usuario no root
# por razones de seguridad, aunque esto no es necesario.
# Puedes ignorar esto
RUN chown -R faucet:faucet /srv/faucet/
USER faucet
Construir la imagen de Docker
Ahora que tienes un Dockerfile
y un archivo .dockerignore
, puedes construir la imagen de Docker con el siguiente comando:
docker build -t my_faucet_app .
Ejecutar la imagen de Docker
Una vez construida la imagen, puedes ejecutarla con el siguiente comando:
docker run --rm -p 3838:3838 my_faucet_app
Ahora puedes acceder a tu aplicación/API en http://localhost:3838
.
Controlar la instancia de faucet
Puedes controlar todos los aspectos de la instancia de faucet configurando
variables de entorno en el contenedor de Docker. Por ejemplo, si deseas cambiar
el número de trabajadores, puedes hacerlo configurando la variable de entorno
FAUCET_WORKERS
:
docker run --rm -p 3838:3838 -e FAUCET_WORKERS=4 my_faucet_app
Si estás ejecutando la aplicación/API detrás de un proxy como Nginx, puedes
configurar la variable de entorno FAUCET_IP_FROM
en x-real-ip
o x-forwarded-for
para asegurarte de que faucet obtenga la dirección IP
correcta del cliente.
docker run --rm -p 3838:3838 -e FAUCET_IP_FROM=x-real-ip my_faucet_app