I wanted to test a time-intensive shiny app, so I created a shiny test application that will build a large model linear model when I clicked on a button. I wanted to test this out with two separate users using the app at the same time (Alice and Bob in two different browsers); however, when this happens, one of the apps crashes. The crash does not happen if only one user is on the app.
Is this just a specific memory problem or is there something that I can do to combat this?
I followed this page while building the ShinyProxy architecture:
The files for ShinyProxy and the model application are below:
File Structure:
ShinyProxy
---application.yml
---Dockerfile
---Model_App
------ Dockerfile
------ shiny-server.sh
------ app.R
ShinyProxy Dockerfile:
FROM openjdk:11-jre
RUN mkdir -p /opt/shinyproxy/
RUN wget https://www.shinyproxy.io/downloads/shinyproxy-2.4.0.jar -O /opt/shinyproxy/shinyproxy.jar
RUN touch /opt/shinyproxy/shinyproxy.log
COPY application.yml /opt/shinyproxy/application.yml
WORKDIR /opt/shinyproxy/
CMD ["java", "-jar", "/opt/shinyproxy/shinyproxy.jar"]
ShinyProxy application.yml:
proxy:
container-log-path: ./container-logs
heartbeat-timeout: 60000
port: 9090
authentication: simple
admin-groups: admins
users:
- name: alice
password: alice
groups: admins
- name: bob
password: bob
docker:
internal-networking: true
specs:
- id: model
display-name: Model
description: Model Build - R Shiny App to test concurrency issues
container-cmd: []
container-image: shiny-model
container-network: sp-test-net
logging:
file:
shinyproxy.log
Model app.R:
library(shiny)
ui <- fluidPage(
titlePanel("Model Run"),
sidebarLayout(
sidebarPanel(
actionButton("btn", "Run Model"),
br()
),
mainPanel(
textOutput("text_time")
)
)
)
server <- function(input, output) {
txt = eventReactive(input$btn, {
start = proc.time()
progress <- shiny::Progress$new()
on.exit(progress$close())
progress$set(message = "Building model", value = 0.1)
practice_df = data.frame(
x1 = rnorm(10000000, 5, 2),
x2 = rnorm(10000000, 10, 3),
x3 = rnorm(10000000, 16, 2),
x4 = rnorm(10000000, 12, 3),
x5 = rnorm(10000000, 12, 3),
x6 = rnorm(10000000, 12, 3),
y = rnorm(10000000, 5, 2.5)
)
progress$inc(0.5)
mod = lm(y ~ x1 + x2 + x3 + x4 + x5 + x6, data = practice_df)
progress$inc(0.4)
seconds = round(as.numeric(proc.time() - start)[3], 1)
print(paste("Took", seconds, "seconds to run the model."))
})
output$text_time <- renderText({
txt()
})
}
shinyApp(ui = ui, server = server)
Model shiny-server.sh
#!/bin/sh
# Make sure the directory for individual app logs exists
mkdir -p /var/log/shiny-server
chown shiny.shiny /var/log/shiny-server
if [ "$APPLICATION_LOGS_TO_STDOUT" != "false" ];
then
# push the "real" application logs to stdout with xtail in detached mode
exec xtail /var/log/shiny-server/ &
fi
# start shiny server
exec shiny-server 2>&1
Model Dockerfile:
FROM rocker/shiny-verse:latest
# copy the app to the image
COPY *.Rproj /srv/shiny-server/
COPY *.R /srv/shiny-server/
COPY data /srv/shiny-server/data
# select port
EXPOSE 3838
# allow permission
RUN sudo chown -R shiny:shiny /srv/shiny-server
# Copy further configuration files into the Docker image
COPY shiny-server.sh /usr/bin/shiny-server.sh
RUN ["chmod", "+x", "/usr/bin/shiny-server.sh"]
# run app
CMD ["/usr/bin/shiny-server.sh"]
Commands used to build/run application:
docker build -t shinyproxy-run .
docker network create sp-test-net
cd Model_App
docker build -t shiny-model .
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock --net sp-test-net -p 9090:9090 shinyproxy-run