Search code examples
rdockershinydocker-volume

How to write to docker volume inside shiny app?


Here is the project directory:

❯ tree ../write-to-volume-from-shiny
../write-to-volume-from-shiny
├── app.R
├── Dockerfile
└── shiny-server.conf

The Dockerfile:

FROM rocker/shiny:4.3.1
RUN rm /srv/shiny-server/index.html /etc/shiny-server/shiny-server.conf
COPY app.R /srv/shiny-server
COPY shiny-server.conf /etc/shiny-server/
RUN chmod -R 755 /srv/shiny-server/
EXPOSE 80
CMD ["/usr/bin/shiny-server"] 

The app file:

library(shiny)

ui <- fluidPage(
  actionButton("touch", "Touch file"),
  textOutput("out")
)

server <- function(input, output, session) {
  observeEvent(input$touch, {
    if (fs::dir_exists("/data")) {
      fs::file_touch("/data/touch-test")
      // Error here because of shiny user
      // trying to write to root owned /data
    }
  })
}

shinyApp(ui, server)

Shiny server conf:

run_as shiny;

server {
  listen 80;
  location / {
    site_dir /srv/shiny-server;
    log_dir /var/log/shiny-server;
    directory_index on;
  }
}


Set up the volume

docker volume create --name write-test

Run the app

docker buildx build . -t write
docker run --mount source=write-test,target=/data -p 80:80 write

Use the app

Go to 127.0.0.1:80

click on button produces an error which I guess happens because shiny user is trying to write to root owned /data

What is the workaround here?


Solution

  • Thanks to this answer (took me hours to find it), I have managed to modify Dockerfile and make it work:

    The line RUN mkdir /data && chown shiny:shiny /data is the key:

    FROM rocker/shiny:4.3.1
    RUN rm /srv/shiny-server/index.html /etc/shiny-server/shiny-server.conf
    COPY app.R /srv/shiny-server
    COPY shiny-server.conf /etc/shiny-server/
    RUN chmod -R 755 /srv/shiny-server/
    RUN mkdir /data && chown shiny:shiny /data
    EXPOSE 80
    CMD ["/usr/bin/shiny-server"]