如何在Docker容器中运行R Shiny应用程序

6
我为一个R Shiny应用程序构建了一个Docker镜像,并在Windows 10 Home上使用Docker Toolbox运行了相应的容器。当试图使用我的Web浏览器打开应用程序时,仅显示索引。我不知道为什么应用程序没有执行。日志向我展示了以下信息:
*** warning - no files are being watched ***
[2019-08-12T15:34:42.688] [INFO] shiny-server - Shiny Server v1.5.12.1 (Node.js v10.15.3)
[2019-08-12T15:34:42.704] [INFO] shiny-server - Using config file "/etc/shiny-server/shiny-server.conf"
[2019-08-12T15:34:43.100] [INFO] shiny-server - Starting listener on http://[::]:3838

我已经通过执行以下命令指定了应用主机到容器的路径,该命令引用了一个 Docker Hub 镜像:

docker run --rm -p 3838:3838 -v /C/Docker/App/:/srv/shinyserver/ -v /C/Docker/shinylog:/var/log/shiny-server/  didsh123/ps_app:heatmap

我的Docker文件如下所示:
# get shiny serves plus tidyverse packages image
FROM rocker/shiny-verse:latest

# 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

##Install R packages that are required--> were already succesfull
RUN R -e "install.packages(c('shinydashboard','shiny', 'plotly', 'dplyr', 'magrittr'))"

#Heatmap related packages
RUN R -e "install.packages('gpclib', type='source')"
RUN R -e "install.packages('rgeos', type='source')"
RUN R -e "install.packages('rgdal', type='source')"

# copy app to image
COPY ./App /srv/shiny-server/App

# add .conf file to image/container to preserve log file
COPY ./shiny-server.conf  /etc/shiny-server/shiny-server.conf


##When run image and create a container, this container will listen on port 3838
EXPOSE 3838

###Avoiding running as root --> run container as user instead
# allow permission
RUN sudo chown -R shiny:shiny /srv/shiny-server
# execute in the following as user --> imortant to give permission before that step
USER shiny

##run app
CMD ["/usr/bin/shiny-server.sh"]

当我在浏览器中输入docker IP地址和端口号时,应该能够运行应用程序,但是只有主页显示出来。我使用以下语句:

http://192.168.99.100:3838/App/

我很高兴能得到任何提示或建议。因为我是 Docker 的新手,所以非常需要详细的解释。

3个回答

8
为了在docker中使用shiny,我建议您使用golem包。golem提供了一个构建shiny应用程序的框架。如果您已经按照他们的框架开发了一个应用程序,函数golem::add_dockerfile()可以自动创建dockerfiles。
如果您对框架不感兴趣,仍然可以查看add_dockerfile()的源代码,以了解他们如何管理部署。他们的策略是使用带有端口参数的shiny::runApp()。因此,在这种情况下,shiny-server是不必要的。
golem中的Dockerfile大致如下:
FROM rocker/tidyverse:3.6.1
RUN R -e 'install.packages("shiny")'
COPY app.R /app.R
EXPOSE 3838
CMD R -e 'shiny::runApp("app.R", port = 3838, host = "0.0.0.0")'

这将使应用程序在端口3838上可用。当然,您还需要安装任何其他的R包和系统依赖项。

额外提示

  • 为了增加可重复性,我建议您使用remotes::install_version()而不是install.packages()
  • 如果您要部署几个具有类似依赖项的应用程序(例如shinydashboard),那么编写自己的基础镜像以替代rocker/tidyverse:3.6.1是有意义的。这样,您的构建速度会更快。

3

最小可复现示例

  1. 创建一个空目录(可以随意命名)

  2. 在其中创建两个内容:

    i. 一个名为 Dockerfile 的文件

    ii. 一个名为 app 的空目录

  3. 将您的闪亮应用程序放置在名为 app 的目录中。

    • 您的闪亮应用程序可以是单个 app.R 文件,或者对于旧的闪亮应用程序,可以是 ui.Rserver.R。任何一种方式都可以(有关更多信息,请参见此处)。
  • 如果对上述任何内容不确定,请只需复制此处找到的文件即可。

将此放入 Dockerfile 中

FROM rocker/shiny:latest

COPY ./app/* /srv/shiny-server/

CMD ["/usr/bin/shiny-server"]

在终端中,cd到你在步骤1中创建的空目录的根目录,并使用以下命令构建镜像。
docker build -t shinyimage . 

使用以下命令运行容器:

docker run -p 3838:3838 shinyimage

最后,访问这个URL以查看您的Shiny应用程序:http://localhost:3838/

这里提供了以上所有内容的副本,以防有任何不清楚的地方。

输入图片说明


0

检查日志是否有任何有用的信息?并进入容器以验证应用程序内容是否已复制到正确位置。

因为/App内容复制的方式看起来不正确

在构建阶段,将/App的内容复制到镜像中的/srv/shiny-server/App中,并且您正在尝试使用-v选项覆盖/srv/shiny-server的内容。

似乎在运行时复制的App数据被覆盖了。

尝试不使用-v /C/Docker/App/:/srv/shinyserver/或使用-v /C/Docker/App/:/srv/shinyserver/App/

docker run --rm -p 3838:3838 -v /C/Docker/shinylog:/var/log/shiny-server/ didsh123/ps_app:heatmap


感谢您对/App内容的建议。我已经修复了这个问题。但由于我是Docker的新手,我还没有处理过日志文件。我在上面的问题中附上了执行日志命令时收到的行。您能否也看一下它们?此外,我按照您的建议执行了容器,它运行正常。 - Heysa12
@Heysa12 很高兴知道它起作用了。根据日志,该应用程序正在使用配置文件/etc/shiny-server/shiny-server.conf,但是当您复制COPY ./shiny-server.conf.txt /etc/shiny-server/时,会复制.txt文件。这意味着您的应用程序正在使用默认配置,而不是您复制到镜像中的文件。 - Avinash Reddy
你还可以在dockerfile中添加 USER appuser 以减轻日志中的安全风险警告。参考:https://medium.com/@mccode/processes-in-containers-should-not-run-as-root-2feae3f0df3b - Avinash Reddy
容器不再以root身份运行,而是以用户身份运行(请参见问题中的编辑)。所以这个问题已经解决了,但仍然存在同样的问题。这可能与配置文件有关吗?在docker文件中,将我的自定义配置文件从相关的github存储库复制到默认的配置文件之外,应该使用什么正确的命令? - Heysa12
@Heysa12 - 使用此命令 COPY ./shiny-server.conf /etc/shiny-server/。您正在尝试将一个 .txt 文件复制到 /etc/shiny-server 目录中,请检查本地目录中的文件扩展名。 - Avinash Reddy
现在我正在使用一个稍微调整过的教程文件,并按照你的建议修改了Dockerfile,但似乎COPY命令无法正常工作。我在Dockerfile中定义了shiny用户,也在配置文件中定义了,但是一旦我将Dockerfile中的那行注释掉,日志就会再次显示“以root身份运行”的警告。你有什么想法吗? - Heysa12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接