为什么以及如何在日常R工作流程中使用Docker?
痛苦之源
- 作为数据科学家,我们在处理生产级代码库时面临的最大挑战之一是确保端到端的可重复性和长期的稳定性。
- 这也会延伸到学术界,但我不是一个学术界人士。
- 一个基本的R设置没有内置的功能来存储软件包的版本和依赖关系(例如,不像在conda环境中运行)。
- 如果你的默认仓库是CRAN,这就是一个大问题,因为CRAN每天都会更新。
- 我发现一些解决方案,如pkgdown,使用起来太麻烦了。我甚至尝试过在为R设置的conda环境中工作,但我并不喜欢。
- 数据科学家之间的团队合作又增加了一层复杂性。根据我的经验。
- 一个团队中的人可以有不同版本的东西--操作系统、R内核、软件包、库、环境变量......!
- 一些人在升级他们的系统时很保守;另一些人则很想尝试新版本的软件包。
- 跨操作系统工作往往会带来意想不到的问题(IME,特别是允许并行计算的函数mcapply,未来。
- 当在本地系统(可能是Windows)上开发代码库,但在另一个环境(可能是Linux)上部署代码库时,这就成了问题。
解决方案
根据我的经验,我在下面概述的解决方案为我提供了一个长期可重复性和代码稳定性的绝佳方法。
- 使用MRAN快照锁定你的R包版本
- 使用Docker镜像锁定你的工作环境
- 在Docker容器中进行所有的开发
- 用Docker镜像陪伴所有项目
这样做的效果非常好,以至于我已经半年多没有在我的本地机器上使用R/Rstudio了。
1.MRAN时间机器
微软R应用网络(MRAN)提供了一个 "时间机器"。这项服务每天对CRAN资源库进行快照--最早可以追溯到2014年9月。你可以在他们的页面上浏览这些快照。
MRAN网站的屏幕截图。来自作者。
MRAN快照帮助我们用一个日期作为 "索引 "来锁定软件包的版本。例如,运行:
install.packages("lattice",
将安装2020年10月1日的{lattice}版本。
现在,这种方法并没有让你更容易选择_随时间发布的_软件包的_特定版本_,而是允许你锁定一个日期,并只获得那些在选定日期可用的版本。这意味着,在10月1日之后的任何日期运行 "更新软件包 "都不会改变你的软件包配置。
> options(repos = "https://mran.microsoft.com/snapshot/2020-10-01")
2.Docker镜像
Docker文件
Dockerfile包含了如何构建Docker镜像的定义。我用来维护这个博客的Dockerfile就保存在这里。它也被托管在hub.docker.com上。
下面是对该文件的快速解释。如果想更深入地了解Dockerfile,网上有很多资源1、2、3。
从
我正在使用rocker/tidyverse:4.0.0镜像,它提供了一个很好的起点。它预装了R4.0.0版本和tidyverse软件包。
FROM rocker/tidyverse:4.0.0
RUN
这将安装许多Linux库,这些库是后续R包工作所需的。我还安装了一些有用的工具包,如curl、jq和vim。
RUN apt-get update && apt-get install -y --no-install-recommends \
env + r pkg install
在这里,我设置了MRAN构建日期,然后使用install2.r安装我需要的R包,其中-r参数指向MRAN Time Machine而不是CRAN。
ENV MRAN_BUILD_DATE=2020-09-01
# Install Basic Utility R Packages
构建和推送
构建docker镜像并将其推送到hub.docker.com。
docker build . -t hatmatrix/blog:latest
你的docker镜像现在可以在线使用,供运行你的项目的人使用。
3.在Docker中开发
现在我有一个稳定的docker镜像,可以用于这个博客。我可以用这个shell cmd来运行这个镜像。
docker run
这个命令的组成部分是:
- docker run :运行一个docker镜像...
- -d : 在分离模式下,也就是说,一旦镜像在后台运行,你就会得到你的shell提示
- -e PASSWORD=1234 : -e是附加参数。这里,我们将Rstudio的密码设置为1234
- -v : 这将我本地机器上的~/github/映射到docker容器中的~/home/rstudio/projects/。
- -p : 这些参数将我本地机器上的端口映射到docker中的端口。我们需要一个用于rstudio(8787),一个用于我们从rstudio中启动的任何闪亮的应用(3838)。
- hatmatrix/blog:latest : 这是docker镜像的名称。
-v的重要性没有-v,你就无法访问docker容器中的任何本地文件。记住,docker容器是与你的本地机器完全隔离的。此外,由于容器是短暂的(即短暂的和临时的),一旦容器关闭,你将永久地失去存储在其中的任何数据。映射到本地文件夹允许你在容器内的本地存储项目上工作。
4.Docker镜像伴随R项目
只要在你的工作项目目录中创建一个/docker文件夹,并保存你的Docker文件。这是我在这篇博客中的例子:例子docker文件夹。可以选择创建一个docker-build.sh,以节省一些输入的时间。
就这样吧!
这是一个轻量级的工作流程,使我无论在哪个操作系统上工作,都能保持完全的可重复性和代码的稳定性。