如何通过docker并行安装R包?

3

我正在通过docker文件从CRAN安装几个R包。下面是我的docker文件:

FROM r-base:4.0.2
RUN apt-get update \
      && apt-get install -y --auto-remove \
      build-essential \
      libcurl4-openssl-dev \
      libpq-dev \
      libssl-dev \
      libxml2-dev \
      && R -e "system.time(install.packages(c('shiny', 'rmarkdown', 'Hmisc', 'rjson', 'caret','DBI', 'RPostgres','curl', 'httr', 'xml2', 'aws.s3'), repos='https://cloud.r-project.org/'))"
RUN mkdir /shinyapp
COPY . /shinyapp    
EXPOSE 5000
CMD ["R", "-e", "shiny::runApp('/shinyapp/src/shiny', port = 5000, host = '0.0.0.0')"]

Docker 构建过程花费的时间太长了(25 到 30 分钟)。以下是构建完成后的执行时间详细信息。

user   system  elapsed 
1306.268  232.438 1361.374 

有没有优化以上Dockerfile的方法?是否有一种并行安装软件包的方法?

注意:我也尝试了rocker/r-base,但在安装速度方面没有找到什么好运气。


或许以下内容对您有用:https://dev59.com/q63la4cB1Zd3GeqPHyEw ,以及这篇博客文章及其内部链接:http://dirk.eddelbuettel.com/blog/2020/08/26/#029_introducing_bspm - user20650
如果您使用单独的命令安装软件包,则安装进度会被缓存,下次开始时您可以从更改开始的那一行继续。这样,您就不必再次安装所有软件包了。 - janderkran
1个回答

4

‘pak’可以并行地下载和安装软件包。

不幸的是,当前CRAN版本的‘pak’(0.1.2.1)有大量依赖关系。相比之下,在GitHub上的开发版本没有外部依赖项,正如应该的那样。因此,我们需要安装开发版本。

因此,您可以按照以下方式更改Dockerfile:

…
 && Rscript -e "install.packages('pak', repos = 'https://r-lib.github.io/p/pak/dev/'); pak::pkg_install(c('shiny', 'rmarkdown', 'Hmisc', 'rjson', 'caret','DBI', 'RPostgres','curl', 'httr', 'xml2', 'aws.s3'))"

但是,老实说,那样写非常难懂。更好的做法是使用ARGENV来提供需要安装的软件包(无论是否使用'pak'来安装软件包):

FROM r-base:4.0.2

ARG PKGS="shiny, rmarkdown, Hmisc, rjson, caret, DBI, RPostgres, curl, httr, xml2, aws.s3"

RUN apt-get update \
 && apt-get install -y --auto-remove \
    build-essential \
    libcurl4-openssl-dev \
    libpq-dev \
    libssl-dev \
    libxml2-dev

RUN Rscript -e 'install.packages("pak", repos = "https://r-lib.github.io/p/pak/dev/")' \
 && echo "$PKGS" \
  | Rscript -e 'pak::pkg_install(strsplit(readLines("stdin"), ", ?")[[1L]])'

RUN mkdir /shinyapp
COPY . /shinyapp

EXPOSE 5000
CMD ["Rscript", "-e", "shiny::runApp('/shinyapp/src/shiny', port = 5000, host = '0.0.0.0')"]

同时请注意,对于脚本使用,不应该通过R二进制文件调用R - 这就是Rscript的作用。它可以更好地处理标准输出等其他事项。


1
是的,pak的CRAN版本存在问题,无法正确安装依赖项。在GitHub上的开发版对我来说运行得非常好。构建完成的时间缩短了10分钟。谢谢! - Prasad Deshmukh

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