R periodic function call inside docker container

Viewed 112

As described by https://yihui.org/en/2017/10/later-recursion/, It is possible to instruct R to execute a function periodically with a timed delay using the later::later package

As a minimal example, consider following main.R and Dockerfile:

# 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"]

build with docker build -t r-timer and running the container with docker run r-timer makes the loop execute exactly once, after which the container exits. terminal output:

$ 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             

my questions:

  • Does using later::later mean the thread is suspended, which makes docker believe there is no running process and the container is thus stopped?
  • How can I keep the container running and make R run continuously?

EDIT:

Thanks to @danlooo I learned about docker killing any background tasks when the container finishes the main thread. I adapted the Dockerfile to do a UNIX sleep on the main thread, pushing the Rscript thread to the background. To monitor the behaviour I added log4r to print lines to a file rather than using print(). I'm still seeing the same behaviour: when accessing the container and checking info.log, it only contains an entry for ONE execution.

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
1 Answers

Docker container automatically shut down once the init process finished. If later is spinning up a background process, it will be killed when main.R just finished. You can use CMD Rscript main.R && wait in your Dockerfile to wait for all background processes. Another approach is to prevent the container from stopping at all using CMD exec /bin/bash -c "trap : TERM INT; Rscript main.R; sleep infinity & wait"

Related