Docker provides a streamlined way to deploy R Shiny applications by encapsulating dependencies, configurations, and execution environments into a container. The write_docker() function automates the process of generating a Dockerfile tailored for a Shiny application. This article walks through its implementation and usage.
The write_docker() function dynamically generates a Dockerfile for a Shiny application by:
Extracting dependencies from the project using renv::dependencies('.').
Filtering out unnecessary or excluded packages.
Creating a Docker image based on the Rocker Shiny image.
Copying necessary project files into the container.
Setting up the port exposure and execution command.
# Required Libraries
library(readr)
library(glue)
write_docker <- function(port, install_pack = '#', packages = unique(renv::dependencies('.')$Package),
Rversion = strsplit(version[['version.string']], ' ')[[1]][3],
packages_ignore = c('surveycto','fireData') ) {
packages_to_install <- unique(renv::dependencies('.')$Package)[!unique(renv::dependencies('.')$Package) %in% c(packages_ignore)]
# Initialize Dockerfile commands
shiny_files <- c()
Rversion_ed <- Rversion
# Define the base Shiny image
shiny_files[1] <- paste('FROM rocker/shiny:',Rversion_ed, sep ='')
# Install required packages
shiny_files[2] <- paste(install_pack,'RUN R -e "install.packages(c(',paste0("'",
paste(paste(packages_to_install, collapse="', '"),
collapse="','"), "'"), collapse = "", "",'), dependencies = TRUE)"',sep = "")
# Create directory for the Shiny app
shiny_files[3] <- 'RUN mkdir /home/shiny-app'
# Copy all necessary files except ignored ones
i <- 4
for (file in c(list.files(all.files = TRUE))) {
if (!grepl('.Rhistory|.Rprofile|.Rproj.user|.Rproj|Dockerfile', file) & file != '.' & file != '..') {
shiny_files[i] <- paste('COPY ',file, ' /home/shiny-app/',file, sep = '')
i <- i+1
}
}
# Set port exposure and run command
shiny_files[i] <- glue::glue("EXPOSE {port}")
shiny_files[i+1] <- paste('CMD ["R", "-e", "shiny::runApp(','\'/home/shiny-app',', "host = '0.0.0.0', port = ",port,')"]', sep = '')
# Write the Dockerfile
readr::write_lines(shiny_files, file = file.path("Dockerfile"))
}
Run the function to create a Dockerfile for a Shiny app:
write_docker(port = 1200, install_pack = '')
This will generate a Dockerfile with the appropriate dependencies, directory structure, and startup commands.
Once the Dockerfile is created, build the Docker image using:
docker build -t shiny-docker-demo .
Start the Shiny app inside the container by running:
docker run -p 8180:1200 shiny-docker-demo
This maps the container's port 1200 to the host machine's port 8180, making the Shiny app accessible in a web browser.
A Dockerfile is automatically created, ensuring reproducibility.
The Shiny app runs in an isolated environment with all dependencies pre-installed.
The containerized app is accessible via a specified port without the need for manual configuration.
By leveraging write_docker(), users can simplify the deployment process of Shiny applications, ensuring consistency across different environments. 🚀🛳️