由于我在评论中推荐了它,我将在这里稍微正式化一下:Docker。事后看来,这个答案变成了比预期更多的教程/方法。我希望这不会令人生畏;这些步骤实际上非常简单,一旦你有可用的 docker,你可能只需要运行类似的东西:
$ docker run --rm -d -p 3838:3838 \
-v c:/Users/r2/R/win-library/4.0/shiny/examples/:/srv/shiny-server \
-v c:/Users/r2/shinylogs/:/var/log/shiny-server/ \
-v c:/Users/r2/R/otherlibrary/:/mylibrary/ \
rocker/shiny-verse:4.0.3
以下内容很少是 R 代码,它们都在 shell/终端中。我正在使用 git-bash 在 win10 上对其进行测试,但这应该可以在 macos 或 linux 上运行,只需很少的修改。
目录
- 如果未安装,请安装 docker。
- 拉出闪亮的服务器映像。
- 启动闪亮服务器容器(使用 app-dir 挂载)。
- 浏览到正在运行的应用程序。更新您的应用,更改会立即生效。
- 停止服务器(当天完成后)。
然后是日志的两个部分以及处理Other Packages的一些方法。
内容
-
如果不可用,请确保 docker 可用:
$ docker -v
Docker version 20.10.2, build 2291f61
如果没有找到,那么Get Docker 是安装它的最佳资源。
-
拉出一张可用的图片。我正在使用rocker/shiny-verse 进行演示,其中包括闪亮的和所有tidyverse 依赖项(图像大小为1.95GB),但也有rocker/shiny 稍小(1.56GB)。 (文档在第二个链接中更详细。)
我强烈建议使用特定版本而不是 :latest(或无版本),因为您可能需要密切模仿笔记本电脑上的开发环境。这个正在运行的容器不会使用你本地的 R,它有自己的。因此,您可能只在主机上安装了 R-3.6,并在容器中使用 R-4.0.3。使用您正在测试/开发的相同 (major.minor) 版本。
$ docker pull rocker/shiny-verse:4.0.3
Using default tag: latest
latest: Pulling from rocker/shiny-verse
a4a2a29f9ba4: Already exists
127c9761dcba: Already exists
d13bf203e905: Already exists
4039240d2e0b: Already exists
fffc4b622efe: Pull complete
c265253654a5: Pull complete
e0161c6ad391: Pull complete
8e7558fa9ec5: Pull complete
Digest: sha256:ce760db38a4712a581aa6653cf3a6562ddea9b48d781aad4f9582b8056401317
Status: Downloaded newer image for rocker/shiny-verse:4.0.3
docker.io/rocker/shiny-verse:4.0.3
-
确定要“挂载”的(主机)目录。我将使用与 R 的 shiny 包一起安装的示例,但您可以使用任何东西。有两种选择:
-
单一应用
Mount:应用目录本身,例如c:/Users/r2/R/win-library/4.0/shiny/examples/01_hello/
使用:http://localhost:3838/ 将运行该应用程序。
-
多个应用程序目录
Mount:包含其他应用程序目录的目录,例如,c:/Users/r2/R/win-library/4.0/shiny/examples/
使用:http://localhost:3838/ 将显示应用程序的目录,http://localhost:3838/01_hello/ 将运行第一个应用程序。
在您的情况下,您可能会选择/path/to/your/package/inst/ 之类的内容,然后选择上面的单应用选项。
根据rocker/shiny 的文档,我们将把它安装在/srv/shiny-server/。
$ docker run --rm -d -p 3838:3838 \
-v c:/Users/r2/R/win-library/4.0/shiny/examples/:/srv/shiny-server \
rocker/shiny-verse:4.0.3
ba4654d541ef39fb4882364446ece0b516e518baf946c21d1857565f05acd2c5
(仅供参考:-p 3838:3838 需要将服务器“暴露”在正在运行的闪亮服务器“容器”之外。第一个数字是您的计算机可见的,第二个数字必须保持 3838 并且是服务器的实际上是在内部运行。如果你不包括这个,你就不会看到它。)
-
将您的浏览器指向http://localhost:3838(或您在上面分配的任何端口),您应该会看到应用程序(如果是单个应用程序)或应用程序目录。
-
完成后,杀死(停止)容器:
$ docker stop exciting_gagarin
日志
有时您会想要/需要查看日志(例如,警告/错误)。有两种类型的日志:
-
服务器日志,可通过运行访问
docker logs -f exciting_gagarin
(Ctrl-C 停止日志,服务器继续运行。)
-
app 日志(每个会话)。为此,您可以跳入正在运行的容器并查看日志,但是当容器停止时,这些日志将被删除(因为 docker 容器内的文件默认为临时文件)......而这可能不方便。相反,您可以通过在docker run 命令中包含此卷挂载指令来将应用日志挂载到本地目录:
-v c:/Users/r2/shinylogs/:/var/log/shiny-server/
当应用程序正在运行并发生警告/错误时,您应该会看到如下文件:
$ ls -l c:/Users/r2/shinylogs/
total 5
-rw-r--r-- 1 r2 197121 112 Jan 8 08:38 shiny-server-shiny-20210108-133524-43293.log
-rw-r--r-- 1 r2 197121 237 Jan 8 08:53 shiny-server-shiny-20210108-135551-35903.log
-rw-r--r-- 1 r2 197121 271 Jan 8 08:54 shiny-server-shiny-20210108-135610-44445.log
-rw-r--r-- 1 r2 197121 271 Jan 8 08:54 shiny-server-shiny-20210108-135612-40369.log
-rw-r--r-- 1 r2 197121 145 Jan 8 08:57 shiny-server-shiny-20210108-140001-43857.log
其他包
您的包可能不包含在rocker/shiny 或rocker/shiny-verse 中。不要害怕!请遵循以下说明:
-
创建一个本地(不是容器内)目录,您将在其中安装这些缺失的软件包。我生成了一个单独的文件夹,因为主机操作系统可能与容器内操作系统(debian)不同,在这种情况下,包的格式可能不正确。我将使用c:/Users/r2/R/otherlibrary。我将不在主机操作系统“R”实例中使用此路径。
-
将卷挂载添加到您的命令中,使其在容器内可用:
-v c:/Users/r2/R/otherlibrary/:/mylibrary/
如果你有一个容器正在运行,你需要docker stop它,然后通过这个添加重新run它。
-
在您的应用中,添加
.libPaths( c("/mylibrary", .libPaths()) )
关于此的两件事:(1)R 需要在备用目录中查找; (2) 如果在主机上运行并且"/mylibrary" 不存在,这不会造成任何伤害。如果愿意,您可以选择包含条件 if (dir.exists("/mylibrary"))...。
-
安装额外的 CRAN 包。
我看到很多应用都是内置的,可以根据需要安装包,比如
if (!require("ggrepel")) install.packages("ggrepel")
这没有错(正确使用 require 与 library),但这不是我喜欢的做事方式。
另一种方法是手动安装这些所需的包,我们可以通过在容器中输入 R 并安装到适当的库路径来做到这一点。
$ docker exec -it exciting_gagarin R
R version 4.0.3 (2020-10-10) -- "Bunny-Wunnies Freak Out"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> .libPaths( c("/mylibrary", .libPaths()) )
> .libPaths()
[1] "/mylibrary" "/usr/local/lib/R/site-library"
[3] "/usr/local/lib/R/library"
> install.packages("ggrepel")
Installing package into ‘/mylibrary’
(as ‘lib’ is unspecified)
trying URL 'https://packagemanager.rstudio.com/all/__linux__/focal/latest/src/contrib/ggrepel_0.9.0.tar.gz'
Content type 'binary/octet-stream' length 980180 bytes (957 KB)
==================================================
downloaded 957 KB
* installing *binary* package ‘ggrepel’ ...
* DONE (ggrepel)
The downloaded source packages are in
‘/tmp/RtmpgPG8YS/downloaded_packages’
> q("no")
-
非 CRAN 软件包。我意识到您正在开发本地软件包。两个引用的镜像都包含devtools 包,因此通过额外的卷挂载,您可以使用devtools::install、devtools::load_all,或者如果您已经构建了源包,您可以使用install.packages("/mylibrary/mypackage.tar.gz")。
更多关于为什么可能需要不同包库的详细信息:编译代码。例如,当我在 Windows 上安装ggrepel(一个示例)时,其中的文件是
ggrepel/libs/i386/ggrepel.dll
ggrepel/libs/x64/ggrepel.dll
它们是特定于 Windows 操作系统的编译库。当我在 linux 上安装相同的包时,我没有这些库,而是看到了
ggrepel/libs/ggrepel.so
我为什么说linux?因为这些 rocker/shiny* 图像在后台运行 linux ......即使您的主机操作系统是 windows 或 macos。
文件格式不兼容,因此无法重命名。许多软件包可能开箱即用(尚未测试),但如果您尝试将 host-OS R 库路径安装到容器中并看到错误,请考虑此讨论。
docker注意事项
(如果你不熟悉。)
-
一般来说,正在运行的 docker 容器中的所有内容都是短暂的,这意味着当容器停止时,日志和保存的文件都会消失。解决这个问题的方法是像我们上面所做的那样使用卷挂载。在这种情况下,如果应用程序将文件保存到自己的目录中,那么您将在主机操作系统的/path/to/mypackage/inst/... 下看到它。
-
根据您的操作系统配置,这仅在本地主机上可见,因此可以是 http://localhost:3838 或 http://127.0.0.1:3838(它们并不总是相同,例如有时是 windows)。如果您需要将它暴露给您网络上的其他计算机......那么我建议您对此进行一些研究。在 docker 中运行服务器并将其暴露给网络的其余部分存在风险和后果。