.env
# 新增R版本 4.2.1
R_NAME_421=r_4_2_1 # 容器/镜像 名称
R_VERSION_421=4.2.1 # 版本号
R_PORT_421=8780
# 新增R版本 4.3.0
R_NAME_430=r_4_3_0
R_VERSION_430=4.3.0
R_PORT_430=8781
# 新增R版本 4.4.2
R_NAME_442=r_4_4_2
R_VERSION_442=4.4.2
R_PORT_442=8782
docker-compose.yml
# R 服务 4.2.1
r_4_2_1:
build:
context: .
dockerfile: ${R_DOCKERFILE} # dockerfile公共文件
args:
FROM_IMAGE: rocker/r-ver:${R_VERSION_421} # 指定镜像版本
R_BIOC_MIRROR: ${R_BIOC_MIRROR} # 公共 镜像源
R_CRAN: ${R_CRAN}
container_name: ${R_NAME_421} # 指定版本名称
image: ${R_NAME_421}-image # 指定镜像名称
ports:
- "${R_PORT_421}:${R_PORT_421}" # 指定端口
volumes:
- ./R:/workspace/R
- ./static/matrix:/workspace/static/matrix
- .env:/workspace/.env # 挂载 .env 文件
#- ./store/docker/r-library/${R_NAME_442}:/usr/local/lib/R/site-library # 持久化 R 包的安装位置
environment:
- R_HOME=/usr/local/lib/R
command: Rscript R/http/start.R # 启动API服务
restart: unless-stopped
networks:
- backend
# R 服务 4.3.0
r_4_3_0:
build:
context: .
dockerfile: ${R_DOCKERFILE} # dockerfile公共文件
args:
FROM_IMAGE: rocker/r-ver:${R_VERSION_430} # 指定镜像版本
R_BIOC_MIRROR: ${R_BIOC_MIRROR} # 公共 镜像源
R_CRAN: ${R_CRAN}
container_name: ${R_NAME_430} # 指定版本名称
image: ${R_NAME_430}-image # 指定镜像名称
ports:
- "${R_PORT_430}:${R_PORT_430}" # 指定端口
volumes:
- ./R:/workspace/R
- ./static/matrix:/workspace/static/matrix
- .env:/workspace/.env # 挂载 .env 文件
#- ./store/docker/r-library/${R_NAME_430}:/usr/local/lib/R/site-library # 持久化 R 包的安装位置
environment:
- R_HOME=/usr/local/lib/R
command: Rscript R/http/start.R # 启动API服务
restart: unless-stopped
networks:
- backend
# R 服务 4.4.2
r_4_4_2:
build:
context: .
dockerfile: ${R_DOCKERFILE} # dockerfile公共文件
args:
FROM_IMAGE: rocker/r-ver:${R_VERSION_442} # 指定镜像版本
R_BIOC_MIRROR: ${R_BIOC_MIRROR} # 公共 镜像源
R_CRAN: ${R_CRAN}
container_name: ${R_NAME_442} # 指定版本名称
image: ${R_NAME_442}-image # 指定镜像名称
ports:
- "${R_PORT_442}:${R_PORT_442}" # 指定端口
volumes:
- ./R:/workspace/R
- ./static/matrix:/workspace/static/matrix
- .env:/workspace/.env # 挂载 .env 文件
#- ./store/docker/r-library/${R_VERSION_442}:/usr/local/lib/R/site-library # 持久化 R 包的安装位置
environment:
- R_HOME=/usr/local/lib/R
command: Rscript R/http/start.R # 启动API服务
restart: unless-stopped
networks:
- backend
dockerfile
ARG FROM_IMAGE=rocker/r-ver:4.4.1
FROM ${FROM_IMAGE}
ARG R_BIOC_MIRROR=https://mirrors.tuna.tsinghua.edu.cn/bioconductor
ARG R_CRAN=https://mirrors.tuna.tsinghua.edu.cn/CRAN/
# 设置镜像源为清华大学的 CRAN 镜像和 Bioconductor 镜像
RUN echo "options(BioC_mirror = '${R_BIOC_MIRROR}')" >> /usr/local/lib/R/etc/Rprofile.site
RUN echo "options(repos = c(CRAN = '${R_CRAN}'))" >> /usr/local/lib/R/etc/Rprofile.site
## 安装系统依赖包
RUN sed -i 's|http://archive.ubuntu.com/ubuntu/|https://mirrors.tuna.tsinghua.edu.cn/ubuntu/|' /etc/apt/sources.list && \
apt-get update && \
apt-get install -y \
libcurl4-openssl-dev \
libssl-dev \
libxml2-dev \
libfontconfig1-dev \
libharfbuzz-dev \
libfribidi-dev \
libpango1.0-dev \
libx11-dev \
libxt-dev \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libbz2-dev \
libsodium-dev \
&& rm -rf /var/lib/apt/lists/* \
# 安装中文字体
RUN apt-get update && apt-get install -y fonts-wqy-zenhei fonts-wqy-microhei ttf-mscorefonts-installer fontconfig
# 查看系统中的中文字体:fc-list :lang=zh
# 报错:dpkg 进程被中断了; 修复:dpkg --configure -a
## 设定工作目录
WORKDIR /workspace
## 常用包安装脚本
COPY R/docker/install_packages.R /workspace/install_packages.R
# 验证文件是否被成功复制
RUN ls -l /workspace/install_packages.R
## 执行(耗时)
RUN Rscript /workspace/install_packages.R
## 设定工作目录
WORKDIR /workspace
#
## 保持容器在后台运行
CMD ["tail", "-f", "/dev/null"]
install_packages.R
# 安装常用的包
install.packages('pheatmap')
install.packages('BiocManager')
options(timeout = 600)
install_missing_packages <- function(packages) {
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
for (package in packages) {
if (!requireNamespace(package, quietly = TRUE)) {
cat(paste("开始安装", package, "...\n"))
BiocManager::install(package, ask = FALSE)
} else {
cat(paste( packageVersion(package), package, "已安装.\n" ))
}
}
}
# 安装常用的包
packages <- c('GEOquery', 'ggplot2', 'readxl', 'readr', 'openxlsx', 'dplyr',
'clusterProfiler', 'limma', 'DESeq2', 'ggtree', 'org.Hs.eg.db','org.Mm.eg.db','org.Rn.eg.db','GOplot','stringr',
'enrichplot', 'treeio', 'WGCNA', 'igraph','plumber','jsonlite','dotenv','remotes')
# 安装缺失的 R 包
install_missing_packages(packages)
# 针对某个版本中的某些包进行检测安装
r_version <- getRversion()
cat(paste("检测R版本", r_version , "...\n"))
if(r_version == "4.2.1"){
if (!requireNamespace("ggtree", quietly = TRUE)) {
remotes::install_github("YuLab-SMU/ggtree")
}
if (!requireNamespace("clusterProfiler", quietly = TRUE)) {
remotes::install_github("ctlab/fgsea")
BiocManager::install("clusterProfiler")
}
}
if(r_version == "4.3.0"){
if (!requireNamespace("ggtree", quietly = TRUE) && !requireNamespace("limma", quietly = TRUE) && !requireNamespace("org.Hs.eg.db", quietly = TRUE) ) {
options(BioC_mirror = "https://bioconductor.org")
install_missing_packages(packages)
}
if (!requireNamespace("ggtree", quietly = TRUE)) {
remotes::install_github("YuLab-SMU/ggtree")
}
if (!requireNamespace("clusterProfiler", quietly = TRUE)) {
remotes::install_github("ctlab/fgsea")
BiocManager::install("clusterProfiler")
}
}
如何在Python中使用R容器,执行R脚本?
- 搭建好后可以通过接口的方式运行R脚本
- 也可以使用py-docker操作容器(线上可能需要挂载docker守护进程)
接口服务
http.R
if (!requireNamespace("plumber", quietly = TRUE)) {
cat(paste("开始安装", "plumber", "...\n"))
BiocManager::install("plumber", ask = FALSE)
}
if (!requireNamespace("jsonlite", quietly = TRUE)) {
cat(paste("开始安装", "jsonlite", "...\n"))
BiocManager::install("jsonlite", ask = FALSE)
}
if (!requireNamespace("dotenv", quietly = TRUE)) {
cat(paste("开始安装", "dotenv", "...\n"))
BiocManager::install("dotenv", ask = FALSE)
}
cat("当前工作目录",getwd(),"\n")
# 加载 dotenv 包
library(dotenv)
library(plumber)
# 读取 .env 文件
load_dot_env(".env")
#print(Sys.getenv())
# 获取 R 版本号
r_version <- getRversion()
cat("R版本:", as.character(r_version), "\n")
# 将 R 版本号转换为 .env 文件中的键名格式 例如:4.2.1 -> 421
r_version_key <- gsub("\\.", "", as.character(r_version))
# 构建端口号的键名
port_key <- paste0("R_PORT_", r_version_key)
# 从 .env 文件中获取端口号
port <- as.integer(Sys.getenv(port_key))
if (is.na(port)) { # 如果端口号不存在,使用默认端口
port <- 8006 # 默认端口
warning("未找到当前R版本的端口配置(",port_key,") 使用默认端口:", port)
}else{
cat("找到当前 R 版本的端口配置:", port, "\n")
}
# 创建 plumber API
pr <- plumb("R/http/app.R")
# 启动 plumber 服务
pr$run(host = "0.0.0.0", port = port)
app.R
library(jsonlite)
# 定义一个 API 端点,执行 R 脚本
#* 执行 R 脚本
#* @post /run_r_script
function(req, script = "", param = "") {
# 调用执行脚本的函数
result <- run_script(script, param)
return(result)
}
#* 执行系统命令 post
#* @post /run_command
function(req, command = "") {
if (command == "") {
return(list(code = unbox(0),msg = unbox("未提供命令") ))
}
# 执行系统命令
result <- tryCatch({
output <- system(command, intern = TRUE)
list(code = unbox(1), msg = unbox("命令执行成功"), data = output)
}, error = function(e) {
list(code = unbox(0), msg = unbox(e$message) )
})
return(result)
}
# 执行 R 脚本的函数
run_script <- function(script_path, params) {
setwd("/workspace")
# 检查脚本文件是否存在
if (!file.exists(script_path)) {
return( list(
code = unbox(0),
msg = unbox("脚本文件不存在"),
data = getwd()
))
}
# 将参数转换为 R 对象
#params <- jsonlite::fromJSON(params)
# 构造命令行
command <- paste("Rscript", script_path, shQuote(params))
# 在独立环境中执行脚本
result <- tryCatch({
#run_result <- source(script_path) # 执行结果
run_result <- system(command, intern = TRUE)
print(run_result)
# 获取退出状态
exit_status <- attr(run_result, "status")
exit_status <- ifelse(is.null(exit_status), 0, exit_status)
print(cat("退出状态:",exit_status,"\n"))
if(exit_status == 1){
# 将 run_result 转换为字符串
result_string <- paste(run_result, collapse = "\n")
#print(result_string)
list(
code = unbox(0), # 使用 unbox() 将 code 转换为标量值
msg = unbox(result_string),
data = run_result, # 捕获的输出
output = params
)
}else{
#run_result <- capture.output(source(script_path))
list(
code = unbox(1), # 使用 unbox() 将 code 转换为标量值
msg = unbox("脚本执行成功"),
data = run_result, # 捕获的输出
output = params
)
}
}, error = function(e) {
print(e)
list(
code = unbox(0),
msg = unbox("脚本执行失败"),
data = NULL,
output = unbox(e$message)
)
})
return(result)
}
评论 (0)