如何减少安装 R 库的 Docker 容器的构建时间?
Posted
技术标签:
【中文标题】如何减少安装 R 库的 Docker 容器的构建时间?【英文标题】:How to reduce build time for a Docker container installing R libraries? 【发布时间】:2021-10-13 16:51:24 【问题描述】:我需要在 Docker 容器中运行一些同时包含 Python 3.8 和 R 4.1.0 的代码。下面是我的 Dockerfile。
FROM python:3.8-slim-buster AS final-image
# R version to install
ARG R_BASE_VERSION=4.1.0
ARG PREBUILD_DEPS="software-properties-common gnupg2"
ARG BUILD_DEPS="build-essential binutils cmake gfortran libblas-dev liblapack-dev libjpeg-dev libpng-dev libnlopt-dev pkg-config"
ARG RUNTIME_DEPS="r-base=$R_BASE_VERSION-* libcurl4-openssl-dev libssl-dev libxml2-dev"
# venv path
ENV PATH="/opt/venv/bin:$PATH"
RUN apt-get update \
# Adding this to install latest versions of g++
&& echo 'deb http://deb.debian.org/debian testing main' > /etc/apt/sources.list.d/testing.list \
# Install the below packages to add repo which is then used to install R version 4
&& apt-get install -y --no-install-recommends $PREBUILD_DEPS \
&& add-apt-repository 'deb http://cloud.r-project.org/bin/linux/debian buster-cran40/'\
# This key is required to install r-base version 4
&& apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key FCAE2A0E115C3D8A \
# Update again to use the newly added sources
&& apt-get update \
&& apt-get install -y --no-install-recommends $RUNTIME_DEPS $BUILD_DEPS \
&& python -m venv /opt/venv \
&& /opt/venv/bin/python -m pip install --upgrade pip \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt packages.R /
RUN pip install wheel setuptools \
&& pip install --no-cache-dir -r requirements.txt \
&& pip install --no-cache-dir --no-binary xgboost xgboost \
&& Rscript packages.R \
&& strip --strip-unneeded usr/local/lib/R/site-library/Boom/lib/libboom.a \
&& strip --strip-debug /usr/local/lib/R/site-library/*/libs/*so \
# Uninstall unnecessary dependencies
&& rm -rf /tmp/* \
&& apt-get purge -y --auto-remove $BUILD_DEPS $PREBUILD_DEPS \
&& apt-get autoremove -y \
&& apt-get autoclean -y \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT XXX
这是packages.R
文件:
#Setting environment
rm(list = ls())
cat("\014")
print(Sys.time())
# CRAN mirror to use. cran.rstudio.com is a CDN and the recommended mirror.
# Specifying multiple backup CRAN mirrors as Jenkins builds fails
# intermittently due to unavailability of packages in main mirror.
cran_repos = c(MAIN_CRAN_MIRROR = 'https://cran.rstudio.com',
ALT_CRAN_MIRROR = 'http://cran.r-project.org/')
#Loading Libraries
package_ls <- c(
"config",
"crayon",
"aws.s3",
"aws.ec2metadata",
"dplyr",
"data.table",
"imputeTS",
"Metrics",
"StatMeasures",
"tseries",
"purrr",
"log4r",
"lubridate",
"forecast",
"caret",
"MASS",
"stringr",
"tidyr",
"uroot",
"readr",
"Boruta",
"bsts"
)
for (pkg_name in package_ls)
message("Installing ", pkg_name)
install.packages(pkg_name, repos = cran_repos)
if (!(pkg_name %in% installed.packages()[, 'Package']))
stop(pkg_name,
" is a required package and it could not be installed, stopping!")
问题
构建 docker 容器花费的时间比我想的要多得多。这是因为,一些包(例如bsts)需要从源代码构建它们的依赖项(例如the C++ library Boom),这需要很多时间。 有没有办法:
-
加快 R 库的构建?或
在本地构建 R 库并仅将二进制文件复制到 Docker 容器。或
以任何其他方式减少 R 包的构建时间。
提前致谢。
更新
来自 cmets 的一些想法:
@botje
-
使用
install.packages
R function 的Ncpus
参数并行安装R 包。 (我有 4 个 CPU 可以使用,设置 Ncpus = 4
可以提高 10% 的速度。)
install.packages(package_ls, repos = cran_repos, Ncpus = 4)
-
创建包含本地编译包的自定义 CRAN 镜像,以加快安装速度。
【问题讨论】:
这和c++有什么关系? 许多安装时间最长的 r 库正在编译它们的依赖项,这些依赖项是用 c++ 编写的。例如。在此处查看 Boom 包:github.com/steve-the-bayesian/BOOM 你多久重建一次这个容器镜像?您的 R 依赖项更改更频繁,还是您的 Python 依赖项更改更频繁?是否可以选择并行构建 R 包? 显然有一个 install.packages 命令,如果Ncpu > 1
将并行安装。或者,您可以创建一个自定义 CRAN 镜像,其中还包含本地编译的二进制包以加快安装速度。
@santhisenan 我的意思是建议您致电install.packages
并提供完整的软件包列表,这样您的所有内核都将处于忙碌状态。我认为这应该会带来 2 倍或 3 倍的加速。你目前的方法仍然是串行安装包,所以你对最大的包只有一点并行优势
【参考方案1】:
我把你packages.R
的最后一段改写如下:
install.packages(package_ls, Ncpus=16)
与使用Ncpus=1
(189s 与 719s)相比,这使我的速度提高了 3 倍。
【讨论】:
对于延迟确认表示歉意。我能够确认 Ncpus 选项将安装时间减少 2-3 倍。以上是关于如何减少安装 R 库的 Docker 容器的构建时间?的主要内容,如果未能解决你的问题,请参考以下文章