rocker-org / rocker-versioned

Run current & prior versions of R using docker
https://hub.docker.com/r/rocker/r-ver
GNU General Public License v2.0
297 stars 169 forks source link

Problems with Sys.timezone() inside containers when timedatectl is present #89

Closed atheriel closed 4 years ago

atheriel commented 6 years ago

Attempting to check the timezone inside an R session in any image that also installs timedatectl surfaces a strange error:

$ Rscript -e "Sys.timezone()"
Failed to create bus connection: No such file or directory
[1] "Etc/UTC"
Warning message:
In system("timedatectl", intern = TRUE) :
  running command 'timedatectl' had status 1

This is due to the fact that R will check the output of timedatectl (and assume it has nonzero exit status) if it is present before looking elsewhere, and timedatectl is nonfunctional on docker.

As a workaround, I noticed that Sys.timezone() will check for the environment variable TZ first, so if you set that correctly in the image it'll prevent this issue from surfacing. E.g.

$ docker run -e TZ=Etc/UTC rocker/r-ver Rscript -e "Sys.timezone()"
[1] "Etc/UTC"

I thought I might suggest adding ENV TZ Etc/UTC to the images to solve this problem.

eddelbuettel commented 6 years ago

Hm, works for me (here using the r-base image corresponding to rocker/r-base):

edd@rob:~$ docker run --rm -ti r-base Rscript -e 'Sys.timezone()'
[1] "Etc/UTC"
edd@rob:~$ docker run --rm -ti r-base Rscript -e 'Sys.setenv("TZ"="America/Chicago"); Sys.timezone()'
[1] "America/Chicago"
edd@rob:~$
eddelbuettel commented 6 years ago

That said, getting TZ info can be a challenge. R wants either the TZ env var, or a symlink. Some systems do not this so I once wrote a package helping with this (cf https://github.com/eddelbuettel/gettz) but by now R itself has improved code for this.

On the margin I recommend setting a TZ. Now, I am not sure if there is a good default for us to pick.

atheriel commented 6 years ago

I don't think that the r-base image includes timedatectl. (You need to install systemd to get it.) Without that tool this behaviour won't show up at all -- it only did for me because we're using rocker/verse images as a base, and also include some other packages.

I'm also unsure of whether setting TZ is a good solution, but I wanted to post something in case anyone else runs into a similar issue.

cboettig commented 6 years ago

interesting, thanks for the heads up. yeah, maybe we should set an env var, at least in the verse stack for that. You're suggestion of "Etc/UTC" seems reasonable to me given that is what Sys.timezone() is reporting on the images prior to timedatactl being installed.

cboettig commented 6 years ago

@atheriel timedatectl isn't installed in rocker/verse (or any of the lower images), and so I see:

docker run --rm -ti rocker/verse R -e "Sys.timezone()"

> Sys.timezone()
[1] "Etc/UTC"

Are you using a custom image that installs systemd? Would it be better to set the env var at the time you install timedatactl / systemd ?

If I install systemd first, then I see:

> Sys.timezone() 
Failed to create bus connection: No such file or directory
[1] "Etc/UTC"
Warning message:
In system("timedatectl", intern = TRUE) :
  running command 'timedatectl' had status 1

(which timedatactl doesn't show anything either).

mjsteinbaugh commented 5 years ago

For reference, I fixed this issue on my images by setting TZ inside /usr/local/lib/R/etc/Renviron.site. Here's an example Dockerfile with this config.

cboettig commented 5 years ago

Thanks @mjsteinbaugh, that's good to know!

eddelbuettel commented 5 years ago

It is a combination of Debian being sticky and not defining TZ, and (older) R not looking everywhere. (I once wrote a package gettz to help.) Newer R is better -- for r-base ie 3.6.1 we have no TZ yet R now tries harder and gets there:

edd@rob:~$ docker run --rm -ti r-base bash -c "echo $TZ"

edd@rob:~$ docker run --rm -ti r-base Rscript -e 'Sys.getenv("TZ")'
[1] ""
edd@rob:~$
edd@rob:~$ docker run --rm -ti r-base Rscript -e 'Sys.timezone()'
[1] "Etc/UTC"
edd@rob:~$