vscode-dev-containers
vscode-dev-containers copied to clipboard
Support setting container time zone to host time zone
It might be good to support and/or document a first-class way to build dev containers that use the host machine's time zone instead of UTC.
While it's far from a showstopper, right now Git commits made inside a container are recorded in UTC. It's a bit odd to look at git log and see mixed time zones on my own commits depending on whether they came from GitHub (local time) or the dev container (UTC).
This also means I can't use git config log.date default-local to tell git log to print all times in local time (unless I also alias git='TZ=America/Toronto git').
Hard-coding a time zone into .devcontainer/Dockerfile should work for me, but probably isn't a great solution for larger projects.
Thanks for the suggestion! This should be doable by using the "initalizeCommand" property to get the local timezone into a file that is then pulled into the container via the Dockerfile (or even "postCreateCommand"). I'll look into documenting it.
Any update?
Also curious to see what's the most crossplatform way of doing this short of exposing a build arg to override the timezone.
I've worked around the problem with the following code snippets
In Dockerfile
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
&& apt-get install -y locales locales-all
In devcontainer
"containerEnv": {
"LC_ALL": "pt_BR.UTF-8",
"LANG": "pt_BR.UTF-8",
"LANGUAGE": "pt_BR.UTF-8"
},
Did that actually affect your time zone?
Those env vars are normally for "localization" (system language, date format style, decimal separator character, etc.), not for time zones.
Did that actually affect your time zone?
Those env vars are normally for "localization" (system language, date format style, decimal separator character, etc.), not for time zones.
You're right, this was to solve an encoding problem
This is an old issue, but to set the system time zone, do two things:
- Install the
tzdatapackage if its not already in your image. - Use
containerEnvin devcontainer.json to set theTZenvironment variable if you're using an image or Dockerfile- Or use your Docker Compose to set the env var for that scenario.
- Or if you prefer to have this set for everyone in your Dockerfile, use
ENV TZ="<timezone>"in the Dockerfile.
e.g.
"containerEnv": { "TZ": "America/Chicago" }
or in a Dockerfile
ENV TZ="America/Chicago"
Run ls /usr/share/zoneinfo to see available timezones.
What is not available is automatically setting this value based on the host's machine with no work.
Here's what I do, that works well for my use case:
In devcontainer.json, add a mount like this:
"type=bind,readonly,source=/etc/localtime,target=/etc/localtime",
Here's what I do, that works well for my use case:
In devcontainer.json, add a mount like this:
"type=bind,readonly,source=/etc/localtime,target=/etc/localtime",
This works for me on MacOS, but the actual behaviour is very unexpected!
/etc/localtime is a symbolic link both locally (to /var/db/timezone/zoneinfo/Europe/Zagreb) and in the dev container (/usr/share/zoneinfo/Etc/UTC).
The bind mount follows both symlinks, mounting /var/db/timezone/zoneinfo/Europe/Zagreb at /usr/share/zoneinfo/Etc/UTC:
$ zdump /usr/share/zoneinfo/Etc/UTC
/usr/share/zoneinfo/Etc/UTC Fri Dec 30 09:43:22 2022 CET
I'm not sure what other side effects this could have, but for MacOS and Linux users it might be a good enough workaround.
I tried the mount solution on MacOS, and while this worked for the date command on the shell, in Node.js Intl.DateTimeFormat().resolvedOptions().timeZone would still equal "UTC".
But, if I add the following line to the Dockerfile
RUN ln -sf /usr/share/zoneinfo/Australia/Sydney /etc/localtime
then Intl.DateTimeFormat().resolvedOptions().timeZone equals "Australia/Sydney"
Here's the workaround I'm using. In devcontainer.json add a TZ build arg that uses the local TZ and if not set a default. e.g.
"build": {
"dockerfile": "Dockerfile",
"args": { "TZ": "${localEnv:TZ:Australia/Sydney}" }
}
In the Dockerfile add the following lines
ARG TZ
ENV TZ="$TZ"
This will default the TZ to the specified default, but allow users to override it by setting the TZ env variable on the host machine.
From the container
node ➜ /workspaces/ArchitectureDoc (main) $ date
Wed 18 Jan 2023 09:58:56 AM AEDT
node ➜ /workspaces/ArchitectureDoc (main) $ node
Welcome to Node.js v16.19.0.
Type ".help" for more information.
> Intl.DateTimeFormat().resolvedOptions().timeZone
'Australia/Sydney'
>
For people who are still trying to figure this out, I combined this in the mounts section of the devcontainer.json:
"source=/etc/localtime,target=/usr/share/zoneinfo/hostlocaltime,type=bind,readonly"
with this in the Dockerfile:
RUN ln -sf /usr/share/zoneinfo/hostlocaltime /etc/localtime
The idea is that the mount follows the symbolic link on the host system, but maps it to a known location in the container with the other time zones. Then, you can create a symbolic link to the host time zone like you would to set it to any other timezone.