How to fix '404 (Not Found)' errors when sourcing CSS and Javascript files in ShinyProxy - r

I am trying to launch a shiny app using ShinyProxy - something I have done many times before. However, this app is not correctly using any of the CSS or JS files that is required to make it run.
When I run the app manually with docker run -p 3838:3838 my_app everything works perfectly fine. However, when pointing ShinyProxy to the my_app image, the resulting app fails to load any CSS or JS files.
Dockerfile
FROM openanalytics/r-base
MAINTAINER Daniel Beachnau "DannyBeachnau#gmail.com"
# Dependencies outside of R
RUN apt-get update && apt-get install -y \
sudo \
gdebi-core \
pandoc \
pandoc-citeproc \
libcurl4-gnutls-dev \
libcairo2-dev \
libxt-dev \
xtail \
wget \
libpq-dev \
libmariadb-client-lgpl-dev \
# Might be needed for the archivist R-Library
dbus \
systemd \
# needed for odbc
unixodbc-dev
RUN apt-get install apt-transport-https curl -y
RUN curl http://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get update
RUN ACCEPT_EULA=Y apt-get install msodbcsql17 -y
# Download R-Packages
# tidyverse
RUN R -e "install.packages('tidyr')"
RUN R -e "install.packages('dplyr')"
RUN R -e "install.packages('readr')"
# Shiny Packages
RUN R -e "install.packages('shiny')"
RUN R -e "install.packages('shinycssloaders')"
RUN R -e "install.packages('shinydashboard')"
RUN R -e "install.packages('shinyWidgets')"
RUN R -e "install.packages('DT')"
RUN R -e "install.packages('shinyjs')"
RUN R -e "install.packages('flexdashboard')"
# Database Packages
RUN R -e "install.packages('odbc')"
RUN R -e "install.packages('RMySQL')"
# Other
RUN R -e "install.packages('devtools')"
RUN R -e "install.packages('lubridate')"
RUN R -e "install.packages('reshape2')"
RUN R -e "install.packages('grid')"
RUN R -e "install.packages('lemon')"
RUN R -e "install.packages('scales')"
RUN R -e "install.packages('ggthemes')"
RUN R -e "install.packages('ggplot2')"
RUN R -e "devtools::install_bitbucket(repo = 'my_repo/my_package', auth_user = 'my_username', password = 'my_password')"
# copy the app to the image
COPY . /root
# run the script to update the app data
WORKDIR /root
RUN Rscript app_data_update.R
WORKDIR /root/app
COPY Rprofile.site /usr/lib/R/etc/
EXPOSE 3838
CMD ["R", "-e", "shiny::runApp('/root/app', host='0.0.0.0', port=3838)"]
application.yml
shiny:
proxy:
title: ShinyProxy Server
logo-url: /images/logo-image.png
landing-page: /
heartbeat-rate: 10000
heartbeat-timeout: 60000
container-wait-time: 60000
port: 8080
authentication: ldap
# Docker configuration
docker:
cert-path: /home/none
url: http://localhost:2375
port-range-start: 20000
support:
container-log-path: ./container-logs
mail-to-address: DannyBeachnau#gmail.co,
- name: my_apps_name
display-name: Shiny App
docker-image: dbeachnau/my_app
groups: [Shiny Users Management]
logo-url: /images/logo-image.png
container-volumes: ["/path/to/app:/root/app"]
logging:
file:
shinyproxy.log
Here is how app looks in shiny proxy.
problem
Here is hoe my app looks when running manually.
desired
The console in chrome's inspect tool is replete with errors such as
GET https://myshinyserver.com/container_name/font-awesome-5.3.1/css/all.min.css net::ERR_ABORTED 404 (Not Found)
I do have other apps running on ShinyProxy which display properly, but I cannot solve the difference between how those apps are configured to how this app is configured. Let me know if additional details are required for diagnosing the issue. All feedback is appreciated - thank you.

You're probably seeing this with Shiny v1.3.0, and not with earlier versions. If so, it's probably because of a misconfiguration in your NGINX proxy directives. I've written up the details here, but I'll also post the salient details here.
proxy_set_header Connection "upgrade";
This directive causes NGINX to add a Connection: upgrade header to every HTTP request, when it's only supposed to be used for WebSockets.
This line is recommended by NGINX Inc. themselves, however, those recommendations are intended for proxying of traffic that is exclusively WebSockets, whereas Shiny traffic is a combination of normal HTTP requests and WebSockets. Older versions of shiny/httpuv didn't mind this situation, but the new versions are stricter.
A correct configuration looks something like this:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
location / {
proxy_pass http://localhost:3838;
proxy_redirect / $scheme://$http_host/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 20d;
proxy_buffering off;
}
}
}
See the articles linked in the RStudio Community post for other examples.

You will have to install the requested font at the top of your Dockerfile. You can add it to your list "Dependencies outside of R":
sudo apt-get install fonts-font-awesome

I have solved my problem, although, this still may not count as a sufficient answer or explanation, because I cannot account for why this solution makes a difference. I decided to rewrite the Dockerfile using a different base image which now works. Nothing else in my code changed - just the Dockerfile. The working docker file is as follows:
FROM rocker/shiny-verse
# based on debian 9
MAINTAINER Daniel Beachnau "DannyBeachnau#gmail.com"
# Dependencies outside of R
RUN apt-get update && apt-get install -y \
gnupg2 \
apt-utils \
sudo \
gdebi-core \
libxt-dev \
xtail \
wget
# Install ODBC driver from microsoft
RUN apt-get install apt-transport-https curl -y
RUN curl http://packages.microsoft.com/keys/microsoft.asc | apt-key add -
RUN curl https://packages.microsoft.com/config/debian/9/prod.list > /etc/apt/sources.list.d/mssql-release.list
RUN apt-get update
RUN ACCEPT_EULA=Y apt-get install msodbcsql17 -y
# Download R-Packages
# Shiny Packages
RUN R -e "install.packages('shinycssloaders')"
RUN R -e "install.packages('shinydashboard')"
RUN R -e "install.packages('shinyWidgets')"
RUN R -e "install.packages('DT')"
RUN R -e "install.packages('shinyjs')"
RUN R -e "install.packages('flexdashboard')"
# Database Packages
RUN R -e "install.packages('odbc')"
RUN R -e "install.packages('RMySQL')"
# Other
RUN R -e "install.packages('lubridate')"
RUN R -e "install.packages('reshape2')"
RUN R -e "install.packages('scales')"
RUN R -e "install.packages('ggthemes')"
RUN R -e "install.packages('ggplot2')"
RUN R -e "devtools::install_bitbucket(repo = 'my_repo', auth_user = 'my_username', password = 'my_password')"
# copy the app to the image
COPY . /root
# run the script to update the app data
WORKDIR /root
RUN Rscript app_data_update.R
WORKDIR /root/app
COPY Rprofile.site /usr/lib/R/etc/
EXPOSE 3838
CMD ["R", "-e", "shiny::runApp('/root/app', host='0.0.0.0', port=3838)"]
If anyone has insight to why this behavior is observed I would love to hear it because I am baffled to say the least.

why this solution makes a difference
It seems to be an issue with the Shiny version, changing the base image has very probably fixed that.
See Shiny apps not rendering after updated to v1.3.0

Related

How to call Dockerized R Plumber API from an external source?

I have created an R Plumber API, and deploy it in a Docker image.
Dockerfile:
ARG R_VERSION=latest
FROM rocker/r-ver:${R_VERSION}
# install the linux libraries needed for plumber
RUN apt-get update -qq && apt-get install -y \
libssl-dev \
libcurl4-gnutls-dev
COPY / /
# Making home & test folders
RUN Rscript required-packages/required-packages.R
# Giving permission to tests to run
RUN chmod +x tests/run_tests.sh
# Run Tests
RUN tests/run_tests.sh
# open port 7575 to traffic
EXPOSE 7575
# when the container starts, start the main.R script
ENTRYPOINT ["Rscript", "./main.R"]
main.R
library(plumber)
r <- plumb("./plumber.R")
r$run(port = 7575, host = "0.0.0.0")
I run the container with the following command.
docker run --rm -p 7575:7575 'container-name'
On the machine, http://localhost:7575/echo works perfectly fine. However, I cannot call the API from an external computer with http://ip_address:7575/echo.
What could be the problem? As far as I know, the 7575 port is open.

Making HTTPS requests within a Docker image behind a Zscaler firewall

I'm interested in running a simple image like this behind a corporate Zscaler firewall:
FROM rocker/r-base
RUN apt-get update && apt-get install libssl-dev
CMD Rscript -e "install.packages('beepr')"
Building the image with docker build -t test . fails with errors like this:
Certificate verification failed: The certificate is NOT trusted. The certificate issuer is unknown. Could not handshake: Error in the certificate verification. [IP: ]
I've tried some of the solutions from here but they don't work. For example:
FROM rocker/r-base
# Add local certificate to Docker
ADD ./zscaler.cer /usr/local/share/ca-certificates/zscaler.crt
# Move the certificate to the cert dir of openssl and update certificates
RUN CERT_DIR=$(openssl version -d | cut -f2 -d \")/certs ; cp /usr/local/share/ca-certificates/zscaler.crt $CERT_DIR ; update-ca-certificates
# Try making https requests
RUN apt-get update && apt-get install libssl-dev
CMD Rscript -e "install.packages('beepr')"
Same errors persist with docker build -t test .. I've read some possible solutions online but all of them continually fail either for apt-get or for installing packages with R. Is there anyone who has experienced this and found a fix?
Apparently, the current advice is slightly wrong. The certificate should not go in /etc/ssl/certs/ (which is the result of CERT_DIR=$(openssl version -d | cut -f2 -d \")/certs) but rather on CERT_DIR=/usr/local/share/ca-certificates/ (at least on this Ubuntu image). After changing that, update-ca-certificates correctly updates the certificate an all HTTPS requests are successful.
This should work now:
FROM rocker/r-base
# Add local certificate to Docker
ADD ./zscaler.pem /usr/local/share/ca-certificates/ZscalerRootCertificate-2048-SHA256.crt
# update certificates
RUN update-ca-certificates
# Try making https requests
RUN apt-get update && apt-get install libssl-dev
CMD Rscript -e "install.packages('beepr')"

Shiny app does not appear when deployed using Shinyproxy

I'm trying to learn how to deploy a shiny app using Shinyproxy, and I'm using the templated "euler app" (from this repo), but the application does not appear when I navigate to http://localhost:4445. Here's the most similar question I could find, but unfortunately not helpful to my issue: link.
Background
All installations seem fine, and I successfully installed Docker and Java.
The Dockerfile and Docker image work locally, no issues there. The command docker run --rm -p 3838:3838 shiny-euler-app works.
Here is my Dockerfile (copied from the repo):
FROM openanalytics/r-base
MAINTAINER Tobias Verbeke "tobias.verbeke#openanalytics.eu"
# system libraries of general use
RUN apt-get update && apt-get install -y \
sudo \
pandoc \
pandoc-citeproc \
libcurl4-gnutls-dev \
libcairo2-dev \
libxt-dev \
libssl-dev \
libssh2-1-dev \
libssl1.1
# system library dependency for the euler app
RUN apt-get update && apt-get install -y \
libmpfr-dev
# basic shiny functionality
RUN R -e "install.packages(c('shiny', 'rmarkdown'), repos='https://cloud.r-project.org/')"
# install dependencies of the euler app
RUN R -e "install.packages('Rmpfr', repos='https://cloud.r-project.org/')"
# copy the app to the image
RUN mkdir /root/euler
COPY euler /root/euler
COPY Rprofile.site /usr/lib/R/etc/
EXPOSE 3838
CMD ["R", "-e", "shiny::runApp('/root/euler')"]
As well, Shinyproxy works fine with the default openanalytics/shinyproxy-demo Docker image, as you can see:
Problem
The issue I have is when I try and supply a different Shiny app and its accompanying application.yml. Here is the application.yml file I'm using (I've tried to make it as basic as possible, with no authentication, etc):
proxy:
title: Standalone Docker Engine
port: 4445
authentication: none
docker:
url: http://localhost:2375
specs:
- id: euler
display-name: Euler's number
container-cmd: ["R", "-e", "shiny::runApp('/root/euler')"]
container-image: shiny-euler-app
Unfortunately, when I run java -jar shinyproxy-2.4.2.jar (in the directory which contains the shinyproxy-2.4.2.jar file and the application.yml file) I get this blank webpage:
For some reason, I am able to access the Shinyproxy webpage, but the Dockerized Shiny app does not appear.
Would really appreciate any helpful suggestions on where/how I could try and solve this issue. Thanks!

How to force a shiny app ran in Docker to use https

I am trying to run a shiny application on an open port on my server. I usually run docker images using command docker run -p 4000:3838 tag_name, assuming that docker container has exposed port, and shiny app is running at this port.
This all works completely fine for any shiny application that is using http. But I need https.
So the Dockerfile I use consists of:
FROM rocker/r-ver:4.0.1
# System libs:
RUN apt-get update
RUN apt-get install -y libcurl4-openssl-dev
RUN apt-get install -y libssl-dev
RUN apt-get install -y zlib1g-dev
RUN apt-get install -y libxml2-dev
# R packages installed
RUN R -e "install.packages('remotes')"
RUN R -e "remotes::install_version('searchConsoleR')"
RUN R -e "remotes::install_version('googleAuthR')"
# [...] more R libraries are installed
# Copy application files to a dir
RUN mkdir /root/app
COPY . /root/app
# Expose and set run command from dir above
EXPOSE 3838
CMD ["R", "-e", "shiny::runApp('/root/app', port = 3838, host = '0.0.0.0')"]
Then I execute docker build -t tag_name . and docker run -p 4000:3838 tag_name.
The page is available at http://server.host:4000
However, since I am using Google Login, I need to use https. But when I visit server's https://server.host:4000 I see an error of page not existing.
Can someone please help?

Application logs to stdout with Shiny Server and Docker

I have a Docker container running a shiny app (Dockerfile here).
Shiny server logs are output to stdout and application logs are written to /var/log/shiny-server. I'm deploying this container to AWS Fargate and logging applications only display stdout which makes debugging an application when deployed challenging. I'd like to write the application logs to stdout.
I've tried a number of potential solutions:
I've tried the solution provided here, but have had no luck.. I added the exec xtail /var/log/shiny-server/ to my shiny-server.sh as the last line in the file. App logs are not written to stdout
I noticed that writing application logs to stdout is now the default behavior in rocker/shiny, but as I'm using rocker/verse:3.6.2 (upgraded from 3.6.0 today) along with RUN export ADD=shiny, I don't think this is standard behavior for the rocker/verse:3.6.2 container with Shiny add-on. As a result, I don't get the default behavior out of the box.
This issue on github suggests an alternative method of forcing application logging to stdout by way of an environment variable SHINY_LOG_STDERR=1 set at runtime but I'm not Linux-savvy enough to know where that env variable needs to be set to be effective. I found this documentation from Shiny Server v1.5.13 which gave suggestions in which file to set the environment variable depending on Linux distro; however, the output from my container when I run cat /etc/os-release is:
which doesn't really line up with any of the distributions in the Shiny Server documentation, thus making the documentation unhelpful.
I tried adding adding the environment variable from the github issue above in the docker run command, i.e.,
docker run --rm -e SHINY_LOG_STDERR=1 -p 3838:3838 [my image]
as well as
docker run --rm -e APPLICATION_LOGS_TO_STDOUT=true -p 3838:3838 [my image]
and am still not getting the logs to stdout.
I must be missing something here. Can someone help me identify how to successfully get application logs to stdout successfully?
You can add the line ENV SHINY_LOG_STDERR=1 to your Dockerfile (at least, this works with rocker/shiny, not sure about rocker/verse), such as with your Dockerfile:
FROM rocker/verse:3.6.2
## Add shiny capabilities to container
RUN export ADD=shiny && bash /etc/cont-init.d/add
## Install curl and xtail
RUN apt-get update && apt-get install -y \
curl \
xtail
## Add pip3 and other Python packages
RUN sudo apt-get update -y && apt-get install -y python3-pip
RUN pip3 install boto3
## Add R packages
RUN R -e "install.packages(c('shiny', 'tidyverse', 'tidyselect', 'knitr', 'rmarkdown', 'jsonlite', 'odbc', 'dbplyr', 'RMySQL', 'DBI', 'pander', 'sciplot', 'lubridate', 'zoo', 'stringr', 'stringi', 'openxlsx', 'promises', 'future', 'scales', 'ggplot2', 'zip', 'Cairo', 'tinytex', 'reticulate'), repos = 'https://cran.rstudio.com/')"
## Update and install
RUN tlmgr update --self --all
RUN tlmgr install ms
RUN tlmgr install beamer
RUN tlmgr install pgf
#Copy app dir and theme dirs to their respective locations
COPY iarr /srv/shiny-server/iarr
COPY iarr/reports/interim_annual_report/theme/SwCustom /opt/TinyTeX/texmf-dist/tex/latex/beamer/
#Force texlive to find my custom beamer theme
RUN texhash
EXPOSE 3838
## Add shiny-server information
COPY shiny-server.sh /usr/bin/shiny-server.sh
COPY shiny-customized.config /etc/shiny-server/shiny-server.conf
## Add dos2unix to eliminate Win-style line-endings and run
RUN apt-get update -y && apt-get install -y dos2unix
RUN dos2unix /usr/bin/shiny-server.sh && apt-get --purge remove -y dos2unix && rm -rf /var/lib/apt/lists/*
# Enable Logging from stdout
ENV SHINY_LOG_STDERR=1
RUN ["chmod", "+x", "/usr/bin/shiny-server.sh"]
CMD ["/usr/bin/shiny-server.sh"]

Resources