Deploy
These are just some of the ways in which you can deploy an ambiorix application, and this is by no means an exhaustive list.
Docker
One of the easiest way to deploy an ambiorix app is by using docker + {renv} + docker compose.
Requirements:
- Install docker.
- Install docker compose.
- Bootstrap your project using
{renv}. Ideally, you only need to runrenv::init().
Create a file named
Dockerfileat the root directory of your project and add this to it:FROM rocker/r-ver:4.3.3 RUN apt-get update && apt-get install -y \ git-core \ libssl-dev WORKDIR /app COPY . . RUN rm -rdf renv/library RUN R -e "renv::restore()" EXPOSE 5000 CMD ["Rscript", "index.R"]Here are some simple explanations of what each line does:
FROM rocker/r-ver:4.3.3: Specifies the base Docker image with R 4.3.3. Change the R version to the one used in your project. eg.rocker/r-ver:4.4.2.RUN apt-get ...: Installs system dependencies required for many R packages. Add more as required. For example, the {magick} R package requireslibmagick++-devto be installed, so you’d have:RUN apt-get update && apt-get install -y \ git-core \ libssl-dev \ libmagick++-devWORKDIR /app: Sets the working directory inside the container to/app. All subsequent commands in the Dockerfile will run in this directory.COPY . .: Copies all files from your local project directory (on the host machine) to the/appdirectory inside the container.RUN rm -rdf renv/library: Clears the pre-existing library to ensure a clean restore of R packages.RUN R -e "renv::restore()": Runs that R expression which restores the package dependencies defined in yourrenv.lockfile.EXPOSE 5000: This is more of documentation to your future self that the container will use port 5000 to serve the application. This should be the same port you set ambiorix to run on ie.Ambiorix$new(port = 8000L)$...CMD [ "Rscript", "index.R" ]: This sets the default command to run when the container starts. Replaceindex.Rwith your app’s entry point if different. eg.server.R.
Build the docker image:
sudo docker build -t cute-cats .docker build: Command to build a Docker image.-t cute-cats: The-tflag tags/names the image ascute-cats..: The dot refers to the current directory, meaning Docker will look for theDockerfilein the current folder.
Create another file named
docker-compose.ymland place these contents in it:services: cute-cats: image: cute-cats ports: - "1028:5000" volumes: - ./data:/app/data restart: unless-stoppedservices: Defines the containers Docker Compose will manage. In this case, we only have one service calledcute-cats.image: cute-cats: Tell Docker Compose to use the image we built earlier, namedcute-cats.ports: Maps port 1028 on the host machine to port 5000 inside the container (where the ambiorix app is served, rememberEXPOSE 5000?). This means you can access the app atlocalhost:1028.volumes: Maps a folder on the host (./data) to the container’s/app/datadirectory. This ensures that data in the container is synced with the host and ensures data persistence if the container stops. You can remove thevolumesmapping if your app doesn’t need persistent data storage.restart: Ensures the container automatically restarts if it crashes, unless it has been manually stopped.
Run the services:
sudo docker compose up -d --remove-orphansdocker compose upcreates and starts the containers as defined in thedocker-compose.ymlfile.- The
-dflag runs the containers in detached mode ie. in the background. - The
--remove-orphansflag cleans up unused containers.
This will run the app on port 1028 of the host machine, so you will view it at localhost:1028.
To stop the services do:
sudo docker compose downThis stops and removes the containers but keeps the Docker images intact, so you can start them again later with
docker compose up.
Shiny Server
Surprise surprise! Yes, you can actually deploy Ambiorix apps & APIs using Shiny Server.
This is such good news because you can put your Ambiorix & Shiny apps in one directory and have Shiny Server serve all of them!
Two things to keep in mind:
- All your Ambiorix entrypoints will have to be named
app.R, you can’t just name the files anyhow (eg.index.R,server.R, etc) because Shiny Server will search forapp.R. - When building frontend applications using Ambiorix, you’d normally set the
hrefattributes of anchor tags to someting like/aboutor/contactto link to the different endpoints within the same app. However, when the app is hosted on Shiny Server at a URL likehttp://localhost:3838/app-name, using/aboutas the link will direct the browser tohttp://localhost:3838/about(outside your app), which isn’t what you intend. To fix this, you need to prepend the app name to thehrefvalues, likehref = "/app-name/about". This ensures that the links point the browser to the correct routes within your app.
Example deployment:
Before Shiny Server starts an R process, it sets the SHINY_PORT environment variable, which
tells the app which port to run on. In your Ambiorix app, you can retrieve this port using
Sys.getenv("SHINY_PORT").
Build your app. Say I have this
app.Rat/home/mwavu/projects/random:library(ambiorix) library(htmltools) home_get <- \(req, res) { html <- tags$h3("Yes, Ambiorix IN Shiny Server!") res$set_status(200L)$send(html) } home_post <- \(req, res) { response <- list( code = 200L, msg = "An API too!" ) res$set_status(200L)$json(response) } # get port to run app on from Shiny Server port <- Sys.getenv("SHINY_PORT") Ambiorix$ new(port = port)$ get("/", home_get)$ post("/", home_post)$ start()Configure Shiny Server to serve apps from the
/home/mwavu/projectsdirectory. Shiny Server configuration file is typically located at/etc/shiny-server/shiny-server.conf.run_as mwavu; # user under which Shiny Server runs server { listen 3838; # define a location at the base URL location / { # host the directory of ambiorix/shiny apps stored in this dir: site_dir /home/mwavu/projects; # log dir: log_dir /var/log/shiny-server; # ...other configs... } }Restart Shiny Server
systemctl restart shiny-server.serviceNow visit localhost:3838/random. Voila!
An Important Consideration:
While the open-source version of Shiny Server will work well for most users, some advanced functionality (such as managing the number of R processes, load balancing, etc.) will require Shiny Server Professional. In the long run, you’d benefit from learning how to implement these features independently, especially for more control & flexibility.
Shinyapps.io
You can use that same solution for deploying using Shiny Server to host your Ambiorix apps & APIs on shinyapps.io.
Good thing is now you won’t have to deal with any configurations. All you need to remember is to get the port to run the app on and the point I made on anchor tags (if building the frontend).
Using the same example app:
library(ambiorix) library(htmltools) home_get <- \(req, res) { html <- tags$h3("Ambiorix IN shinyapps.io!") res$set_status(200L)$send(html) } home_post <- \(req, res) { response <- list( code = 200L, msg = "An API too!" ) res$set_status(200L)$json(response) } # get port to run app on from Shiny Server port <- Sys.getenv("SHINY_PORT") Ambiorix$ new(port = port)$ get("/", home_get)$ post("/", home_post)$ start()Follow the same steps as for a shiny app: how to deploy to shinyapps.io.
See example live app running on shinyapps.io
Systemd Service
The application can be deployed as a service on any Linux server.
You might need to run these commands as sudo.
Create a new
.servicefile in the/etc/systemd/system/directory. The name of the file defines the name of the service. We will usecute-cats.serviceas an example:vim /etc/systemd/system/cute-cats.serviceIn that
.servicefile place the following configuration, it creates a service that runs the application at the defined path (/path/to/app).[Unit] Description=An Ambiorix app about the cutest of cats [Service] ExecStart=cd /path/to/app && /usr/bin/Rscript --no-save --slave -f app.R Restart=on-abnormal Type=simple [Install] WantedBy=multi-user.targetReload systemd to recognize the new service:
systemctl daemon-reloadStart the service and enable it to automatically start on boot:
systemctl start cute-cats systemctl enable cute-catsCheck the service status to ensure it’s running without any issues:
systemctl status cute-cats