Deploy your website using Golem / Shiny & Docker on NAS Synology
In this story I explain how to deploy a Shiny interface on your NAS Synology using the R programming language package ‘Golem’ and Docker.
Prerequisites for this story:
- Have some bases in the R programming language, specially how develop a web Shiny interface.
- Have some notion of what is Docker (despite I explain some vocabulary around Docker).
- Have Docker installed on your Computer (where is your RStudio)
- Have your own NAS, especially a Synology for Reverse proxy configuration, neverless with other brands the process should be very similar.
Introduction
Shiny is an R package that makes it easy to build interactive website from R programming language. The code is globally divided into 2 parts for each modules: UI part (visual aspect) and SERVER part (calculation, navigation, action on buttons, …), plus the functions developed and used in the project. Shiny makes it possible to make very complete web interfaces whether for reporting interfaces, data visualization, cartographic representations or even more classic websites or IS interfaces.( https://shiny.rstudio.com/)
To facilitate the deployment and the conception of a Shiny application I use the Golem R package developed by ThinkR (https://thinkr.fr/introduction-au-package-golem-en-video/) . It is a framework for developing Shiny applications especially.
Docker is a relatively recent free software (2013), acclaimed for its “simplicity” and its efficiency. It is a virtualization tool that allows to deploy applications in a less cumbersome and burdensome way than using and mounting a virtual machines.
“ Docker is a tool that can package an application and its dependencies into an isolated container, which can be run on any server.”. Wikipedia
A NAS (Network Attached Storage) is a network-attached device that can store your exponentially growing data, whether at home or in your business. Synology is a particular brand of NAS.
Shiny interface with golem
I am not explaining how to develop a website using the programming language R and the R package Shiny, neither how to use the R package Golem. There are some good websites for this, such as:
- https://shiny.rstudio.com/articles/build.html
- https://shiny.rstudio.com/tutorial/
- https://thinkr.fr/introduction-au-package-golem-en-video/
- https://engineering-shiny.org/golem.html
I quickly explain and introduce how to install golem, how to create a golem project and what rules to follow to export and deploy your Shiny interface.
Install golem (R package) and create golem project
- Execute the following line in your RStudio Console and restart your RStudio. If you already have golem install, make sure that your version is higher than 3.0. At the time of writing this story, the latest version is 3.3. I advise you to have the latest version (3.3), as it is more reliable to create the Docker Image of our project.
install.packages("golem")
- Create a project and select “Package for Shiny App using golem”. It will initialize your project.
If you do not know golem I advise you to refer to the sites mentioned at the beginning of this part.
Rules to follow before exporting and deploying your website
When developing an interface with Shiny, to be able to deploy it, your code must respect certain standards and certain rules in the design of your website. If you have already developed R packages it is the same rules.
These include the following rules:
- Do not use non-ASCII characters in your code, such as accents for French, and replace these characters with their uni-code (example é will be replaced by \u00e9).
- Declare the parameters of the functions you create in your project.
- Declare the R packages necessary for the operation of your program. Declare them in the app_ui.R file. R in particular and with the functions of the file dev. R golem project.
#’ The application User-Interface
#’
#’ @param request Internal parameter for `{shiny}`.
#’ DO NOT REMOVE.
#’ @import shiny
#’ @import bslib
#’ @import shinybusy
#’ @import shiny.i18n
# @import googleLanguageR
#’ @import shinyjs
#’ @import DBI
#’ @import dplyr
#’ @import RPostgres
#’
#’
#’ @noRd
app_ui <- function(request) {
Those lines of code will feed the NAMESPACE file when you run run_dev. R (code lines in app_ui.R file).
usethis::use_package(“bslib”)
usethis::use_package(“shinybusy”)
usethis::use_package(“shinydisconnect”)
usethis::use_package(“shiny.i18n”)
usethis::use_package(“shinyjs”)
usethis::use_package(“shinydisconnect”)
usethis::use_package(“DBI”)
usethis::use_package(“dplyr”)
usethis::use_package(“RPostgres”)
Run its lines and you will feed the DESCRIPTION file (code line in dev.R file).
Properly describe all the packages that you use and needed to run your site even more with Docker because your Image Docker will only compose packages filled with its 2 files (NAMESPACE and DESCRIPTION) So if you miss a package your application will not work.
RStudio offers a great tool to test and verify your code on its rules and writing standards.
- Click on the “Build” tab at the top right of RStudio and make a “Check” if you have 0 errors and as few warnings as possible your Shiny application can be dockerized.
In case you have errors and warnings this tool makes explicit the rules that have not been complied with and so you can correct them.
Some warnings will not block the deployment of your website, you should still have as few as possible.
Build the Docker Image of your web site
Vocabulary and principles of Docker
Docker is an open platform for application development, shipping and execution. Docker is a virtualization tool that allows you to separate your applications from your infrastructure so you can deliver software quickly, without all the constraints of using and setting up virtual machines. With Docker, you can manage your infrastructure the same way you manage your applications.
Docker objects :
Dockerfile is a text file that corresponds to the list of instructions (to the «recipe») that allow to build a Docker image.
“A Docker Image is a read-only template with instructions for creating a Docker container. Often, an image is based on another image, with some additional customization. For example, you may build an image which is based on the ubuntu image, but installs the Apache web server and your application, as well as the configuration details needed to make your application run.”
“A Docker Container is a runnable instance of an image. You can create, start, stop, move, or delete a container using the Docker API or CLI. You can connect a container to one or more networks, attach storage to it, or even create a new image based on its current state. By default, a container is relatively well isolated from other containers and its host machine. You can control how isolated a container’s network, storage, or other underlying subsystems are from other containers or from the host machine.”
Build your Docker Image with golem
With golem v3.3 :
- Run the command below in the RStudio console to dockerize your project. This command will create a “deploy” folder containing a Dockerfile_base, a Dockerfile, a renv.lock.prod file, your packaged Shiny project and a READ ME in which you will find the sequence of commands to be executed in Docker.
golem::add_dockerfile_with_renv_shinyproxy(output_dir = "deploy")
The actions on RStudio end there we will no longer use RStudio except to update our Shiny application (the project compressed in .tar.gz) and thus this deploy folder.
In Docker on your computer :
- Go to the folder “deploy” on your project.
- Execute the 2 first commands on the README file 1 by 1, to build the my_project_base Image and after to build your project Image.
And now your project Image is build on your computer.
With golem under v3.3 and over v3.0 :
- Run the command below in the RStudio console to dockerize your project. This command will create a Dockerfile file.
golem::add_dockerfile(sysreqs = FALSE,update_tar_gz = T, build_golem_from_source = F)
The actions on RStudio end there we will no longer use RStudio except to update our Shiny application (the project compressed in .tar.gz) and thus this Dockerfile file.
In Docker on your computer :
- Go to the folder deploy on your project.
- Execute the following line to build your Image with the Dockerfile.
docker build -t my_image_web .
In this example, the name of the Docker Image is ‘my_image_web’ and the ‘.’ is really important, it sais to use the Dockerfile ‘in the folder that your are’.
It is possible that by using this golem function does not create a complete Dockerfile to build your Image Docker and it is possible that it falls into error. In this case you have to observe the logs after the launch of the above command to see what is missing. This is often a lack of linux libraries or a lack of installation of package R (bad links between dependencies) or an installation in the wrong order of R packages.
It is for these reasons that I recommend using the version of golem 3.3 as it is more reliable on these steps of creating your Docker Image.
Export your Image to Docker Hub
- Create an account on Docker Hub.
For the rest of this story, we will take into account that my Docker Hub account is julienmilon and that the name of my Image is docker101tutorial and the version is 0.0.1 (we can also put lastest otherwise). Your Docker Hub account URL will be https://hub.docker.com/u/julienmilon .
- Execute the following commands.
docker tag docker101tutorial julienmilon/docker101tutorial:0.0.1
docker push julienmilon/docker101tutorial:0.0.1
Your project will be created and available at the following URL https://hub.docker.com/r/julienmilon/docker101tutorial
More generally :
docker tag my_image_web my_account_dockerhud/my_image_web:0.0.1
docker push my_account_dockerhub/my_image_web:0.0.1
Global URL https://hub.docker.com/r/my_account_dockerhub/my_image_web
Deploy your Docker Image (Image of your site) on your NAS Synology
Import your Image in Docker on your NAS Synology
To import a Docker Image from Docker Hub :
- Copy the URL of your Image in Docker Hub (example : https://registry.hub.docker.com/r/julienmilon/docker101tutorial).
- Open Docker on your NAS Synology.
- Click on Image.
- Click on Add.
- Select Add from URL.
Paste the URL of your Image in Docker Hub in the window. If your project is public your can Click on Add, if it’s private your have to use the user Name and create an access token on Docker Hub (https://docs.docker.com/docker-hub/access-tokens/).
If your Image on Docker Hub is private and you are having authentication problems importing your Image, I advise you to make it public while importing it and then to make it private.
Now your Image is in Docker on your NAS Sylology and your can create a container with the Image you just imported.
Run a container with your Image
- Double click on the Image you Imported.
- Select “Use the same network than Docker Host”.
- Click Next.
- Name your container.
- Select “Enable automatic restart”.
- If your Image need specific parameters you can click on Advanced parameters and add them. Optional
- Click Next
- If your website write some file locally you would like to save it in your Synology Files, so you can give Docker containers access to some folders. Optional
- Execute to run your Image in a container
- Go to Container to see if your container is still running.
If it is not the case, stop your container, double click on it and click on Journal to see logs and errors.
Then correct your code and rebuild your Image and the previous Steps.
If your container is running, you still have to open access from the outside to your Docker container thanks to a Reverse Proxy.
Configure your Reverse Proxy to open access to your website
- Go to Control Panel — Login portal — Advanced
- Click on Reverse Proxy
- Click on Create
- Fill the window such the example abrove :
- Name the reverse proxy as you want
- Sources is to define the URL of your website. Beforehand you must have a domain, must have define a DNS with your domain provider (Such OVH or other) that point to your public IP and have a certificate if you want to have https URL (or you can do it after).
- Activate HSTS
- Destination is to point to your Docker container. If you did not change the port on the Dockerfile or when you have created your container the default port of Shiny is 3838
- Don’t save now because you need to enable Websocket so that the server part of your interface Shiny can run
- Select Custom header (or “En-tête personnalisé” ) and then Create and Select Websocket.
- You can now save and test your web site with the URL that you choose.
There is an example of a test website and project in progress that I made in Shiny / Golem and deploy on my NAS Synology with Docker. Running during the day at French time.
Multiple website on your NAS Synology
In case you want to develop and deploy multiple websites on your NAS you can use the same method, just need to deploy your Docker Image on another port. Often other than port 3838 which is the default port. To replace 3838 in the last 2 lines of the Dockerfile file in the “deploy” folder of your Golem project by other port such 3839.
Or you could also use Shinyproxy
You can also use Shinyproxy
ShinyProxy is a way to deploy Shiny apps in an enterprise context. It has built-in functionality for LDAP authentication and authorization, makes securing Shiny traffic (over TLS) a breeze and has no limits on concurrent usage of a Shiny app (https://www.shinyproxy.io/).
The use of Shinyproxy is not developed in this story, but you will need all the previous steps. Using Shinyproxy will add a step after building your Docker Image. You will build the Shinyproxy Docker Image that will use the Docker Image you built (the Docker Image of your website). You will then deploy this Docker Image of your Shinyproxy on your NAS in the same way as in this story.
NB : In a next article I will explain how to create a PostgreSQL Database in a Docker container on your NAS Synology for those you would like to connect their web site to a database (for user data table, log data table or any reason)