【问题标题】:Install R packages using docker file使用 docker 文件安装 R 包
【发布时间】:2017-12-30 13:56:44
【问题描述】:

我已经在我的 docker 文件中使用以下行安装了 R。请建议我现在如何指定要安装在我的 docker 文件中的软件包。

RUN yum -y install R-core R-devel

我正在做这样的事情:

RUN R -e "install.packages('methods',dependencies=TRUE, repos='http://cran.rstudio.com/')"\
    && R -e "install.packages('jsonlite',dependencies=TRUE, repos='http://cran.rstudio.com/')" \
    && R -e "install.packages('tseries',dependencies=TRUE, repos='http://cran.rstudio.com/')" 

这是正确的做法吗?

【问题讨论】:

  • 可能的相关帖子:stackoverflow.com/questions/6907937/…
  • 您提供的链接根本与 dockerfile 无关。如果你有任何想法,你能建议我怎么做吗?
  • 是否可以从 shell 提示符运行命令或通过 Docker 运行 R 脚本?该帖子提供了多种安装软件包的替代方法——我认为其中一种可能适用于您的情况,即使没有特别提到 docker。
  • R 在这种情况下不会返回失败代码,例如,如果您要求一个不可用的包)——这意味着您最终会忽略构建失败。 install.packages 不返回 NULL 以外的任何内容...可能您想要执行 install.packages(...) 后跟匹配 library(...) 并在 library(...) 失败时退出。

标签: r docker dockerfile yum install.packages


【解决方案1】:

您可以使用所需的安装命令编写一个 R 脚本,然后使用 Docker 运行它——如果我没有正确阅读此文档 (https://hub.docker.com/_/r-base/)。

FROM r-base
COPY . /usr/local/src/myscripts
WORKDIR /usr/local/src/myscripts
CMD ["Rscript", "myscript.R"]

Build your image with the command:

$ docker build -t myscript /path/to/Dockerfile

myscript.R 包含相应的软件包安装命令。

【讨论】:

  • 无法运行 R 脚本。
  • 我正在做这样的事情: RUN R -e "install.packages('methods',dependencies=TRUE, repos='cran.rstudio.com/')"\ && R -e "install.packages ('jsonlite',dependencies=TRUE, repos='cran.rstudio.com/')" \ && R -e "install.packages('tseries',dependencies=TRUE, repos='cran.rstudio.com/')"
  • 我对 Docker 不是很熟悉,但文档似乎建议使用 CMD ["Rscript", "myscript.R"],其中 myscript 包含安装命令,而不是 RUN R -e 将安装命令作为命令的参数行
【解决方案2】:

是的,您的解决方案应该有效。我遇到了同样的问题,在这里https://github.com/glamp/r-docker/blob/master/Dockerfile找到了解决方案。

简而言之,使用:RUN Rscript -e "install.packages('PACKAGENAME')"。我试过了,效果很好。

正如其他人在 cmets 中提到的,如果无法安装软件包,此解决方案不会引发错误。

【讨论】:

  • 不幸的是,当 install.packages 失败时,这不会导致 Docker 构建失败。
  • @CameronKerr 是正确的,Rscript -e "install.packages('devtoolsssss')" || echo FAIL 不会回显 FAIL,因此这不会返回所需的非零退出代码。
【解决方案3】:

正如@Cameron Kerr 的评论所建议的,Rscript 不会让您构建失败。 到目前为止,推荐的方法是按照问题的建议进行操作。

RUN R -e "install.packages('methods',dependencies=TRUE, repos='http://cran.rstudio.com/')"
RUN R -e "install.packages('jsonlite',dependencies=TRUE, repos='http://cran.rstudio.com/')"
RUN R -e "install.packages('tseries',dependencies=TRUE, repos='http://cran.rstudio.com/')" 

如果您相当确定没有包失败,请使用此单线 -

RUN R -e "install.packages(c('methods', 'jsonlite', 'tseries'),
                           dependencies=TRUE, 
                           repos='http://cran.rstudio.com/')"

编辑:如果您不使用 Base-R 图像,您可以使用 rocker-orgr-verr-studiotidyverse 图像。这是repo。这是一个示例 Dockerfile -

FROM rocker/tidyverse:latest

# Install R packages
RUN install2.r --error \
    methods \
    jsonlite \
    tseries

--error 标志是可选的,如果包安装失败,它会使install.packages() 抛出错误(这将导致docker build 命令失败)。默认情况下,install.packages() 只抛出一个警告,这意味着即使安装包失败,Dockerfile 也可以构建成功。

所有rocker-org 基本上都是installs littler 包,用于install2.R 功能

【讨论】:

  • 在我的 .gitlab-ci.yml 中很有用
【解决方案4】:

R -e "install.packages..." 方法在包安装失败时并不总是产生错误。

我根据Cameron Kerr的回答here写了一个脚本,如果无法加载包会产生错误,并中断Docker构建过程。它从 R 包存储库、GitHub 或给定完整 URL 的源安装包。它还会打印安装时间,以帮助计划在一个命令中将哪些包组合在一起。

Dockerfile 中的使用示例:

# Install from CRAN repo:
RUN Rscript install_packages_or_die.R https://cran.rstudio.com/ Cairo
RUN Rscript install_packages_or_die.R Cairo # Uses default CRAN repo
RUN Rscript install_packages_or_die.R jpeg png tiff # Multiple packages

# Install from GitHub:
RUN Rscript install_packages_or_die.R github ramnathv/htmlwidgets
RUN Rscript install_packages_or_die.R github timelyportfolio/htmlwidgets_spin spin

# Install from source given full URL of package:
RUN Rscript install_packages_or_die.R https://cran.r-project.org/src/contrib/Archive/curl/curl_4.0.tar.gz curl

这是脚本:

#!/usr/bin/env Rscript

# Install R packages or fail with error.
#
# Arguments:
#   - First argument (optional) can be one of:
#       1. repo URL
#       2. "github" if installing from GitHub repo (requires that package 'devtools' is
#          already installed)
#       3. full URL of package from which to install from source; if used, provide package
#          name in second argument (e.g. 'curl')
#     If this argument is omitted, the default repo https://cran.rstudio.com/ is used.
#   - Remaining arguments are either:
#       1. one or more R package names, or
#       2. if installing from GitHub, the path containing username and repo name, e.g.
#          'timelyportfolio/htmlwidgets_spin', optionally followed by the package name (if
#          it differs from the GitHub repo name, e.g. 'spin').

arg_list = commandArgs(trailingOnly=TRUE)

if (length(arg_list) < 1) {
  print("ERROR: Too few arguments.")
  quit(status=1, save='no')
}

if (arg_list[1] == 'github' || grepl("^https?://", arg_list[1], perl=TRUE)) {
  if (length(arg_list) == 1) {
    print("ERROR: No package name provided.")
    quit(status=1, save='no')
  }
  repo = arg_list[1]
  packages = arg_list[-1]
} else {
  repo = 'https://cran.rstudio.com/'
  packages = arg_list
}

for(i in seq_along(packages)){
    p = packages[i]

    start_time <- Sys.time()
    if (grepl("^https?://[A-Za-z0-9.-]+/.+\\.tar\\.gz$", repo, perl=TRUE)) {
      # If 'repo' is URL with path after domain name, treat it as full path to a package
      # to be installed from source.
      install.packages(repo, repo=NULL, type="source");
    } else if (repo == "github") {
      # Install from GitHub.
      github_path = p
      elems = strsplit(github_path, '/')
      if (lengths(elems) != 2) {
        print("ERROR: Invalid GitHub path.")
        quit(status=1, save='no')
      }
      username = elems[[1]][1]
      github_repo_name = elems[[1]][2]
      if (!is.na(packages[i+1])) {
        # Optional additional argument was given specifying the R package name.
        p = packages[i+1]
      } else {
        # Assume R package name is the same as GitHub repo name.
        p = github_repo_name
      }

      library(devtools)
      install_github(github_path)
    } else {
      # Install from R package repository.
      install.packages(p, dependencies=TRUE, repos=repo);
    }
    end_time <- Sys.time()

    if ( ! library(p, character.only=TRUE, logical.return=TRUE) ) {
      quit(status=1, save='no')
    } else {
      cat(paste0("Time to install ", p, ":\n"))
      print(end_time - start_time)
    }

    if (repo == "github") {
      break
    }
}

【讨论】:

    【解决方案5】:

    这很难看,但它确实有效 - 请参阅下面的真实示例,了解为什么值得这样做。

    # install packages and check installation success, install.packages itself does not report fails
    RUN R -e "install.packages('RMySQL');     if (!library(RMySQL, logical.return=T)) quit(status=10)" \
     && R -e "install.packages('devtools');   if (!library(devtools, logical.return=T)) quit(status=10)" \
     && R -e "install.packages('data.table'); if (!library(data.table, logical.return=T)) quit(status=10)" \
     && R -e "install.packages('purrr');      if (!library(purrr, logical.return=T)) quit(status=10)" \
     && R -e "install.packages('tidyr');      if (!library(tidyr, logical.return=T)) quit(status=10)"
    

    真实世界示例:devtools 安装开始失败,因为它突然需要 libgit2-devinstall.packages() 打印信息丰富的信息。关于失败,但没有非零退出代码,它只是随着 docker build 的继续而滚动。

    【讨论】:

      【解决方案6】:

      我想推荐rocker/tidyverse 镜像,在上面你可以安装其他包,像这样:

      RUN R -e "install.packages('bigrquery',dependencies=TRUE, repos='http://cran.rstudio.com/')"

      从 r-base 进行相同的安装之后,Rserve 出现问题,该问题可能已预安装在 r-base 映像中。我在关于 r-base 的页面上没有找到任何关于此的内容,因此我不建议将 r-base 作为简单的解决方案。

      R 包的安装也可以使用apt-get install r-cran-* 来完成,但是rocker/tidyverse 的维护者不建议为这个特定的镜像安装它,因为这会导致安装另一个R 版本。但是,您可以检查一下,发现它适合您的任务。

      【讨论】:

      • 是否可以指定多个repos来查找?
      【解决方案7】:

      这些存储库是解决这个问题的方法吗?

      我在这个存储库中的解决方案是创建两个 Docker 映像: “安装映像”:第一个映像仅包含项目的先决条件。当从这个镜像运行一个容器时,它可以在容器内以它需要的格式安装 R 包,并通过挂载将它们保存到主机上 {renv} 的缓存中。 “最终映像”:第二个映像将项目连同依赖项从主机复制到映像中。

      【讨论】:

        【解决方案8】:

        我找到的最佳解决方案是使用 litter 包中的 install2.r

        • 首先安装垃圾
        RUN R -e "install.packages('litter', dependencies=TRUE)"
        
        • 然后您可以在 Dockerfile 中通过 bash 使用它
        RUN install2.r --error --deps TRUE methods
        RUN install2.r --error --deps TRUE jsonlite
        RUN install2.r --error --deps TRUE tseries
        

        如果软件包没有正确安装,--error 标志会使构建退出。 --deps TRUE 标志用于自动安装包的依赖项

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-30
          • 1970-01-01
          • 1970-01-01
          • 2020-02-14
          • 2020-07-31
          • 2017-09-16
          相关资源
          最近更新 更多