docker容器内的R周期性函数调用



如https://yihui.org/en/2017/10/later-recursion/,可以使用later::later包指示R以定时延迟周期性地执行功能

作为一个最小的例子,考虑以下main.RDockerfile:

# main.R:
timer <- function() {
print("repeat after 3 seconds")
later::later(timer, 3)
}
timer()
# Dockerfile
FROM rocker/r-base:4.1.2
RUN R -e "install.packages('later')"
COPY / /
ENTRYPOINT ["Rscript", "main.R"]

使用docker build -t r-timer构建并使用docker run r-timer运行容器会使循环只执行一次,然后容器退出。终端输出:

$ docker run r-timer
[1] "repeat after 3 seconds"

$ docker ps -a
CONTAINER ID   IMAGE    COMMAND          CREATED             STATUS
aa1c33b39c2e   r-timer  "Rscript main.R" About a minute ago  Exited (0) About a minute ago             

我的问题:

  • 使用later::later是否意味着线程被挂起,这使得docker认为没有正在运行的进程,因此容器被停止
  • 如何保持容器运行并使R连续运行

编辑:

多亏了@danlooo,我学到了docker在容器完成主线程时杀死任何后台任务。我调整了Dockerfile以在主线程上执行UNIX睡眠,将Rscript线程推到后台。为了监控行为,我添加了log4r来将行打印到文件中,而不是使用print((。我仍然看到同样的行为:当访问容器并检查info.log时,它只包含一个执行ONE的条目。

library("log4r")
log_file <- "info.log"
log <- logger("INFO", appenders = file_appender(log_file))
info(log,"started logger")
timer <- function() {
info(log, "Repeat after 3 seconds")
later::later(timer, 3)
}
timer()
FROM rocker/r-base:4.1.2
RUN R -e "install.packages('later')"
RUN R -e "install.packages('log4r')"
COPY / /
CMD Rscript main.R & tail -f info.log

初始化过程结束后,Docker容器会自动关闭。如果later正在启动后台进程,它将在main.R刚刚完成时被终止。您可以在Dockerfile中使用CMD Rscript main.R && wait来等待所有后台进程。另一种方法是使用CMD exec /bin/bash -c "trap : TERM INT; Rscript main.R; sleep infinity & wait"防止容器完全停止

最新更新